ducu Postat Iulie 1, 2010 Partajează Postat Iulie 1, 2010 Salut, am facut de curand un test cu acest microcontroler[pic16f887] lcd[2x16] si senzor[18s20] de temperatura, totul functioneaza ireprosabil, mai putin afisarea simbolului "-" [minus] cand detecteaza temperaturi negative. Mentionez ca testul a constat in simulare [Proteus] si fizic pe o placa breadboard.Concluzia?!, acelasi rezultat. Nu reusesc sa imi dau seama ce nu e in regula. Limbajul folosit este mikroC. Puteti sa imi dati o mana de ajutor in aceasta privinta? Programul: //TERMOMETRU ELECTRONIC CU PIC16F887 LCD 2X16 SI SENZOR DE TEMPERATURA DS18S20 // declara conexiunea lcd sbit LCD_RS at RB4_bit; sbit LCD_EN at RB5_bit; sbit LCD_D4 at RB0_bit; sbit LCD_D5 at RB1_bit; sbit LCD_D6 at RB2_bit; sbit LCD_D7 at RB3_bit; sbit LCD_RS_Direction at TRISB4_bit; sbit LCD_EN_Direction at TRISB5_bit; sbit LCD_D4_Direction at TRISB0_bit; sbit LCD_D5_Direction at TRISB1_bit; sbit LCD_D6_Direction at TRISB2_bit; sbit LCD_D7_Direction at TRISB3_bit; // sfarsit de declaratie const unsigned short TEMP_RESOLUTION = 9; char *text = "000.0000"; unsigned temp; void Display_Temperature(unsigned int temp2write) { const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8; char temp_whole; unsigned int temp_fraction; // verificare pentru temperaturi negative if (temp2write & 0x8000) { text[0] = '-'; temp2write = ~temp2write + 1; } // extrage temp_whole temp_whole = temp2write >> RES_SHIFT ; // converteste temp_whole in caractere if (temp_whole/100) text[0] = temp_whole/100 + 48; else text[0] = '0'; text[1] = (temp_whole/10)%10 + 48; // extrage zecimi text[2] = temp_whole%10 + 48; // extrage unitati // extrage temp_fraction si converteste in unsigned int temp_fraction = temp2write << (4-RES_SHIFT); temp_fraction &= 0x000F; temp_fraction *= 625; // converteste temp_fraction in caractere text[4] = temp_fraction/1000 + 48; // extrage miile text[5] = (temp_fraction/100)%10 + 48; // extrage sutele text[6] = (temp_fraction/10)%10 + 48; // extrage zecile text[7] = temp_fraction%10 + 48; // extrage unitatile // afisare temp. pe LCD Lcd_Out(2, 5, text); } void main() { ANSEL = 0; // Configureaza pinii AN ca i/o digitali ANSELH = 0; C1ON_bit = 0; // comparator dezactivat C2ON_bit = 0; Lcd_Init(); // Initializeaza LCD Lcd_Cmd(_LCD_CLEAR); // curata LCD Lcd_Cmd(_LCD_CURSOR_OFF); // cursor off Lcd_Out(1, 1, " Temperatura: "); // aviseaza caracterul, 'C' pentru grade Celsius Lcd_Chr(2,13,223); // char code pentru lcd 178 sau 223 [afiseaza grade] Lcd_Chr(2,14,'C'); //--- bucla principala do { //--- citire temperatura Ow_Reset(&PORTE, 2); // Onewire semnal de reset Ow_Write(&PORTE, 2, 0xCC); // comanda SKIP_ROM Ow_Write(&PORTE, 2, 0x44); // comanda CONVERT_T Delay_us(120); Ow_Reset(&PORTE, 2); Ow_Write(&PORTE, 2, 0xCC); // comanda SKIP_ROM Ow_Write(&PORTE, 2, 0xBE); // comanda READ_SCRATCHPAD temp = Ow_Read(&PORTE, 2); temp = (Ow_Read(&PORTE, 2) << 8) + temp; //--- formati si afisare pe lcd Display_Temperature(temp); Delay_ms(500); } while (1); } Rezultatul: Link spre comentariu
A_L_E_X Postat Iulie 1, 2010 Partajează Postat Iulie 1, 2010 Variabila temp trebuie sa fie signed. Link spre comentariu
Liviu M Postat Iulie 2, 2010 Partajează Postat Iulie 2, 2010 Eu cred ca suprascrii "-" din text[0] cand convertesti in caractere. // verificare pentru temperaturi negativeif (temp2write & 0x8000) {text[0] = '-';temp2write = ~temp2write + 1;} // converteste temp_whole in caractereif (temp_whole/100)text[0] = temp_whole/100 + 48;elsetext[0] = '0'; Link spre comentariu
ducu Postat Iulie 2, 2010 Autor Partajează Postat Iulie 2, 2010 Multumesc pentru promptitudine, am testat ambele variante de raspuns, nici un rezultat.Daca incerc://temp[0] = '0' ;ramane constant pe minus. Link spre comentariu
Liviu M Postat Iulie 2, 2010 Partajează Postat Iulie 2, 2010 Pai e normal. Ar trebui o locatie independenta la inceputul textului in care sa scrii sau nu '-'. O varianta ar fi sa "lungesti" text[] cu un caracter, semnul, pentru care o sa afisezi '-' sau ' '/'': // verificare pentru temperaturi negativeif (temp2write & 0x8000) { text[0] = '-'; temp2write = ~temp2write + 1;}else text[0] = ' '; //blank sau nimic Pentru afisatul numarului, incepi cu text[1] pentru sute (aduni o unitate la indexul afisarii numarului). O alta varianta ar fi sa scrii direct semnul inainte de restul numarului si sa lasi afisarea numarului asa cum e: // verificare pentru temperaturi negativeif (temp2write & 0x8000) { Lcd_Out(2, 4, '-'); temp2write = ~temp2write + 1;}else Lcd_Out(2, 4, ' '); In functie de cum e definitn Lcd_Out(), sunt sanse sa trebuiasca sa scrii - sub forma de sir: Lcd_Out(2, 4, "-"); Link spre comentariu
ducu Postat Iulie 2, 2010 Autor Partajează Postat Iulie 2, 2010 Multumesc Liviu M pentru asistenta, am incercat ce ai spus, functioneaza pe jumatate ambele variante, temperatura negativa este afisata dar cand vin pe temperatura pozitiva ramane blocat pe 8 grade celsius, indiferent de caracterul ales pentru + si -. din variantele tale am observat ca ai scos: temp_whole = temp2write >> RES_SHIFT; // convert temp_whole to characters if (temp_whole/100) // 48 is the decimal character code value for displaying 0 on LCD temp[0] = temp_whole/100 + 48; __________________________________________________________ aici e problema zic eu pentru ca daca aduc un delay_ms(1000) la declaratiile scoase de tine din program observ cum oscileaza intre simbolul "-" si "+", atunci cand sunt pe temperaturi negative. Ciundat mi se pare si faptul ca cei de la Mikroelektronika au scris in cartea lor despre microcontrolere, ca varianta este functionala dar, la teste se comporta ca in cazul de fata. Link spre comentariu
Liviu M Postat Iulie 2, 2010 Partajează Postat Iulie 2, 2010 Eu n-am vrut sa scot nimic din program, voiam doar sa modific partea cu semnul. Sper ca ai inteles ce voiam sa fac: mie mi s-a parut ca dupa ce setezi semnul pe minus, il "tergi" cu caracterul pentru sute. In prima varianta, ti-am aratat cum as face eu sa afiseze si minus; stergerea lui in cazul numerelor pozitive n-am implementat-o. In variatele din mesajul anterior, ma ocupam pe indelete de semn in ambele cazuri, dar fara sa incerc modificarea altei parti din program. Bucatelele mele trebuie sa inlocuiasca fix blocul cu detectia si afisarea minusului din programul original. Exceptand eventual indecsii lui text[], restul programului original trebuie sa ramana cum era. LE Daca ai indenta textul: void Display_Temperature(unsigned int temp2write) { const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8; char temp_whole; unsigned int temp_fraction;// verificare pentru temperaturi negative if (temp2write & 0x8000) { text[0] = '-'; temp2write = ~temp2write + 1; }// extrage temp_whole temp_whole = temp2write >> RES_SHIFT ;// converteste temp_whole in caractere if (temp_whole/100) text[0] = temp_whole/100 + 48; else text[0] = '0'; text[1] = (temp_whole/10)%10 + 48; // extrage zecimi text[2] = temp_whole%10 + 48; // extrage unitati// extrage temp_fraction si converteste in unsigned int temp_fraction = temp2write << (4-RES_SHIFT); temp_fraction &= 0x000F; temp_fraction *= 625;// converteste temp_fraction in caractere text[4] = temp_fraction/1000 + 48; // extrage miile text[5] = (temp_fraction/100)%10 + 48; // extrage sutele text[6] = (temp_fraction/10)%10 + 48; // extrage zecile text[7] = temp_fraction%10 + 48; // extrage unitatile// afisare temp. pe LCD Lcd_Out(2, 5, text);}ai vedea ca atribuirile pe care zici ca le-am "pierdut" nu fac parte din blocul de detectie a semnului. Link spre comentariu
ducu Postat Iulie 2, 2010 Autor Partajează Postat Iulie 2, 2010 Nici o problema Liviu M, am inteles eu ce ai incercat sa faci, am facut si asta deja dar cand vin pe temperatura negativa oscileaza rapid intre "0" si "-", asta nu inteleg eu, de ce intra in fibrilatie, sa zic asa.am schimbat si locatia caracterului pe lcd dar tot asa face.Ciudat tare. Link spre comentariu
ducu Postat Iulie 8, 2010 Autor Partajează Postat Iulie 8, 2010 Am reusit sa rezolv problema. Testul de fata este facut cu ds18b20 dar programul este aproape identic. Se poate modifica softul sa functioneze si pe alte microcontrolere, foarte simplu. Rezultatul il postez mai jos. Am creat un marker care modifica la randul sau flag-ul pentru a nu suprascrie peste "temp[0]". Codul functional este acesta: //Microcontroller P16f887//Oscilator intern 8MHz//Domeniu de masurare in grade Celsius [-55~+128] cu pas de 0,1 grade Celsius// LCD module connectionssbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;sbit LCD_RS_Direction at TRISB4_bit;sbit LCD_EN_Direction at TRISB5_bit;sbit LCD_D4_Direction at TRISB0_bit;sbit LCD_D5_Direction at TRISB1_bit;sbit LCD_D6_Direction at TRISB2_bit;sbit LCD_D7_Direction at TRISB3_bit;// End LCD module connections// Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:// 18S20: 9 (default setting; can be 9,10,11,or 12)// 18B20: 12const unsigned short TEMP_RESOLUTION = 12;char *text = "000,0";unsigned temp;void Display_Temperature(unsigned int temp2write) { const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8; char temp_whole; unsigned int temp_fraction; unsigned short isNegative = 0x00; // Check if temperature is negative if (temp2write & 0x8000) { text[0] = '-'; temp2write = ~temp2write + 1; isNegative = 1; } // Extract temp_whole temp_whole = temp2write >> RES_SHIFT ; // Convert temp_whole to characters if (!isNegative){ if (temp_whole/100) text[0] = temp_whole/100 + 48; else text[0] = '+'; } text[1] = (temp_whole/10)%10 + 48; // Extract tens digit text[2] = temp_whole%10 + 48; // Extract ones digit // Extract temp_fraction and convert it to unsigned int temp_fraction = temp2write << (4-RES_SHIFT); temp_fraction &= 0x000F; temp_fraction *= 625; // Convert temp_fraction to characters text[4] = temp_fraction/1000 + 48; // Extract thousands digit //text[5] = (temp_fraction/100)%10 + 48; // Extract hundreds digit //text[6] = (temp_fraction/10)%10 + 48; // Extract tens digit //text[7] = temp_fraction%10 + 48; // Extract ones digit // Print temperature on LCD Lcd_Out(2, 5, text);}const char character[] = {4,10,4,0,0,0,0,0};void CustomChar(char pos_row, char pos_char) { char i; Lcd_Cmd(64); for (i = 0; i<=7; i++) Lcd_Chr_CP(character[i]); Lcd_Cmd(_LCD_RETURN_HOME); Lcd_Chr(pos_row, pos_char, 0);}void main() { CMCON |=7; Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 3, "Temperatura:"); // Print degree character, 'C' for Centigrades CustomChar(2,10); // Different LCD displays have different char code for degree // If you see greek alpha letter try typing 178 instead of 223 Lcd_Chr(2,11,'C'); //--- Main loop do { //--- Perform temperature reading Ow_Reset(&PORTA, 1); // Onewire reset signal Ow_Write(&PORTA, 1, 0xCC); // Issue command SKIP_ROM Ow_Write(&PORTA, 1, 0x44); // Issue command CONVERT_T Delay_us(600); Ow_Reset(&PORTA, 1); Ow_Write(&PORTA, 1, 0xCC); // Issue command SKIP_ROM Ow_Write(&PORTA, 1, 0xBE); // Issue command READ_SCRATCHPAD temp = Ow_Read(&PORTA, 1); temp = (Ow_Read(&PORTA, 1) << 8) + temp; //--- Format and display result on Lcd Display_Temperature(temp); Delay_ms(400); } while (1);}Mentionez de asemenea ca modificarile au fost facute de catre Aleksandar. Multumirile mele catre dansul.Datorita donatie facute acum ceva timp de catre sofian, in care am primit printre multe altele si doua picuri 16f628A, am reusit sa realizez si practic acest poriect.Multumirile mele profunde catre sofian. Rezultatul testului: Link spre comentariu
gabrielmrc Postat Mai 18, 2011 Partajează Postat Mai 18, 2011 Am reusit sa rezolv problema. Testul de fata este facut cu ds18b20 dar programul este aproape identic. Se poate modifica softul sa functioneze si pe alte microcontrolere, foarte simplu. Rezultatul il postez mai jos. Am creat un marker care modifica la randul sau flag-ul pentru a nu suprascrie peste "temp[0]". Codul functional este acesta: //Microcontroller P16f887//Oscilator intern 8MHz//Domeniu de masurare in grade Celsius [-55~+128] cu pas de 0,1 grade Celsius// LCD module connectionssbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;sbit LCD_RS_Direction at TRISB4_bit;sbit LCD_EN_Direction at TRISB5_bit;sbit LCD_D4_Direction at TRISB0_bit;sbit LCD_D5_Direction at TRISB1_bit;sbit LCD_D6_Direction at TRISB2_bit;sbit LCD_D7_Direction at TRISB3_bit;// End LCD module connections// Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:// 18S20: 9 (default setting; can be 9,10,11,or 12)// 18B20: 12const unsigned short TEMP_RESOLUTION = 12;char *text = "000,0";unsigned temp;void Display_Temperature(unsigned int temp2write) { const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8; char temp_whole; unsigned int temp_fraction; unsigned short isNegative = 0x00; // Check if temperature is negative if (temp2write & 0x8000) { text[0] = '-'; temp2write = ~temp2write + 1; isNegative = 1; } // Extract temp_whole temp_whole = temp2write >> RES_SHIFT ; // Convert temp_whole to characters if (!isNegative){ if (temp_whole/100) text[0] = temp_whole/100 + 48; else text[0] = '+'; } text[1] = (temp_whole/10)%10 + 48; // Extract tens digit text[2] = temp_whole%10 + 48; // Extract ones digit // Extract temp_fraction and convert it to unsigned int temp_fraction = temp2write << (4-RES_SHIFT); temp_fraction &= 0x000F; temp_fraction *= 625; // Convert temp_fraction to characters text[4] = temp_fraction/1000 + 48; // Extract thousands digit //text[5] = (temp_fraction/100)%10 + 48; // Extract hundreds digit //text[6] = (temp_fraction/10)%10 + 48; // Extract tens digit //text[7] = temp_fraction%10 + 48; // Extract ones digit // Print temperature on LCD Lcd_Out(2, 5, text);}const char character[] = {4,10,4,0,0,0,0,0};void CustomChar(char pos_row, char pos_char) { char i; Lcd_Cmd(64); for (i = 0; i<=7; i++) Lcd_Chr_CP(character[i]); Lcd_Cmd(_LCD_RETURN_HOME); Lcd_Chr(pos_row, pos_char, 0);}void main() { CMCON |=7; Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 3, "Temperatura:"); // Print degree character, 'C' for Centigrades CustomChar(2,10); // Different LCD displays have different char code for degree // If you see greek alpha letter try typing 178 instead of 223 Lcd_Chr(2,11,'C'); //--- Main loop do { //--- Perform temperature reading Ow_Reset(&PORTA, 1); // Onewire reset signal Ow_Write(&PORTA, 1, 0xCC); // Issue command SKIP_ROM Ow_Write(&PORTA, 1, 0x44); // Issue command CONVERT_T Delay_us(600); Ow_Reset(&PORTA, 1); Ow_Write(&PORTA, 1, 0xCC); // Issue command SKIP_ROM Ow_Write(&PORTA, 1, 0xBE); // Issue command READ_SCRATCHPAD temp = Ow_Read(&PORTA, 1); temp = (Ow_Read(&PORTA, 1) << 8) + temp; //--- Format and display result on Lcd Display_Temperature(temp); Delay_ms(400); } while (1);}Mentionez de asemenea ca modificarile au fost facute de catre Aleksandar. Multumirile mele catre dansul.Datorita donatie facute acum ceva timp de catre sofian, in care am primit printre multe altele si doua picuri 16f628A, am reusit sa realizez si practic acest poriect.Multumirile mele profunde catre sofian. Rezultatul testului: raspunsul meu nu prea ajuta cu nimic pe mine m-ar interesa schema electrica a circuitului pe care l-ai realizat.ms anticipat Link spre comentariu
ducu Postat Decembrie 11, 2011 Autor Partajează Postat Decembrie 11, 2011 gabrielmrc, schema electronica poate fi gasita aici. Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum