logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Atmega128, AVR Studio, WinAVR Problem z prostym kodem

piwcci 16 Lut 2010 18:52 1852 6
  • #1 7704151
    piwcci
    Poziom 12  
    Witam serdecznie,
    mam mały problem z moim urządzeniem. Zbudowałem kiedyś płytkę ewaluacyjna dla Atmegi128, nigdy nie miałem z nią większego problemu. Mam teraz jednak problem. Jak zawsze chciałem ją oprogramować ale cos jest nie tak. Poniżej zamieszczam kod i tłumacze o co mi chodzi.

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdlib.h>
    
    //#define F_CPU 14.7456E6
    #define F_CPU 16E6
    #include <util/delay.h>
    
    #define LCD  PORTA
    #define E  3
    #define RS  2
    #include "lcd.h"
           
    #define BAUD	4800            
    #define MYUBRR F_CPU/16/BAUD-1
    
    
    /******************************************************************************/
    /****** ** *                     OBŁUGA USART0						* ** ******/
    /******************************************************************************/
    
    /************************Zmienne globalne portu USART0*************************/
    char rxGsm[30];											//bufor znaków odebranych z modułu GSM
    int iterGsm = 0;										//iterator odbieranych znaków
    int enterRx = 0;
    
    char x;												//flaga odebrania wiadomosci 
    /**********************Ustawienei parametrów portu USART0**********************/
    void USART_Init( unsigned int baud ) { 
    		UBRR0H = (unsigned char)(baud>>8); 
    		UBRR0L = (unsigned char)baud;  
    		UCSR0A = 0;
    		UCSR0B = 0; 
    		UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
    }
    /*****************************Odbiór danych z USART0***************************/
    SIGNAL(SIG_USART0_RECV){
    	rxGsm[iterGsm] = UDR0;		
    															
    			if(rxGsm[iterGsm] == 0x0D){
    					UCSR0B = (0<<RXEN0)|(0<<RXCIE0);			// zakończ przerwania i odbiór
    					iterGsm = 0;								// wyzeruj licznik
    					enterRx=1;
    					write_text("e");
    			}
    			else{
    				iterGsm++;
    				write_char(rxGsm[iterGsm]);										//iteracja
    			}		
    }
    
    /******************************************************************************/
    /****** ** *                     PROGRAM GŁÓWNY						* ** ******/
    /******************************************************************************/
    int main(void)
    {
    	sei();
    	DDRA = 0xFF;
    	PORTA = 0xFF;
    	lcd_init();
    	USART_Init(MYUBRR);
    	UCSR0B = (1<<RXEN0)|(1<<RXCIE0);
    
    		while(1)
    		{
    			if(enterRx == '1'){
    				enterRx = 0;
    				write_text("p");
    				UCSR0B = (1<<RXEN0)|(1<<RXCIE0);
    			}		
    		}	
    
    return 0;
    }
    


    Powyżej przedstawiony kod ma za zadanie odbieranie ciągów znaków do tablicy rxGSM. W momencie kiedy moduł otrzyma znak końca linii 0x0D wówczas na wyświetlaczu ma sie pojawić ciąg literek p. Niestety tak sie nie dzieje. Po odebraniu znaku końca linii wyświetla literkę "e", zablokowany zostaje odbiór ale program nigdy nie wchodzi do pętli while(1).
    Najśmieszniejsze w tym wszystkim jest to, że cała ta procedura działa kiedyś.
    Kod tworze w AvrStudio a kompilator to WinAVR.
    Zastanawiam sie teraz czy wina leży po stronie sprzętu(płyta ewalucayjna służy mi juz dłuższy czas) czy tez może z kompilatorem coś jest nie tak.
    Czy kompilator przez przypadek nie powinien ostrzegać mnie o tym ze została zdefiniowaną zmienna

    a nigdzie jej nie używam???

    Będę wdzięczny za wszelka pomoc
    Pozdrawiam
    Paweł
  • Pomocny post
    #2 7704404
    mirekk36
    Poziom 42  
    piwcci napisał:
    Zastanawiam sie teraz czy wina leży po stronie sprzętu(płyta ewalucayjna służy mi juz dłuższy czas) czy tez może z kompilatorem coś jest nie tak.


    Taa, dobre - jak zwykle gdy się zbaboli (czyli źle napisze) program i nie wie się jak rozwiązać problem to od razu winny kompilator albo sprzęt, procek itp

    Nie panie kolego wina leży tylko i wyłącznie po twojej stronie, myślisz że jesteś pierwszą na świecie osobą, która wykryła błędy kompilatora albo procesora ????

    Generalnie sam pomysł wyświetlania na LCD w przerwaniu to już masakra. Poza tym kto wie co to za twoje procedury do wyświetlania ? Jeśli one są podobnie napisane to może to właśnie one są winne ..... szukaj błędu u siebie.
  • Pomocny post
    #3 7704433
    morson
    Poziom 14  
    Znalazłem conajmniej 2 błędy
    1. Zadeklaruj enterRx jako volatile
    2. Najpierw przypisujesz zmiennej enterRx wartość 1, a potem sprawdzasz czy zmienna ma wartość '1' (czyli 49)

    Spróbuj z tymi 2 zmianami i powinno zacząć chodzić

    Mirekk36, może on ma procedury LCD buforowane (ja zwykle takich używam), wtedy to niebyłby taki wielki błąd, ale wnikał niebędę.
  • #4 7704716
    mirekk36
    Poziom 42  
    morson napisał:

    Mirekk36, może on ma procedury LCD buforowane (ja zwykle takich używam), wtedy to niebyłby taki wielki błąd, ale wnikał niebędę.


    Może i ma - może i nie ma - tego to my nie wiemy. Ale jak nie ma - to nie powiesz że to nie jest wielki błąd.
  • #5 7705354
    piwcci
    Poziom 12  
    Panowie cały ten bałagan z wykorzystaniem wyświetlacza lcd miał na celu znalezienie błędu. Chciałem po prostu sprawdzić co się dzieje. Docelowo przerwanie wyglądało w taki sposób:
    
    SIGNAL(SIG_USART0_RECV){
    	rxGsm[iterGsm] = UDR0;				
    			if(rxGsm[iterGsm] == 0x0D){
    					UCSR0B = (0<<RXEN0)|(0<<RXCIE0);
    					iterGsm = 0;				
    					enterRx=1;
    			}
    			else{
    				iterGsm++;
    			}		
    }
    

    To wszystko wcześniej działało.
    Sprawdzę to jeszcze na zwykłej diodzie.

    Dodano po 51 [minuty]:

    Dobra, przejrzałem to i wszystko gra. Błąd to oczywiście wartość '1'. Generalnie moja wina i sie przyznaje, nie jestem super programistą. W związku z tym mam jeszcze kilka pytań:
    1. modyfikator volatile informuje kompilator, że ma sie zawsze odnosić bezpośrednio do zmiennej i nie brany jest pod uwage podczas optymalizacji. Jakie skutki mogło to mieć w moim przypadku kiedy zmienna będąca "flaga" nie była typu volatile???
    2. zostało coś powiedziane na temat buforowej obsługi wyświetlacza. Czym ona sie różni od zwykłej obsługi???
    3. wracając do mojego pytania z pierwszego postu, czy kompilator nie powinien sygnalizować tego ze zadeklarowałem zmienną x a jej nie używam. (Pamiętam, że kiedyś własnie tak było i teraz sie zastanawiam czy przez przypadek czegos nie pozmieniałem).
  • #6 7705897
    mirekk36
    Poziom 42  
    1. takie skutki, że w pętli głównej dzięki optymalizacji bez volatile wrzucił sobie kompilator tą zmienną do rejestru i tylko do niego się odwoływał a w przerwaniu podobnie, w związku z tym zarówno w pętli głównej jak i w przerwaniu widoczne były inne wartości i to jest normalne

    2. zwykła obsługa wymaga sporych ilości czasu na przesłanie danych do LCD a buforowa może polegać na tym, że dane do wyświetlania wrzucane są tylko do pamięci - bufora , a gdzieś indziej - np w pętli głównej są dopiero wyrzucane naprawdę na LCD

    3. powinieneś mieć ostrzeżenie: "warning: unused variable x" - chyba że gdzieś w opcjach wyłączyłeś sobie warningi
  • #7 7705994
    piwcci
    Poziom 12  
    Ok, bardzo dziekuje za pomoc. Zamykam temat
    Pozdrawiam
REKLAMA