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

[ATmega32][C] RS i funkcja USART_in.

hcmateusz 29 Maj 2008 06:26 2151 10
  • #1 5193011
    hcmateusz
    Poziom 10  
    Witam. Mam problem. Napisalem program do wysylania danych przez RS z plytki ZL10AVR z mikrokontrolerem ATmega32. Dodatkowo w programie LabView na PC zrobilem odczyt jak i wysyl danych. Na dzien dzisiejszy program dziala tak, ze po wcisnieciu odpowiedniego przycisku na klawiaturze 4x4 wysylana zostaje odpowiednia dana (np: "1"). Na PC LabView odbiera oraz rozpoznaje dana. Wysylanie z ATmegi oraz odbior przez PC (LabView) odbywa sie swietne. Problem mam z odbiorem danych na ATmedze. Program LabView wydaje mi sie ze wysyla dana "A" do ATmelca, jednak wydaje mi sie ze zle uzywam funkcji USART_in. Prosze o pomoc. Program powinien odczytac z RS wyslana wczeniej dana z PC. Jezeli odbierze to na wyswietlaczu LED zapala sie wszystkie diody. Prosze o pomoc. Czekam na odpowiedz co robie zle.

    
    
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #include <avr/delay.h> 
    #include <stdlib.h> 
    
    #define CPU_Hz   8000000          
    #define OSC    8                
    #define BAUD   9600            
    #define MYUBRR  CPU_Hz/16/BAUD-1  
    
    
    
    
    // **** fukcje dla RS232 **** 
    void UART_init(unsigned int ubrr)      
    { 
       UBRRH = (unsigned char) (ubrr>>8);    
       UBRRL = (unsigned char) ubrr; 
       UCSRB = (1<<RXEN)|(1<<TXEN);          
       UCSRC = (1<<URSEL)|(3<<UCSZ0);      
    } 
    
    
    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");             // dodatkowa instrukcja opóźniająca o 1 cykl 
            
    } 
    
    int button1={0B00000110}; 
    int button2={0B01011011}; 
    int button3={0B01001111}; 
    int button4={0B01100110}; 
    int all={0B01111111}; 
    
    //**** program glowny 
    int main(void) 
    { 
    
    
    DDRD=0x00; //klawa ustawiona jako wejscie 00000000 
    PORTD=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 odbiorA; 
       odbiorA=65; //dana "A" 
    //---------------------- 
    
    
    
    
    DDRA = 0xFF; 
    DDRB = 0xFF; 
    PORTA = 0xFF; 
    PORTB = 0x01; 
    
    
    while (1) { 
    _delay_ms(250); 
    _delay_ms(250); 
    _delay_ms(250); 
    _delay_ms(250); 
    _delay_ms(250); 
    _delay_ms(250); 
    
    
    if (PIND==0xFE){ 
    PORTB = 2; 
    PORTA = button1; 
    _delay_ms(8); 
    UART_init(MYUBRR); 
    USART_out(przycisk1); 
    
    } 
    
    
    
    if (PIND==0xFD){ 
    PORTB=2; 
    PORTA=button2; 
    _delay_ms(8); 
    UART_init(MYUBRR); 
    USART_out(przycisk2); 
    } 
    
    
    
    if (PIND==0xFB){ 
    PORTB=2; 
    PORTA=button3; 
    _delay_ms(8); 
    UART_init(MYUBRR); 
    USART_out(przycisk3); 
    
    } 
    
    
    
    if (PIND==0xF7){ 
    PORTB=2; 
    PORTA=button4; 
    _delay_ms(8); 
    UART_init(MYUBRR); 
    USART_out(przycisk4); 
    
    } 
    //---------Chodzi gownie o ta czesc prog-czyli odbior 
    //---------Mozliwe ze nie moge uzywac USART_in() w warunku if 
    //---------Chcialbym sie dowiedziec czy skladnia jest ok i czy powinno dzialac 
    char temp; 
    temp=USART_in(); 
    if (temp==odbiorA) { 
    PORTB=8; 
    PORTA=all; } 
    
    } 
    }



    Poprawiłem tytuł:
    https://www.elektroda.pl/rtvforum/topic1015361.html
    [c_p]
  • #3 5200188
    hcmateusz
    Poziom 10  
    Myślełem bardziej o takim rozwiązaniu.
    Zastąpić ten kawałek kodu:
    
    char temp; 
    temp=USART_in(); 
    if (temp==odbiorA) { 
    PORTB=8; 
    PORTA=all; }
    

    Tym:
    
    SIGNAL (SIG_UART_RECV) 
    { 
       unsigned char byte; 
       byte = UDR; 
      
       if (byte=='A')   // lub if (byte==odbiorA) 
       { 
    PORTB=8; 
    PORTA=all; 
       } 
    }
    


    Czy to by było dobre rozwiązanie????
    Możliwość sprawdzenia tego będę miał we wtorek. Lecz chciałbym mieć już pewność.
  • #4 5200328
    tomsyty

    Poziom 26  
    Tak, ten fragment z przerwaniem wygląda dobrze, powinien działać, skonfiguruj tylko obsługę przerwań i powinno być OK. Co do poprzedniego, spróbuj może wyrzucić deklarację zmiennej temp poza pętlę - nie wiem jak się program zachowuje, gdy w pętli while tworzona jest zmienna, czy za każym przejściem tworzy ją od nowa, czy tworzy nową zmienną, a może optymalizacja ją sama przeniosła poza pętlę... Możesz również zadeklarować ją jako volatile. No i pytanie, czy dane przesyłane z PC nie są przypadkiem zakończone znakiem CRLF.
  • #5 5200748
    hcmateusz
    Poziom 10  
    Przepraszam, ale jak mam skonfigurować przerwania?? Myślałem że wystarczy na początku prog podać
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    To przerwania należy jeszcze konfigurować?
    Poproszę przerobić mój kod jeżeli jest to możliwe.
  • #7 5201549
    hcmateusz
    Poziom 10  
    Dziekuje za pomoc. Czyli mam to wrzucic najlepiej w sama inicjacje USART? czyli:
    
    void UART_init(unsigned int ubrr)      
    { 
       UBRRH = (unsigned char) (ubrr>>8);    
       UBRRL = (unsigned char) ubrr; 
       // UCSRB = (1<<RXEN)|(1<<TXEN);    *** To zanegować ??
       UCSRC = (1<<URSEL)|(3<<UCSZ0);        
       //--------------------------------------------------------  
       UCSRB = 1<<RXCIE | 1<<TXCIE | 1<<RXEN; 
       sei();  // *** To dopisac ??
       //--------------------------------------------------------
    }
    


    To juz bedzie ostatnie :)
  • #8 5202119
    tomsyty

    Poziom 26  
    Zamiast TXCIE ma być TXEN, kolega chyba z rozpędu pisał, TXCIE jest od przerwania przy nadawaniu a tego nie wykorzystujesz.
  • #9 5202876
    hcmateusz
    Poziom 10  
    OK. Fajnie. Czyli powinno to wyglądać tak:
    Przy inicjacji USART:
    
    void UART_init(unsigned int ubrr)      
    { 
       UBRRH = (unsigned char) (ubrr>>8);    
       UBRRL = (unsigned char) ubrr; 
       UCSRB = (1<<RXCIE) | (1<<TXEN) | (1<<RXEN); 
       UCSRC = (1<<URSEL)|(3<<UCSZ0);      
    } 
    

    No i oczywiście w prog głównym czyli po main:
    
    sei();  //to jest jakaś funkcja prog, nie należy nigdzie wcześniej jej inicjować??
    

    No i dalsza część programu. Czyli odbiór danej w przerwaniu:
    
    SIGNAL (SIG_UART_RECV) 
    { 
       unsigned char byte; 
       byte = UDR; 
      
       if (byte=='A')   // lub if (byte==odbiorA) 
       { 
    PORTB=8; 
    PORTA=all; 
       } 
    }
    


    I to wszystko powinno cykać jak należy?
  • #10 5203172
    tomsyty

    Poziom 26  
    Tak, tak, domyślam się że masz to na studiach i nie posiadasz własnego sprzętu w domu, ale spokojnie, powinno działać.
  • #11 5203217
    sheeeep
    Poziom 25  
    tomsyty napisał:
    Zamiast TXCIE ma być TXEN, kolega chyba z rozpędu pisał, TXCIE jest od przerwania przy nadawaniu a tego nie wykorzystujesz.


    Faktycznie, moje przeoczenie. A teraz całość wygląda poprawnie więc nie powinno być żadnych niespodzianek.

    pozdrawiam
REKLAMA