Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

ATmega32, obsługa LCD - AVRStudio, Problem

11 Mar 2008 12:36 1528 2
  • Poziom 10  
    Witam. Mam problem, podejrzewam z opóźnieniami w inicjacji LCD. Mam do zrobienia komunikacje szeregową pomiedzy ZL10AVR z ATmega32 a komputerem PC. Program działa tak, że jak nacisnę przycisk 1 (S12) to na komputerze uruchamia sie program notatnik (to zrobilem w programie LabView - ale to nie wazne). Chodzi mi o to - jak nacisnę ten przycisk to na wyświetlaczu LCD (hd44780) ma mi wyswietlic napis (np. Uruchamiam notepad). I problem w tym, że jak umieszcze komendę wysyłającą znaki w pętli while, na LCD powstają zupełnie inne litery. Słyszałem, że mam nie odpowiednie opóźnienia. Nie jestem na wysokim poziomie programowania AVR więc nie mogę sobie poradzić. Proszę o pomoc. Niżej umieszczam kod programu:

    Code:


    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <avr/delay.h>
    #include <stdlib.h>

    #define CPU_Hz   8000000               // częstotliwość zegara w Hz
    #define OSC    8                  // częstotliwość zegara w MHz
    #define BAUD   9600               // prędkość transmisji po RS232
    #define MYUBRR  CPU_Hz/16/BAUD-1   

    // **** fukcje dla RS232 ****
    void UART_init(unsigned int ubrr)       // inicjalizacja
    {
       UBRRH = (unsigned char) (ubrr>>8);   // ustawienie prędkości
       UBRRL = (unsigned char) ubrr;
       UCSRB = (1<<RXEN)|(1<<TXEN);         // transmisja dwukierunkowa,
       UCSRC = (1<<URSEL)|(3<<UCSZ0);      // 8 bit danych i 1 bit stopu
    }

    void USART_out (unsigned char data)    // wysłanie znaku
    {
       while (!(UCSRA & (1<<UDRE)));
       UDR = data;
    }

    unsigned char USART_in (void)    // odebranie znaku
    {
       while (!(UCSRA & (1<<RXC)));
       return UDR;
    }

    // **** funkcja czasowa ****
    void waitms(unsigned char czas)
    {
       unsigned char a, b;                // zmnienne licznikowe
       for( ; czas > 0; --czas)                // ta pętla zostanie wykonana x-razy
          for(b = 10; b > 0; --b)          // a ta 10 razy
             for(a = 25 * OSC; a > 0; --a)    // natomiast ta 100 razy
                __asm("nop");             // instrukcja opóźniająca o 1 cykl
    }

    //Funkcja sterująca sygnałem E
    void lcd_e(unsigned char e){
       
       if(e!=0)
          //jeżeli argument funkcji rózny
          //od zera sygnał E zostaje ustawiony
          PORTB=PORTB|(1<<2);
       else
          PORTB=PORTB&~(1<<2);
    }

    //Funkcja sterująca sygnałem RW
    void lcd_rw(unsigned char rw){
       
       if(rw!=0)
          PORTB=PORTB|(1<<1);
       else
          PORTB=PORTB&~(1<<1);
    }

    //Funkcja sterująca sygnałem RS
    void lcd_rs(unsigned char rs){
       
       if(rs!=0)
          PORTB=PORTB|1;
       else
          PORTB=PORTB&~1;
    }

    //Funkcja wysyłająca komendę
    //w trybie ośmio bitowym
    void lcd_send_cmd(unsigned char cmd){

       lcd_rs(0);
       lcd_rw(0);
       lcd_e(1);
       PORTD=cmd;
       lcd_e(0);
    }

    //Funkcja wysyłająca daną
    //w trybie ośmio bitowym
    void lcd_send_data(unsigned char data){

       lcd_rs(1);
       lcd_rw(0);
       lcd_e(1);
       PORTD=data;
       lcd_e(0);
    }


    // **** program główny ****
    int main(void)                       
    {
       //inicjalizacja
       //wszystkie sygnały sterujące zostają wyzerowane
       lcd_rw(0);
       lcd_rs(0);
       lcd_e(0);
       //wszystkie linie danych otrzymują stan niski
       lcd_send_data(0);
       
       //PORTD ustawiony jako wyjście - dane
       DDRD=DDRD|0xff;
       
       //PORTB ustawiony jako wyjście - sygnały sterujące
       DDRB=DDRB|0x07;
       
       _delay_ms(80);
       
       
       //0x38=
       //00111000b
       //--1----- kod specyficzny komendy Function set (tabela 6 [6])
       //---1---- DL=1   - transmisja ośmio bitowa
       //----1--- N=1   - wyświetlacz stanowi dwie linie
       //-----0-- F=0   - wielkość czcionki 5 x 8 pikseli
       lcd_send_cmd(0x38);
       //żądane opóźnienie
       _delay_us(38);
       
       //0xf=
       //00001111b
       //----1--- kod specyficzny komendy Display on/off Control
       //-----1-- D=1   - wyświetlacz załączony
       //------1- C=1   - kursor załączony
       //-------1 B=1   - migotanie znaku
       lcd_send_cmd(0x0f);
       _delay_us(38);
       
       //0x06=
       //00000110
       //-----1-- kod specyficzny komendy Entry mode set
       //------1- I/D=1   - inkrementacja położenia kursora
       //-------0 S=0   - wyświetlany obraz pozostaje w spoczynku
       lcd_send_cmd(0x06);
       _delay_us(38);
       
       //0x01=
       //00000001
       //-------1 kod specyficzny komendy Clear Display
       //czyści ekran i ustawia adres DDRAM=0
       lcd_send_cmd(0x01);
       _delay_ms(1.52);
       

       
       
       
          

    //----------------------------------------------------------------------------------
    DDRA=0x00; //klawa ustawiona jako wejscie 00000000
    PORTA=0xFF;//port ustawiony jako wyjscie 11111111
    //----------------------------------------------------------------------------------


          
       int i; int j; int x; int z;
       char przycisk1; //inicjacja na przycisk 1
       char przycisk2; //inicjacja na przycisk 2
       char przycisk3; //inicjacja na przycisk 3
       char przycisk4; //inicjacja na przycisk 4


       przycisk1=49;   przycisk2=50;   przycisk3=51;
    przycisk4=52;


             
             char znaki[]={"11\n11"};
             unsigned char q=0;
       

       UART_init(MYUBRR);               // Inicjalizacja RS232

    while (1) {
    _delay_ms(250);
    _delay_ms(250);
    _delay_ms(250);
    _delay_ms(250);



    if (PINA==0xFE){
             
                USART_out(przycisk1);

             while(znaki[q]!=0){                  //1
             if(znaki[q]=='\n')                     //1 w wprzypadku nowej linii
                lcd_send_cmd(0xc0);                  //1 adres DDRAM zostaje zmieniony na 0x40
             else                              //1
                lcd_send_data(znaki[q]);            //1
             q++;                              //1
             _delay_us(37);                        //1
             }               

       //while(1){                                 //1 zatrzymanie na końcu kodu
       //};
       }   
                      

              

    if (PINA==0xFD){
          
          USART_out(przycisk2);
          
              }

    if (PINA==0xFB){
          
          USART_out(przycisk3);
          
              }

    if (PINA==0xF7){
          
          USART_out(przycisk4);
             
              }

    };
    }


    /*UBRRH, UBRRL - służy do ustawiania prędkości transmisji UART*/




    Z góry dziękuję za pomoc. Pozdrawiam serdecznie.
    Hcmateusz.
  • Pomocny dla użytkowników
    Przed zapisem polecenia do wyświetlacza powinieneś badać stan bitu BUSY (na linii DB7 dla RS=0 i R/W=1) stan 1 oznacza, że trzewia wyświetlacza trawią poprzednie dane i trzeba czekać.

    Ewentualnie daj większe opóźnienia, np 50us i 2ms dla kasowania ekranu.

    Czasy wykonywania operacji wewnętrznych w wyświelaczu są zmienne, jedne się wykonują w ok 40us ale są i takie co potrzebują 1.7 ms (np. kasowanie wyświetlacza). Czasy te są podawane dla częśtotliwości zegara wewnętrznego wyświewtlacza = 250kHz ale ta warotść może się różnić w różnych egzemplarzach.
  • VIP Zasłużony dla elektroda
    Przenoszę z "Początkujący, Laborki, .......".