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

[ATTiny2313/AT90S2313][C/AVR gcc] Przerwania i RS232

Skyttop 01 Kwi 2009 22:37 2999 3
  • #1 6364378
    Skyttop
    Poziom 11  
    Witam

    Od dwóch dni borykam się z pewnym problemem. Mam 2 mikrokontrolery: ATTiny2313 i AT90S2313. W tematach na elektrodzie znalazłem taki oto banalny program, odbierający znaki przez RS232 na przerwaniach, napisany dla AT90S2313:

    
    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #include <stdlib.h> 
    
    #define F_CPU 4000000UL
    #define UART_BAUD 19200
    #define UART_CONST (F_CPU/(16ul*UART_BAUD)-1)
    
    volatile char znak; 
    
       SIGNAL(SIG_UART_RECV) 
       { 
          PORTB=32; 
          znak = UDR; 
       } 
    
    int main(void){ 
    
       DDRD = 126; 
       DDRB = 255; 
       PORTB = 0; 
       PORTD=2; 
        
       UBRR=(unsigned char)UART_CONST;
       UCR = 1<<RXCIE | 1<<RXEN; 
       sei(); 
    
       for(;;)
       { 
          if(znak=='b') 
             PORTB=64; 
       } 
    }
    


    Po skompilowaniu i załadowaniu program działa poprawnie, czyli jeśli z terminala do mikrokontrolera wyślę znak 'b', to na wyświetlaczu LED zapalają się zera. Problem jest z ATTiny2313, a więc następujący kod:

    
    #include <stdlib.h> 
    
    #define F_CPU 4000000UL
    #define UART_BAUD 19200
    #define UART_CONST (F_CPU/(16ul*UART_BAUD)-1)
    
    volatile char znak; 
    
       SIGNAL(SIG_UART_RECV) 
       { 
          PORTB=32; 
          znak = UDR; 
       } 
    
    int main(void)
    { 
    
    	DDRD = 126; 
    	DDRB = 255; 
    	PORTB = 0; 
     	PORTD=2;
    
    
    	UBRRH = (unsigned char)(UART_CONST>>8);
    	UBRRL = (unsigned char)UART_CONST;
    													/* Enable receiver and transmitter */
    	UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
    													/* Set frame format: 8data, 2stop bit */
    	UCSRC = 1<<UCSZ1 | 1<<UCSZ0 | 0<<USBS;			//ramka 8bit, 1 bit stopu 
    	sei(); 
    
       for(;;)
       { 
          if(znak=='b') 
             PORTB=64; 
       } 
    } 
    


    już niestety tego nie robi. Nie reaguje na żadne znaki, tak jakby przerwanie nie było obsługiwane. Oczywiście mogę skompilować program dla AT90S2313 i załadować go do ATTiny2313 i będzie działał, ale nie tędy droga. Chcę mieć dostęp do wszystkich danych rejestrów UART i aby przerwanie było obsługiwane.
    Gdzie jest błąd?
  • #2 6365034
    mirekk36
    Poziom 42  
    AT90S2313 -> jak zapewne wiesz MUSI mieć zewnętrzny kwarc bo inaczej nie będzie działał - i jak się domyślam na pewno dałeś kwarc 4MHz (jak wynika z kodu i wszystko w nim działa)

    jeśli chodzi o ATtiny2313 - to po zakupie działa on na wewnętrzym oscylatorze 1MHz a nie na kwarcu - nawet jeśli jest on podłączony.

    Tak więc podstawowe pytanie jak zawsze w tego typu przypadkach - czy zmieniłeś ustawienia FuseBitów ??? żeby tiny mógł działać na zewnętrznym kwarcu 4MHz albo czy zmieniłeś je tak - aby działał na wewn. oscylatorze ale z częstotliwością 4MHz ??? zamiast domyślnej 1MHz ???
  • #3 6365169
    Skyttop
    Poziom 11  
    Tak, właśnie tu był problem!
    Nie ustawiłem 4MHz, teraz jest już wszystko dobrze. Dziękuję i pozdrawiam!
  • #4 6369759
    Skyttop
    Poziom 11  
    Chciałbym jeszcze dodać, że problem był nie tylko po stronie fusebitów. Dla ATtiny2313 inaczej wyglądają uchwyty przerwań. Kompilator ostrzegał zresztą przed tym, że uchwyt jest niewłaściwy. Przed zaprogramowaniem uC zawsze należy zapoznać się z jego plikiem nagłówkowym, o czym mówiono wiele razy ale nie zawsze ta zasada jest przestrzegana. Dla ATtiny2313 program powinien wyglądać następująco:

    
    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    #include <stdlib.h> 
    
    #define F_CPU 4000000UL
    #define UART_BAUD 19200
    #define UART_CONST (F_CPU/(16ul*UART_BAUD)-1)
    
    volatile char znak; 
    
       SIGNAL(SIG_USART0_RECV) 
       { 
          PORTB=32; 
          znak = UDR; 
       } 
    
    int main(void)
    { 
    
    	DDRD = 126; 
    	DDRB = 255; 
    	PORTB = 0; 
     	PORTD=2;
    
    
    	UBRRH = (unsigned char)(UART_CONST>>8);
    	UBRRL = (unsigned char)UART_CONST;
    													/* Enable receiver and transmitter */
    	UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
    													/* Set frame format: 8data, 2stop bit */
    	UCSRC = 1<<UCSZ1 | 1<<UCSZ0 | 0<<USBS;			//ramka 8bit, 1 bit stopu 
    	sei(); 
    
       for(;;)
       { 
          if(znak=='b') 
             PORTB=64; 
       } 
    } 
    


    Dopiero teraz wszystko śmiga jak należy. Pozdrawiam!
REKLAMA