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

AT90S2313 - brak zmiany PORTB przy odbiorze danych z UDR przez RS232

galsan 01 Mar 2007 14:18 2180 11
REKLAMA
  • #1 3631288
    galsan
    Poziom 12  
    Posty: 94
    Witam.
    Napisałem prosty program dla testu odbierania znaków z komputera przez RS232 do ukontrolera AT90S2313.. oto program:

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


    W ogóle obsługa przerwania SIGNAL(SIG_UART_RECV) działa, widzę to po tym że zapalają się diody na płytce wg. ustawienia PORTB. Nie działa natomiast rzecz związana z przepisywaniem zawartości UDR do zmiennej znak, bo nie ma zmiany w PORTB w pętli for(;;).

    Czy wiecie może co jest nie tak?
  • REKLAMA
  • #2 3631330
    genetix
    Poziom 24  
    Posty: 669
    Pomógł: 42
    spróbuj zmienić funcję:
       SIGNAL(SIG_UART_RECV) 
       { 
          PORTB=32; 
          znak = UDR; 
       } 

    na:
       SIGNAL(SIG_UART_RECV) 
       { 
          PORTB+=1; 
          znak = UDR; 
       } 

    zobaczysz, czy odbiera ciągle znaki, czy wiesza się np. po pierwszym. Jak szybko wysyłasz bajty?

    Dodano po 2 [minuty]:

    F_CPU jest ustawione poprawnie?
  • REKLAMA
  • #4 3631371
    galsan
    Poziom 12  
    Posty: 94
    No to tak Panowie..

    Nic się nie ścina. Przy PORTB+=1 jest ok.

    volatile char znak; nic nie pomaga...

    wciąż nie ma reakcji na znak 'b' ...

    BaudRate jak widać z programu wynosi 2400.. tak samo w terminalu mam ustawione.. tak więc błąd wynosi 0%....

    ech...

    F_CPU również dobrze, 4MHZ...

    no ogólnie transmisja działa, bo przerwanie reaguje.. tylko co z tym UDR :/

    Może jeszcze jedna informacja, mianowicie, ostrzeżenie z kompilacji:

    
    Compiling: Uart.c
    avr-gcc -c -mmcu=at90s2313 -I. -gdwarf-2 -DF_CPU=4000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=Uart.lst  -std=gnu99 -MD -MP -MF .dep/Uart.o.d Uart.c -o Uart.o 
    Uart.c: In function `main':
    Uart.c:24: warning: integer overflow in expression
    Uart.c:24: warning: large integer implicitly truncated to unsigned type
    Uart.c:32:2: warning: no newline at end of file
    
    
  • #5 3631397
    genetix
    Poziom 24  
    Posty: 669
    Pomógł: 42
    galsan napisał:
    BaudRate jak widać z programu wynosi 2400.. tak samo w terminalu mam ustawione.. tak więc błąd wynosi 0%....


    No nie dokładnie 2400, bo dla 4MHz do UBRR trafia (powinna trafić) wartość 103, co daje 0,2% :D

    wstaw linię: i zobaczy się co dalej....
  • REKLAMA
  • #6 3631424
    galsan
    Poziom 12  
    Posty: 94
    Yupi yupi yupi! Działa! z UBRR=103.. jesteś boski genetix :P
    a mógłbyś jeszcze wyjaśnić co było w takim razie nie tak? zły wzór do obliczania:

    #define VUART 2400
    #define VUBRR F_CPU/(VUART*16)-1

    ?

    THX!
  • Pomocny post
    #7 3631451
    genetix
    Poziom 24  
    Posty: 669
    Pomógł: 42
    podejrzyj sobie w AVRStudio co ląduje w UBRR.

    może brakuje nawiasów?
    ((F_CPU/(VUART*16))-1)

    albo masz błąd w F_CPU, powinno być 4000000.
  • REKLAMA
  • Pomocny post
    #8 3631487
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    galsan napisał:
    ...a mógłbyś jeszcze wyjaśnić co było w takim razie nie tak? zły wzór do obliczania:
    #define VUART 2400
    #define VUBRR F_CPU/(VUART*16)-1

    GCC ma swoje "widzimisie" i potrzebuje do obliczeń , typu danych.Domyślnie przyjmuje int i stąd ostrzeżenia kompilatora.
    
    #define VUART 2400
    #define VUBRR F_CPU/(VUART*16UL)-1
    


    Piotrek
  • #9 3631526
    galsan
    Poziom 12  
    Posty: 94
    Ok, dzięki za pomoc! wszystko działa...

    PS. zumek, a co oznacza to UL przy *16 w zapisie:

    #define VUBRR F_CPU/(VUART*16UL)-1
  • #10 3631528
    genetix
    Poziom 24  
    Posty: 669
    Pomógł: 42
    unsigned long
  • #11 3631540
    galsan
    Poziom 12  
    Posty: 94
    Ahaa... a to jakiś specyficzny rodzaj rzutowania czy coś? Mógłbyś przybliżyć sprawę..? Albo podać jakieś źródło informacji na ten temat..?
  • #12 3631573
    genetix
    Poziom 24  
    Posty: 669
    Pomógł: 42
    Generalnie unsigned long oznacza liczbę długą bez znaku, w tym przypadku 32-bitową.

    VUART równe 2400 spokojnie wejdzie do zmiennej int, stała 16 też. Dlatego należy poinformować kompilator, żeby zarówno VUART jak i 16 traktował jako typ long bez znaku - gdyż w dalszej kolejności wykonywane jest dzielenie F_CPU będące zapewne również typu unsigned long. Dzięki temu zyskujemy zgodność typów.

    Dodano po 5 [minuty]:

    natomiast rzutowanie, to potraktowanie zmiennej typu int jako np. unsigned long:
    int vuart;
    vuart=2400;
    UBRR= (F_CPU/((unsigned long)vuart*(unsigned long) 16)-1);

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczył braku zmiany stanu PORTB w pętli głównej programu podczas odbioru danych przez RS232 na mikrokontrolerze AT90S2313. Przerwanie UART działało poprawnie, co potwierdzała reakcja na diody, jednak zmienna przechowująca odebrany znak (znak) nie była aktualizowana prawidłowo. Przyczyną błędu okazało się niepoprawne obliczenie wartości rejestru UBRR dla ustawienia prędkości transmisji 2400 bodów przy taktowaniu 4 MHz. Definicja makra VUBRR: F_CPU/(VUART*16)-1 powodowała błędy kompilacji i niepoprawne przypisanie wartości. Poprawne ustawienie UBRR na 103 (ręcznie) rozwiązało problem. Dodatkowo wskazano, że w makrach należy stosować typ unsigned long (np. 16UL) dla poprawności obliczeń i uniknięcia ostrzeżeń kompilatora. Zmienna znak powinna być zadeklarowana jako volatile, aby zapewnić poprawną obsługę w przerwaniu. Wyjaśniono także znaczenie sufiksu UL jako oznaczenie typu unsigned long, co jest istotne dla prawidłowego rzutowania i obliczeń w czasie kompilacji.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA