[avr-gcc] i2c+lcd = pcf8574+lcd4bit

Jul 19, 2007 9 Replies

Witam,



Morduje LCD przez PCF8574 :) o ile inicjacja dzia³a bez problemu to przesy³anie tekstu (jak i pozosta³e operacje nie dzia³aj±) :/ mo¿e kto¶ "rzuci okiem" kto robi³ takie co¶:



// PinoutPCF: P0-P3 -> D4-D7, P4 -> RS, P5 -> R/W (not used), P6 -> EN2 (not used), P7 -> EN <code>



//globalna zmienna trzymaj±ca stan portu pcf'a uint8_t lcd_pcf_port;



void i2c_lcd_init(void) { delay1ms(250); lcd_pcf_port = 0xef; // RS=0 i2c_send8574(adr,lcd_pcf_port); delay1us(10); i2c_lcd_sendHalf(0x03,adr); // D4,D5 = 11 - data 8bit ; wg. noty hd44780 trzeba 3x wyslac to polecenie delay1ms(10); i2c_lcd_sendHalf(0x03,adr); delay1us(500); i2c_lcd_sendHalf(0x03,adr); delay1us(500); i2c_lcd_sendHalf(0x02,adr); // 4bit data delay1us(500); // tryb 4bit w³±czony i2c_lcd_command(0x28,adr); // 4bit data - DL=0, 2 lines lcd - N=1, char



5x8 - F=0 i2c_lcd_command(0x08,adr); // Off: display, cursor, blinking i2c_lcd_cls(adr); i2c_lcd_command(0x06,adr); // Cursor shift: incr I/D=1, display shift off S=0 i2c_lcd_command(0x0c,adr); // On: display; Off: cursor, blinking // jak nawet w±cze wy¶wietlanie kursora (0x0c|0x02) i/lub miganie (0x0c|0x01) to jest dobrze i dzia³a } </code>


Mój problem musi gdzie¶ le¿eæ ko³o funkcji command i data ale ja nic nie widze co robi³ bym ¼le :/



I funkcje wysy³aj±ce dane i polecenia: <code>



void i2c_lcd_command(uint8_t command, uint8_t adr) { lcd_pcf_port &= 0xef; // RS=0 i2c_send8574(adr,lcd_pcf_port); delay1us(100); i2c_lcd_send(command, adr); delay1us(100); }



void i2c_lcd_data(uint8_t data, uint8_t adr) { lcd_pcf_port |= 0x10; // RS=1 i2c_send8574(adr,lcd_pcf_port); //delay1us(100); i2c_lcd_send(adr,data); } // ----------------- Pozostale funkcje void i2c_lcd_cls(uint8_t adr) { i2c_lcd_command(0x01, adr); // lcd CLS delay1ms(10); }



void i2c_lcd_home(uint8_t adr) { i2c_lcd_command(0x02, adr); // lcd_cursor: home delay1ms(15); }



void i2c_lcd_setPos(uint8_t yy, uint8_t xx, uint8_t adr) { uint8_t n=0; if (yy == 1) n = 0; if (yy == 2) n = 64; if (yy == 3) n = 12; if (yy == 4) n = 76; n += xx; i2c_lcd_command((0x80|n), adr); // Set DDRAM addr }



// pisanie void i2c_lcd_str(char* str, uint8_t adr) { char znak; while(0 != (znak = *(str++))) i2c_lcd_data(znak, adr); }



</code>


Aha i funkcja send8574 jest dobra gdy¿ ca³y czas z niej korzystam (od pocz±tku jej napisania).



A jak wygl±da i2c_lcd_send? Nie widzê machania lini± Enable. Czy R/W wy¶wietlacza jest pod³±czone do masy czy P5? Chyba jest na masie... Micha³

Czyzbys chcial kompletny kod ;> - i tak chcia³em go udostêpniæ jak bêdzie dzia³a³ :) Po³±czenia opar³em na an118 z bascom-avr (biblioteka i2c_lcd.lib).

i2c_lcd_send - nic nadzwyczajnego taka sama jak w przypadku normalnie pod³±czonego lcd czyli odwo³uje siê do sendHalf przesy³aj±æ najpierw starsz± czê¶æ potem m³odsz±. A linia EN jest dobrze... R/W do masy.

A psze: <code>

void I2C_LCD_EPULSE(uint8_t adr) { lcd_pcf_port |= 0x80; // EN=1 i2c_send8574(adr,lcd_pcf_port); delay1us(50); lcd_pcf_port &= 0x7f; // EN=0 i2c_send8574(adr,lcd_pcf_port); delay1us(50); }

void i2c_lcd_sendHalf(uint8_t data, uint8_t adr) { delay1us(100); // wykrojenie 4 starszych bitow i wyzerowanie 4 mlodszych ,a nastepnie wpisanie w mlodsza czesc danych lcd_pcf_port &= 0xf0; lcd_pcf_port |= (0x0f & data); i2c_send8574(adr,lcd_pcf_port); delay1us(100); I2C_LCD_EPULSE(adr); }

void i2c_lcd_send(uint8_t data, uint8_t adr) { // starsza czê¶æ delay1us(100); i2c_lcd_sendHalf((data>>4), adr); // m³odsza czê¶æ delay1us(100); i2c_lcd_sendHalf(data, adr); delay1us(100); } </code>

Saper/nolin11 pisze:

[...]

Jeżeli chcesz swoje kody źródłowe udostępniać szerszej publiczności, proponuję pisać je bardziej przejrzyście. Wystarczy trzymać się kilku zasad. Jeden z wielu przykładów to wskazówki dla kodów źródłowych jądra Linuxa (gdzie ludzi piszących kod są setki i jakoś muszą sobie radzić):

formatting link
nieco szerzej wytłumaczone:
formatting link

ZNALAZ£EM!

masz funkcjê: void i2c_lcd_send(uint8_t data, uint8_t adr);

a w funkcji i2c_lcd_data wywo³ujesz: i2c_lcd_send(adr,data);

Jako¶ od pocz±tku mi siê nie podoba³o przekazywanie wszystkim funkcjom w g³±b parametru adr. Je¶li lcd_pcf_port jest zmienn± globaln±, niech adr te¿ ni± bêdzie. I tak nie dasz rady w ten sposób obs³u¿yæ wiêcej LCD pod ró¿nymi adresami (trzyma Ciê jedna zmienna lcd_pcf_port), a i wiêcej pamiêci stosu zabiera taka polityka.

Nie potrzebujê. Sam pisa³em w ASM na '51 z rejestrem 4094 pe³ni±cym t± sam± rolê co u Ciebie PCF wiêc mam ten temat przerobiony.

Gdy program zadzia³a, proponujê wywaliæ wszystkie oprócz niezbêdnych opó¼nienia. I2C jest sporo wolniejsze od LCD. Jeszcze zastanowi³ bym siê, czy nie 'wch³on±æ' procedury i2c_lcd_sendHalf w i2c_lcd_send. Mo¿na zaoszczêdziæ na czasie i pamiêci RAM, a rozmiar kodu zwiêkszy siê mo¿e o kilka bajtów...

Pozdrawiam, Micha³

Narzekasz :P ,wiem o tym i jako¶ staram siê tego trzymaæ nawet jak pisze w³asne programy ale jak piszê to pisze szybko i nie zastanawiam siê co naciskam :/ (mam na my¶li Shift) - g³upi nawyk z pascala :|

[odp. do postu pana Micha³a] Te¿ my¶la³em nad tym ale podczas inicjacji trzeba wys³aæ 3x 0x03 i nie bardzo da³o by siê to przyci±æ ale zjecha³em do 1160b z 1214b :) w tiny45 po usuniêciu opó¼nieñ.

e...

lcd_pcf_port = 0xe0; // RS=0 i2c_send8574(adr,lcd_pcf_port); lcd_pcf_port = 0xe3; i2c_send8574(adr,lcd_pcf_port); I2C_LCD_EPULSE(adr); I2C_LCD_EPULSE(adr); I2C_LCD_EPULSE(adr); lcd_pcf_port = 0xe2; i2c_send8574(adr,lcd_pcf_port); I2C_LCD_EPULSE(adr);

i ju¿ jest tryb 4-bit,

o ile gdzie¶ siê nie machn±³em, piszê pod presj± ¿ony wo³aj±cej na kolacjê ;)

Micha³

Saper/nolin11 pisze:

A ja akurat miałem na myśli ten nieszczęsny nawias klamrowy na końcu linii deklarującej prototyp funkcji. Wg mnie takie jego użycie w wybitny sposób zaciemnia kod (gdy ktoś się przyzwyczaił codziennie widzieć inny styl kodowania), podobnie jak konstrukcje typu:

if (warunek) zrobcos; zrobcoinnego;

U¿ytkownik "Micha³ Lankosz" snipped-for-privacy@tlen.pl napisa³ w wiadomo¶ci news:f7pqln$v3k$ snipped-for-privacy@opal.futuro.pl...

Zadzia³a³o?

Micha³

Oczywi¶cie :), tu by³ b³±d teraz ju¿ mam napisane tka ¿e moge podl±czyæ kilka wy¶wietlaczy przez PCF'a (odczytuje na pocz±tku stan funkcji z uk³adu)

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required