Skocz do zawartości

[C] Kurs AVR-GCC cz.5 wyświetlacz LCD


piter_kula

Pomocna odpowiedź

Witam wszystkich forumowiczów,
jestem początkujący jeśli chodzi o programowanie AVR i mam taką prośbę odnośnie programu do wyświetlacza LCD umieszczonego w kursie AVR-GCC.

Mógłby ktoś wytłumaczyć może nie krok po kroku ale mniej więcej kod programu hd44780.h.

Wklejam program z moimi zapytaniami.

/*
Plik hd44780.h
*/

#ifndef LCD_HD44780               
#define LCD_HD44780

/* RS */
#define SET_OUT_LCD_RS  DDRA  |=  _BV(PA0)
#define SET_LCD_RS      PORTA |=  _BV(PA0)
#define CLR_LCD_RS      PORTA &= ~_BV(PA0)

/* RW */
#define SET_OUT_LCD_RW  DDRA  |=  _BV(PA1)
#define SET_LCD_RW      PORTA |=  _BV(PA1)
#define CLR_LCD_RW      PORTA &= ~_BV(PA1)

/* E */
#define SET_OUT_LCD_E   DDRA  |=  _BV(PA2)
#define SET_LCD_E       PORTA |=  _BV(PA2)
#define CLR_LCD_E       PORTA &= ~_BV(PA2)

/* D4 */
#define SET_OUT_LCD_D4  DDRA  |=  _BV(PA3)
#define SET_IN_LCD_D4   DDRA  &= ~_BV(PA3)
#define SET_LCD_D4      PORTA |=  _BV(PA3)
#define CLR_LCD_D4      PORTA &= ~_BV(PA3)
#define IS_SET_LCD_D4   PINA  &   _BV(PA3)

/* D5 */
#define SET_OUT_LCD_D5  DDRA  |=  _BV(PA4)
#define SET_IN_LCD_D5   DDRA  &= ~_BV(PA4)
#define SET_LCD_D5      PORTA |=  _BV(PA4)
#define CLR_LCD_D5      PORTA &= ~_BV(PA4)
#define IS_SET_LCD_D5   PINA  &   _BV(PA4)

/* D6 */
#define SET_OUT_LCD_D6  DDRA  |=  _BV(PA5)
#define SET_IN_LCD_D6   DDRA  &= ~_BV(PA5)
#define SET_LCD_D6      PORTA |=  _BV(PA5)
#define CLR_LCD_D6      PORTA &= ~_BV(PA5)
#define IS_SET_LCD_D6   PINA  &   _BV(PA5)

/* D7 */
#define SET_OUT_LCD_D7  DDRA  |=  _BV(PA6)
#define SET_IN_LCD_D7   DDRA  &= ~_BV(PA6)
#define SET_LCD_D7      PORTA |=  _BV(PA6)
#define CLR_LCD_D7      PORTA &= ~_BV(PA6)
#define IS_SET_LCD_D7   PINA  &   _BV(PA6)


#define LCD_NOP asm volatile("nop\n\t""nop\n\t" "nop\n\t" "nop\n\t" ::);



#define LCDCOMMAND 0
#define LCDDATA    1

#define LCD_LOCATE(x,y)  WriteToLCD(0x80|((x)+((y)*0x40)), LCDCOMMAND)

#define LCD_CLEAR              WriteToLCD(0x01, LCDCOMMAND)
#define LCD_HOME               WriteToLCD(0x02, LCDCOMMAND)

/* IDS */

#define LCDINCREMENT           0x02
#define LCDDECREMENT           0x00
#define LCDDISPLAYSHIFT        0x01

#define LCD_ENTRY_MODE(IDS)    WriteToLCD(0x04|(IDS), LCDCOMMAND)

/* BCD */
#define LCDDISPLAY             0x04
#define LCDCURSOR              0x02
#define LCDBLINK               0x01

#define LCD_DISPLAY(DCB)       WriteToLCD(0x08|(DCB), LCDCOMMAND)

/* RL */
#define LCDLEFT                0x00
#define LCDRIGHT               0x04

#define LCD_SHIFT_DISPLAY(RL)  WriteToLCD(0x18|(RL), LCDCOMMAND)
#define LCD_SHIFT_CURSOR(RL)   WriteToLCD(0x10|(RL), LCDCOMMAND)

#define LCD_CGRAM_ADDRESS(A)   WriteToLCD(0x40|((A)&0x3f), LCDCOMMAND)
#define LCD_DDRAM_ADDRESS(A)   WriteToLCD(0x80|((A)&0x7f), LCDCOMMAND)

#define LCD_WRITE_DATA(D)      WriteToLCD((D),LCDDATA)


void lcd_init(void);
void WriteToLCD(unsigned char v,unsigned char rs);
unsigned char ReadAddressLCD(void);
void lcd_puts(char *str);

#endif

Pierwsze pytanie:

Dyrektywa #ifndef LCD_HD44780 wykonuje się jeżeli LCD_HD44780 nie jest zdefiniowany, a nie jest bo dopiero definiujemy go linię niżej #define LCD_HD44780, więc w sumie możemy pominąć tą dyrektywę warunkową według mnie, ale zapewne została w jakimś celu użyta chciałbym się dowiedzieć dlaczego?

Drugie pytanie:

Tyczy się tego fragmentu kodu:

#define SET_OUT_LCD_RS DDRA |= _BV(PA0)

#define SET_LCD_RS PORTA |= _BV(PA0)

#define CLR_LCD_RS PORTA &= ~_BV(PA0)

#define SET_OUT_LCD_RS DDRA |= _BV(PA0) - ten fragment kodu ustawia RS jako wyjście i RS jest skojarzony z PA0. Tylko nie rozumiem dlaczego DDRA |= _BV(PA0), a dokładniej " |= _BV(PA0) " jest 1? Bo inaczej możemy to zapisać DDRA=DDRA | _BV(PA0), domyślnie (tzn wartość początkowa) DDRA binarnie wygląda 0000 0000 tak?

Trzecie pytanie:

Może ktoś wytłumaczyć co robi ten kawałek kodu?

#define LCD_NOP asm volatile("nop\n\t""nop\n\t" "nop\n\t" "nop\n\t" :🙂;

Narazie mam tyle pytań, ponieważ nie wiem czy ktoś będzie zainteresowany odpowiedzią. Pozdrawiam.

__________

Komentarz dodany przez: Sabre

Używaj znaczników code.

Link do komentarza
Share on other sites

Pierwsze pytanie:

Zacytuje z wikibooks:

"Zapewne zapytasz się na co komu instrukcje #ifndef, #define oraz #endif. Otóż często się zdarza, że w programie korzystamy z plików nagłówkowych, które dołączają się wzajemnie. Oznaczałoby to, że w kodzie programu kilka razy pojawiła by się zawartość tego samego pliku nagłówkowego. Instrukcja #ifndef i #define temu zapobiega. Dzięki temu kompilator nie musi kilkakrotnie kompilować tego samego kodu."

Chyba jasno wyjaśnione 🙂

Drugie pytanie:

DDRA=DDRA | _BV(PA0) czyli DDRA = DDRA | 0b00000001 czyli DDRA = 0b000001

Makro _BV(bit) jest równoznaczne z (1<

Trzecie pytanie:

#define LCD_NOP asm volatile("nop\n\t""nop\n\t" "nop\n\t" "nop\n\t" :🙂;

Jest to wstawka assemblerowa, jeden "nop" oznacza nic nie rób (rozkaz procesora, jeden cykl bez robienia niczego) 🙂 wykorzystuje się to przede wszystkim do robienia opóźnień

Link do komentarza
Share on other sites

Wracając do drugiego pytania to zapis

 [b]DDRA=DDRA | _BV(PA0)[/b] 

jest równoznaczny z DDRA=DDRA | _BV(0) tak?

Wracając do pytania trzeciego możesz napisać co oznaczają te znaki n i t ? Rozumiem że modyfikator asm volatile jest użyty po to żeby kompilator nie mógł zignorować tego opóźnienia.

#define LCD_NOP asm volatile("nop\n\t""nop\n\t" "nop\n\t" "nop\n\t" :🙂;

Link do komentarza
Share on other sites

Literki \n \t oznaczają znaki ASCII, \n to nowa linia a \t to o ile się nie mylę tabulator 😉 W tym przypadku wg mnie są zupełnie niepotrzebne.

asm volatile... nie wiem po co jest użyty... być może wystarczyłoby samo "asm" co oznacza wstawkę assemblerową 🙂

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.