Aktyw Forum

Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.

Sprawdź punkty Zarejestruj się

Problem z wyświetlaczem LCD

Awatar użytkownika
arek944
-
-
Posty:5
Rejestracja:26 mar 2011, o 11:22
Lokalizacja:Olsztyn
Kontaktowanie:
Problem z wyświetlaczem LCD

Postautor: arek944 » 26 mar 2011, o 11:50

Witam serdecznie
Mam pewien problem z wyświetlaczem LCD, otóż nie chce on w ogóle ze mną gadać. I chciałbym wiedzieć co jest nie tak, i jak ewentualnie roziązać problem? Poniższy program jest zaczerpnięty z Biblii Dolińskiego z niewielkimi zmianami kosmetycznymi.
Jeśli taka informacja okaże się pomocna, to korzystam z programatora STK500 i oprogramowania AVR Studio 4.16.638.

Kod: Zaznacz cały

//**** Biblioteki i pliki nagłówkowe ****// #include <avr/io.h> #include <avr/pgmspace.h> #include <stdlib.h> //**** Definicje stałych i zmiennych ****// #define LCD_RS 1 #define LCD_E 0 #define LCD_PORT PORTA #define DISP_CR 0x0A unsigned char line=0; //wiersz LCD unsigned char unit=0; //kolumna LCD #define wait_time 10.38 //**** Wektory przerwań ****// //**** Funkcje konfiguracyjne ****// void PORT_config(void) { /* 0 = WEJŚCIE / CMOS Pull-DOWN 1 = WYJŚCIE / CMOS Pull-UP */ DDRA = 0xFF; DDRC = 0xFF; DDRD = 0b00111000; //......................Impulsator(7,6) / LED(5,4) / INT1(3) PORTA = 0xFF; PORTC = 0xFF; PORTD = 0b11101000; //.....................Ustawienia Source / Sink } void REG_init(void) { ; } //**** Funkcje obsługi wyświetlacza LCD 1602 ****// void LCD_Wait(unsigned long p_time) { for (;p_time>0;p_time--) { for (unsigned char tp1=255;tp1!=0;tp1--) { ; } } } void LCD_Directive(unsigned char lcd_dir) //służy do sterowania LCD { LCD_PORT &= ~(_BV(LCD_RS)); LCD_PORT |= _BV(LCD_E); LCD_PORT |= (LCD_PORT&0x0F)|(lcd_dir&0xF0); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(10L); LCD_PORT |= _BV(LCD_E);; //sbi LCD_PORT |= (LCD_PORT&0x0F)|((lcd_dir&0x0F)<<4); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(10L); } void LCD_Character(unsigned char lcd_char) //służy do wypisywania znaków na LCD { LCD_PORT |= _BV(LCD_RS); LCD_PORT |= _BV(LCD_E); LCD_PORT |= (LCD_PORT&0x0F)|(lcd_char&0xF0); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(10L); LCD_PORT |= _BV(LCD_E); //sbi LCD_PORT |= (LCD_PORT&0x0F)|((lcd_char&0x0F)<<4); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(10L); } //**** Funkcje sterujące znakami wyświetlacza LCD ****// void LCD_XY(unsigned char x_pos, unsigned char y_pos) { LCD_Directive((x_pos*0x40+y_pos)|0x80); } void LCD_CLR(void) { LCD_Directive(0x01); LCD_Wait(1.64*wait_time); line=0; unit=0; } void LCD_WRITE(char lcd_sign) { LCD_Character(lcd_sign); if (++unit==16) { unit=0; if (++line==2) { line=0; } } } void LCD_WRITE_TXT(char *text) { char mark; char turn=0; while(1) { mark=pgm_read_byte(&text[turn++]); //PRG_RDB if (mark!=0) { if (mark==DISP_CR) { line==1?unit=0:++line; unit=0; LCD_XY(line,unit); } else { LCD_Character(mark); } } else { break; } }//end while } //eof void LCD_INIT(void) { LCD_Wait(45*wait_time); for (unsigned char s=0;s<=3;s++) { LCD_PORT |= _BV(LCD_E); //sbi LCD_PORT |= (LCD_PORT&0x0F)|(0x30); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(5*wait_time); } LCD_PORT |= _BV(LCD_E); //sbi LCD_PORT |= (LCD_PORT&0x0F)|(0x20); asm ("nop"); asm ("nop"); asm ("nop"); LCD_PORT &= ~(_BV(LCD_E)); //cbi LCD_Wait(10L); LCD_Directive(0x28); //interfejs 4bit, 2 linie, znak 5x7 LCD_Directive(0x08); LCD_Directive(0x01); LCD_Wait(1.64*wait_time); LCD_Directive(0x06); } //**** Funkcja MAIN ***// int main(void) { char *tekst1=PSTR("Test"); PORT_config(); REG_init(); LCD_INIT(); while(1) { LCD_Directive(0x0F); LCD_WRITE_TXT(tekst1); } //end while } //end main

Awatar użytkownika
arek944
-
-
Posty:5
Rejestracja:26 mar 2011, o 11:22
Lokalizacja:Olsztyn
Kontaktowanie:

Postautor: arek944 » 26 mar 2011, o 12:20

Na moje oko jest coś nie tak z funkcją LCD_Wait() generującą opóźnienie czasowe... O ile mi wiadomo zmienna typu long nie łyka wartości zmiennoprzecinkowych jak 1.64*10.38, no ale może jestem w błędzie :633:

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty:2653
Rejestracja:24 sty 2005, o 00:39
Lokalizacja:Winny gród

Postautor: pajaczek » 26 mar 2011, o 15:05

A co jest nie tak?? Włączyłeś jakąś optymalizację kodu?

A co do long, to przytoczona operacja zostanie przeprowadzona na zmiennoprzecinkowych i niejawnie zrzutowana na stałoprzecinkową (zostanie ucięta część ułamkowa). Ale same obliczenia zmiennoprzecinkowe zależą już od kompilatora / optymalizacji.

Awatar użytkownika
arek944
-
-
Posty:5
Rejestracja:26 mar 2011, o 11:22
Lokalizacja:Olsztyn
Kontaktowanie:

Postautor: arek944 » 26 mar 2011, o 15:33

Dzieje się to, że wyświetlacz nic nie wyświetla, lub wyświetla standardowy błąd inicjalizacji (16 pełnych pól w 1 rzędzie). I pomimo, iż jest to przykład wprost z książki, to nie działa :(

Sądząc, że jest to wina źle odmierzanego czasu, postanowiłem poczynić przemyślenia:

~ jeśli zegar jest taktowany z częstotliwością 1MHz, to czas trwania impulsu wynosi 1us,
~ zatem aby AVRka odmierzyła czas np 5ms, musi minąć 5000 impulsów,
~ w AVR czas wykonywania rozkazu jest równy 1 impulsowi zegara,
zatem podmieniłem funkcję LCD_Wait na:

Kod: Zaznacz cały

#define CPU_Speed 1000000 //należy przepisać wartość podaną w F_CPU unsigned char step=(CPU_Speed/1000000); void LCD_Wait(unsigned long p_time) { unsigned long s_time=p_time*step; for (;s_time!=0;s_time--) { ; } }
Gdzie, po wywpołaniu funkcji odmierzany czas podaje się w us:
LCD_Wait(45000); //czekaj 45ms

.. No cóż, i dalej nic :( Może czasy w funkcji LCD_INIT() są źle podane? Sam jużnie wiem, co jest źle :/

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty:2653
Rejestracja:24 sty 2005, o 00:39
Lokalizacja:Winny gród

Postautor: pajaczek » 26 mar 2011, o 21:26

Poczyń jeszcze takie przemyślenia (bo nie odpowiedziałeś mi na pytanie o optymalizację, a nie mam tego gdzie sprawdzić).

Kod: Zaznacz cały

void LCD_Wait(unsigned long p_time) { for (;p_time>0;p_time--) { for (unsigned char tp1=255;tp1!=0;tp1--) { asm("nop"); } } }

Awatar użytkownika
arek944
-
-
Posty:5
Rejestracja:26 mar 2011, o 11:22
Lokalizacja:Olsztyn
Kontaktowanie:

Postautor: arek944 » 26 mar 2011, o 23:03

Takiego cuda już próbowałem xD a ten program nie działa też u kilku moich znajomych, więc albo my jesteśmy łośki, albo braknie jakichś fusebitów, albo ten program po prostu nie działa xD
Optymalizacja, tak.. wg AVR Studio stopień optymalizacji jest podany jako -Os

Chociaż wgrałem sobie programik z tej stronki http://www.avr-asm-tutorial.net/avr_en/LCD4_500.html gdzie jest projekt zegarka z datownikiem przedstawiony... i szczerze powiem, że po przestawieniu kilku stałych wartości w programie, przestawieniu zworki XTAL w programatorze i wstawieniu rezonatora kwarcowego 8HMz zegarek śmigał stabilnie, wyświetlacz mrugał aż miło, a w ciągu 6 godzin działania programu nie zgubił ani jednej sekundy :)
Ew przerobię programik z tej stronki, chociaż pozostała mi trauma i wstręt do assemblera po zajęciach z DSM-51 :612:

Awatar użytkownika
arek944
-
-
Posty:5
Rejestracja:26 mar 2011, o 11:22
Lokalizacja:Olsztyn
Kontaktowanie:

Postautor: arek944 » 27 mar 2011, o 22:06

Dobra, problem rozwiązany ;) funkcja odliczająca czas była o kant d ;)

Wróć do „AVR/AVR32”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 5 gości