Vizitator fod Postat Februarie 18, 2012 Partajează Postat Februarie 18, 2012 Salut, Vreau sa fac o placa de achizitie de date si nu stiu cum pot afisa pe un LCD un float(de ex o temperatura cu o zecimala dupa virgula)? Ma poate ajuta cineva cu o portiune de cod functionala? Folosesc pic16f877, MPLAB cu HI TECH-C si libraria pentru LCD este urmatoarea : #define _LCD_C #include #include #include #include #include "lcd.h" //#include "HardwareProfile.h" // Delays (in uS) (big delay is *2) #define SMALL_DELAY 40 // write a nybble to the port void lcdWriteNybble(unsigned char nybble) { // This routine is required because the LCD data bus // is not connected on a continuous sequence of port pins // so we have to break it up and write to the pins // individually. // Write the nybble to the LCD databus pins if (nybble & 0b00000001) LCD_DB4 = 1; else LCD_DB4 = 0; if (nybble & 0b00000010) LCD_DB5 = 1; else LCD_DB5 = 0; if (nybble & 0b00000100) LCD_DB6 = 1; else LCD_DB6 = 0; if (nybble & 0b00001000) LCD_DB7 = 1; else LCD_DB7 = 0; } // write a byte to the LCD in 4 bit mode void lcdWrite(unsigned char address, unsigned char c) { LCD_RS = address; __delay_us(SMALL_DELAY); // Write the 4 bits non-distructively to the port lcdWriteNybble((c >> 4) & 0x0F); // Toggle the clock bit LCD_EN = 1; __delay_us(SMALL_DELAY); LCD_EN = 0; __delay_us(SMALL_DELAY); // Write the 4 bits non-distructively to the port lcdWriteNybble(c & 0x0F); // Toggle the clock bit LCD_EN = 1; __delay_us(SMALL_DELAY); LCD_EN = 0; __delay_us(SMALL_DELAY); } // write one character to the LCD void lcdPutch(char c) { // This routine needs updating so it monitors the cursor posiiton LCD_RS = 1; // write characters lcdWrite(DATA_REG, c); } void lcdClearDisplay(void) { lcdWrite(CMD_REG, LCD_CLR); // Reset our internal cursor position lcdX = 0; lcdY = 0; // Delay for (int counter = 0; counter < 200; counter++) __delay_us(100); } // Initialise the LCD void lcdInit(void) { int counter; // Power up delay for (counter = 0; counter < 1500; counter++) __delay_us(100); LCD_EN = 0; // Set clock low LCD_RS = CMD_REG; // Set RS to command register // Set up the interface lcdWriteNybble(LCD_WAKE); LCD_EN = 1; LCD_EN = 0; for (counter = 0; counter < 500; counter++) __delay_us(100); LCD_EN = 1; LCD_EN = 0; __delay_us(200); LCD_EN = 1; LCD_EN = 0; __delay_us(200); // Set the interfact to 4 bits lcdWriteNybble(LCD_4BIT); __delay_us(SMALL_DELAY); LCD_EN = 1; __delay_us(SMALL_DELAY); LCD_EN = 0; // Don't know what this does... lcdWrite(CMD_REG, 0x28); // Enable display / hide cursor lcdWrite(CMD_REG, LCD_ENDISP); // Clear the display and home the cursor lcdClearDisplay(); // Set the cursor movement direction to right lcdWrite(CMD_REG, LCD_CURRIGHT); // Turn on display lcdWrite(CMD_REG, LCD_DISPON); // Reset our internal cursor position lcdX = 0; lcdY = 0; } void lcdDisplayState(int state) { if (state == 1) lcdWrite(CMD_REG, LCD_DISPON); else lcdWrite(CMD_REG, LCD_DISPOFF); } // Move the cursor to the specified X,Y void lcdGoto(int x, int y) { int offset; // Select the correct line of the display switch (y) { case 0: offset = 0x00; break; case 1: offset = 0x40; break; case 2: offset = 0x14; break; case 3: offset = 0x54; break; } // Select the correct character of the line offset += x; // Send the command to the LCD lcdWrite(CMD_REG, LCD_DDSET | offset); // Reset our internal cursor position lcdX = x; lcdY = y; } // Output a string of characters to the display void lcdPuts(const char *string) { // Since the 4 line display is in the order line 1, line 3, line 2, line 4 // we need to read the current cursor position and control how the text is // output, adjusting the cursor position as we go int loop; for (loop = 0; loop < strlen(string); loop++) { // Write the character to the LCD lcdWrite(DATA_REG, string[loop]); lcdX++; // Have we reached the end of the line? if (lcdX == 20) { // Move to the start of the next line lcdX = 0; lcdY++; // If we are off the bottom of the screen // go back to the top line if (lcdY == 4) lcdY = 0; // Adjust the cursor position on the LCD lcdGoto(lcdX, lcdY); } } Multumesc! Link spre comentariu
nooob64 Postat Februarie 18, 2012 Partajează Postat Februarie 18, 2012 Salut , cel mai simplu mod de a afisa un float este cu sprintf insa costul memoriei este mare (unele compilatoare ajung si la 4KB pt primul apel al functiei sprintf) ex : sprintf(lcd_buffer,"numar float = %.2f",nr_float); Eu asi alege metoda cu sprintf pentru controlere cu multa memorie (mai mare de 16KB flash). Pentru pic16f877 incearca varianta in care "spargi" numarul int si afisezi virgula cind trebuie. unsigned char ch;unsigned int adc_rd;char *text;long tlong;void main() {............. LCD_Cmd(LCD_CURSOR_OFF); // send command to LCD (cursor off) LCD_Cmd(LCD_CLEAR); // send command to LCD (clear LCD) text = "LCD example"; // assign text to string LCD_Out(2,1,text); // print string a on LCD, 2nd row, 1st column ADCON1 = 0x82; // configure VDD as Vref, and analog channels TRISA = 0xFF; // designate PORTA as input Delay_ms(2000); text = "voltage:"; // assign text to string while (1) { adc_rd = ADC_read(2); // get ADC value from 2nd channel LCD_Out(2,1,text); // print string a on LCD, 2nd row, 1st column tlong = (long)adc_rd * 5000; // covert adc reading to milivolts tlong = tlong / 1023; // 0..1023 -> 0-5000mV ch = tlong / 1000; // extract volts digit LCD_Chr(2,9,48+ch); // write ASCII digit at 2nd row, 9th column LCD_Chr_CP('.'); ch = (tlong / 100) % 10; // extract 0.1 volts digit LCD_Chr_CP(48+ch); // write ASCII digit at cursor point ch = (tlong / 10) % 10; // extract 0.01 volts digit LCD_Chr_CP(48+ch); // write ASCII digit at cursor point ch = tlong % 10; // extract 0.001 volts digit LCD_Chr_CP(48+ch); // write ASCII digit at cursor point LCD_Chr_CP('V'); Delay_ms(1); }}//~! Link spre comentariu
Vizitator fod Postat Februarie 18, 2012 Partajează Postat Februarie 18, 2012 Din pacate tot nu merge...se poate sa fie din cauza librariei pentru lcd de care o folosesc(cea pe cara am afisat-o)? Link spre comentariu
nooob64 Postat Februarie 18, 2012 Partajează Postat Februarie 18, 2012 Exemplul pe care ti l-am dat este din MikroC O librarie pt LCD proprie , insa pentru avr-uri: int s_contor=0;int s_end = 0;unsigned char s_count=0;#ifndef LCD_DRIVER_H_#define LCD_DRIVER_H_#define RS AVR32_PIN_PB12#define RW AVR32_PIN_PB13#define E AVR32_PIN_PB14#define DB4 AVR32_PIN_PB15#define DB5 AVR32_PIN_PB16#define DB6 AVR32_PIN_PB17#define DB7 AVR32_PIN_PB18#define LCD_BCKL AVR32_PIN_PB19#endif /* LCD_DRIVER_H_ */char lcd_buffer[21];void lcd_putchar(char c,unsigned char x,unsigned char y);//pune caracter la x,yvoid transferthedata (unsigned char data);//transfera datelevoid writecommand(unsigned char data);//scrie comanda la lcdvoid writedata(unsigned char data);//trimite comanda la lcdvoid init_lcd();//initializare lcdvoid write_char(char chr);//trimite caracter la lcd (fara pozitionare, se incrementeaza cursorul)void lcd_setup(unsigned char lcd , unsigned char bkl);//setare lcd on/off , bkl on/offvoid lcd_clear();//clear lcdvoid lcd_gotoxy(unsigned char x ,unsigned char y);//pozitionare cursor la x(coloana), y(linie)void lcd_puts(char *c,unsigned char x,unsigned char y);//pune string la x,yvoid lcd_delay();void scrolling_text(char *text,unsigned char x,unsigned char y,int delay); //afiseaza scrolling textunsigned char vector_init[]={12,0x03,0x03,0x03,0x02,0x02,0x0C,0x00,0x08,0x00,0x01,0x00,0x06};void transferthedata (unsigned char data){ if (data & 0x01) setbit(DB4); else if ( ! (data & 0x01) ) clrbit(DB4); if ( ( data >> 1 ) & 0x01 ) setbit(DB5); else if ( !(( data >> 1 ) & 0x01) ) clrbit(DB5); if ( ( data >> 2 ) & 0x01 ) setbit(DB6); else if ( !(( data >> 2 ) & 0x01) ) clrbit(DB6); if ( ( data >> 3 ) & 0x01 ) setbit(DB7); else if ( !(( data >> 3 ) & 0x01) ) clrbit(DB7);}void lcd_delay(){ cpu_delay_us(850,FOSC0_redef);// delay_ms(1) ....}void writecommand(unsigned char data) { clrbit(E); clrbit(RS); clrbit(RW); transferthedata(data); setbit(E); lcd_delay(); clrbit(E); lcd_delay();//10ms }void writedata(unsigned char data) { clrbit(E); setbit(RS); clrbit(RW); transferthedata(data); setbit(E); lcd_delay(); clrbit(E); lcd_delay(); }void init_lcd(){ unsigned char i=0; delay_ms(30); for(i=1;i<=vector_init[0];i++) { writecommand(vector_init[i]); delay_ms(5); }}void write_char(char chr){ writedata(chr >> 4); writedata(chr);}void lcd_setup(unsigned char lcd , unsigned char bkl){ if(lcd == 1) { writecommand(0x00); writecommand(0x0C); //display on ; cursor , blink off } else { writecommand(0x00); writecommand(0x00); } if(bkl == 1) setbit(LCD_BCKL); else clrbit(LCD_BCKL);}void lcd_clear(){ writecommand(0x00); writecommand(0x01);}void lcd_gotoxy(unsigned char x ,unsigned char y){if(y==2){ writecommand(0x0C); //muta cursorul writecommand(0x00); //pe linia 2}if(y==1){ writecommand(0x00); //muta cursorul writecommand(0x02); //pe linia 1}while(x!=0){ writecommand(0x01); //muta cursorul writecommand(0x04); //in dreapta cu 1x--;}}void lcd_putchar(char c,unsigned char x,unsigned char y){ lcd_gotoxy(x,y); write_char(c);}void lcd_puts(char *c,unsigned char x,unsigned char y){ unsigned char i; lcd_gotoxy(x,y); for(i=0;i<strlen(c);i++) write_char(c[i]);}void long2lcd(unsigned long x,unsigned char z,unsigned char y){ unsigned long limita; unsigned char nrz; unsigned char fost; unsigned char r=0; limita=10000000; fost=0; while (limita>=10){ nrz=48; while (x>=limita){ x-=limita; nrz++; fost=1; } if (fost) { lcd_putchar(nrz,z+r,y); r++; } limita/=10; } lcd_putchar(x+48,z+r,y);}void nr2lcd(unsigned char c,unsigned char x,unsigned char y){ lcd_putchar(48+c/10,x,y); lcd_putchar(48+c%10,x+1,y);} Link spre comentariu
Vizitator fod Postat Februarie 18, 2012 Partajează Postat Februarie 18, 2012 Merci, dar eu folosesc mplab cu hi tech-c.Ar putea cineva sa imi de-a o librarie cu care pot afisa un float pe LCD? Link spre comentariu
Liviu M Postat Februarie 19, 2012 Partajează Postat Februarie 19, 2012 Dupa parerea mea, daca urmezi sfatul lui nooob64, acela de a afisa numarul pe bucati, atunci poti folosi biblioteca ta. Scris asa, la repezeala si fara sa testez, codul ar arata cam asa: volatile bit bNumarNegativ;void main(void){ unsigned char ucIntregi = 0; unsigned char ucZecimale = 0; float fNumarDeTest=123.95; //un numat cu partea intreaga < 255 si partea zecimala < 255 (2 zecimale) bNumarNegativ = 0; if(fNumarDeTest<0) { bNumarNegativ = 1; ucIntregi = (unsigned char) -fNumarDeTest; //asta ar trebui sa "arunce" partea zecimala ucZecimale = (unsigned char) (-(fNumarDeTest + ucIntregi) * 100); //asta ar trebui sa pastreze numai partea zecimala } else { bNumarNegativ = 0; ucIntregi = (unsigned char) fNumarDeTest; //asta ar trebui sa "arunce" partea zecimala ucZecimale = (unsigned char) ((fNumarDeTest - ucIntregi + 1) * 100); //asta ar trebui sa pastreze numai partea zecimala } if(bNumarNegativ ) //pentru numere negative afisam semnul { lcdGoto(2, 4); //linia 2, coloana 4 lcdWrite(CMD_REG, '-'); //afiseaza punctul zecimal } else { lcdGoto(2, 5); //linia 2, coloana 5 } lcdWrite(CMD_REG, (ucIntregi /100) + '0'); //afiseaza sutele lcdWrite(CMD_REG, ((ucIntregi /10)%10) + '0'); //afiseaza zecile lcdWrite(CMD_REG, (ucIntregi %10) + '0'); //afiseaza unitatile lcdWrite(CMD_REG, '.'); //afiseaza punctul zecimal lcdWrite(CMD_REG, ((ucZecimale /10)%10) + '0'); //afiseaza zecimile lcdWrite(CMD_REG, (ucZecimale %10) + '0'); //afiseaza sutimile}Bineinteles, am presupus ca biblioteca ta functioneaza (ca ai afisat deja alte caractere cu functiile alea) si ca pui bucatica de cod de mai sus la locul ei in program. PS Daca ajungi la concluzia ca e ce-ti trebuie, poti "extinde" biblioteca definind o functie care sa contina codul de mai sus. LE In urma unor teste am corectat codul. Observatii: - e "urias" (compilat cu picc - lite mode (adica fara optimizari) - numai conversia ocupa 15% din memoria unui 16F877) - la "generarea" zecimalelor are probleme cu "rezolutia" - uneori ucZecimale e cu o unitate pe langa ce ar trebui sa fie. Link spre comentariu
Vizitator fod Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Am incercat si asa dar tot nu merge...cred ca am nevoie de alta librarie pentru lcd.Are cineva sa imi de-a o librarie cu care a mai afisat float-uri?Multumesc! Link spre comentariu
Liviu M Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Posteaza un zip cu fisierele lcd.c si lcd.h si pune o schema a montajului, ca poate nu ai setat tot ce si cum trebuie. Link spre comentariu
Vizitator fod Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Am atasat un fisier cu librariile pt lcd (.c si .h) si o imagine cu ce imi afiseaza daca folosesc codul urmator : lcdClearDisplay();lcdGoto(0,0);lcdPuts(" TEMPERATURA ");lcdGoto(0,1);lcdPuts("20*C-");ucIntregi = (unsigned char) temp; //asta ar trebui sa "arunce" partea zecimalaucZecimale = (unsigned char) ((temp - ucIntregi + 1) * 100); //asta ar trebui sa pastreze numai partea zecimala lcdGoto(5,1); lcdWrite(CMD_REG, (ucIntregi /100) + 48); //afiseaza sutele lcdWrite(CMD_REG, ((ucIntregi /10)%10) + 48); //afiseaza zecile lcdWrite(CMD_REG, (ucIntregi %10) + 48); //afiseaza unitatile lcdWrite(CMD_REG, '.'); //afiseaza punctul zecimallcdWrite(CMD_REG, ((ucZecimale /10)%10) + 48); //afiseaza zecimilelcdWrite(CMD_REG, (ucZecimale %10) + 48); //afiseaza sutimilelcdGoto(13,1);lcdPuts("*C-25*C");lcdGoto(0,2);lcdPuts(" UMIDITATE ");lcdGoto(0,3);lcdPuts(" 15% - xx.x% - 35%"); Fac ceva gresit? Link spre comentariu
MatyC Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Nu inteleg un lucru. De ce nu afiseaza sirul de caractere " TEMPERATURA " si cel de-al doilea cu UMIDITATE.Ca sa scot din calcul o varianta te intreb un lucru: ai folosit functia lcdInit()??? Link spre comentariu
Vizitator fod Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Da, am folosit functia lcdinit();.Asta nu inteleg nici eu, dar sa verific am pus un delay de o sec intre fiecare instructiune de afisare si am observat ca prima data afiseaza "temperatura" si "20*C" dar apoi cand face acea conversie imi afiseaza acele caractere. Fara acel delay nu ai timp sa vezi ce se intampla si vezi numai acele carractere... Link spre comentariu
Liviu M Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Cand apelezi lcdWrite() ca sa scrii pe LCD (in codul de la mine), schimba CMD_REG cu DATA_REG. LE Cu ce frecventa a oscilatorului simulezi? Se potriveste cu cea din lcd.h (5 MHz)? #define _XTAL_FREQ 5000000 LLE Ar fi bine daca ne-ai povesti si cum ai configurat portul B (banui ca e tot setat ca iesire); in simulator cred ca n-are importanta daca e activat LVP (si cum e conectat PGM). Link spre comentariu
Vizitator fod Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Da, merge! Multumesc foarte mult !!! Link spre comentariu
Liviu M Postat Februarie 20, 2012 Partajează Postat Februarie 20, 2012 Cu placere, desi am senzatia ca metoda (cam mura-n gura) n-a fost prea "didactica" (proiectul asta cam miroase a tema de la scoala). Sper totusi ca ai ramas cu ceva din el. Felicitari! 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