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

[ATmega16][C] UART i przerwanie po resecie

Myrek1 11 Wrz 2008 20:34 2000 11
REKLAMA
  • #1 5526559
    Myrek1
    Poziom 23  
    Witam.
    Mam kod, w którym Atmega ma wysłać na kompa dane dopiero wtedy jak komp wyśle ramkę 0b01111111. Zatrzymanie wystąpi po wysłaniu z kompa 0b00000000 (stan początkowy Atmegi, nic nie wysyła). Komenda 0b1xxxxxxx oznacza odczyt konkretnego urządzenia.
    Każda przesłana komenda ustawia odpowiednią flagę, która sygnalizuje działanie.

    Odbiór z kompa (Rx) działa w przerwaniu, oto kod:

    ISR(SIG_UART_RECV)
    {
    		uart_bufor = UDR;
    		if (uart_bufor == 0x7F)
    			{
    				flaga = 1;// start
    			}
    		else if ((uart_bufor>>7) == 1)
    			{
    				flaga = 2; //odczyt konkretnego urzadzenia
    			}
    		else
    			{
    				flaga = 0; //stop
    			}
    }
    
    void uart_init(void)
    {
    	UBRRH = (unsigned char) (ZAWARTOSC_UBRR >> 8); //ustawienie prędkości
    	UBRRL = (unsigned char) ZAWARTOSC_UBRR;
    	UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); //8bitowe slowo, bit parzystosci, bit stopu
    	UCSRB = _BV(RXEN)| _BV(TXEN) | _BV(RXCIE);
    
    }


    I po uruchomieniu programu automatycznie następuje wpisanie do flaga wartości 2.
    Widać więc, że następuje przerwanie. Dlaczego skoro nic nie wysyłam do procka? Po odpaleniu flaga powinna być równa 0 i program powinien czekać na daną z kompa. A teraz od razu wysyła dane, więc występuje przerwanie.
    Czy to wina terminala? Czy terminal po podłączeniu wysyła jakąś daną, która ma na najstarszym bicie 1 i uaktywnia mi flagę?

    Gdy wrzucę do przerwania instrukcję wysłania z powrotem zawartości UDR do kompa to w terminalu mam takie wartości:

    00 F8 00 FC 00 00 00 00  00 00 00 00 00 FC 00 00    .ř.ü.... .....ü.. 
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........ ........ 
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........ ........ 
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........ ........ 
    00 00 00 00 00 00 00 80  20 00 00 80 40 00 00 40    .......€  ..€@..@ 
    40 40 00 20 00 10 10 00  00 00 04 80 10 10 84 80    @@. .... ...€..„€ 
    00 00 08 08 40 04 04 20  00 22 12 20 02 20 02 20    ....@..  .". . .  
    12 00 80 90 10 12 48 40  00 40 49 48 40 40 48 08    ..€�..H@ .@IH@@H. 
    08 08 08 08 08 28 81 A1  A5 05 85 15 05 15 55 55    .....(�ˇ Ą.…...UU 
    55 55 15 55 55 FD 


    Skąd przychodzą te dane? Przecież z kompa nic nie wysyłam? I to nie jest z terminala, bo w czasie resetu procka port jest cały czas otwarty, wiec to nie jakieś dane startowe z terminala.
  • REKLAMA
  • #2 5527303
    markosik20
    Poziom 33  
    Myrek1 napisał:

    I po uruchomieniu programu automatycznie następuje wpisanie do flaga wartości 2.
    Widać więc, że następuje przerwanie. Dlaczego skoro nic nie wysyłam do procka? Po odpaleniu flaga powinna być równa 0...


    Może jeszcze gdzieś w programie przypisujesz jej taką wartość (niekoniecznie w przerwaniu)?
    A po odpaleniu (resecie) to flaga wcale nie musi mieć wartości zero (no chyba że przy deklaracji wpiszesz do niej zero).
  • REKLAMA
  • #3 5527311
    Myrek1
    Poziom 23  
    Ma 0, nie ma innego przypisania. Zresztą po resecie widać, że Rx przyjmuje jakieś wartości wyjęte nie wiadomo skąd. Reagując na jedną z otrzymanych wartości flaga rzeczywiście przyjmuje 2. Pytanie dlaczego występuje przerwanie po resecie i są odbierane te dziwne wartości złapane w terminalu.
    Przypominam, że wiem jakie to wartości bo w przerwaniu dałem odczyt z rejestru i funkcje wysłania tej danej do kompa. Stąd wiem jakie tam występują.
  • #4 5527380
    markosik20
    Poziom 33  
    Myrek1 napisał:
    Zresztą po resecie widać, że Rx przyjmuje jakieś wartości wyjęte nie wiadomo skąd.


    W takim razie linię RxD odłącz od PC i podciągnij do Vcc od strony uC. Ja zawsze daję LED na Rx i Tx i w ten sposób widzę (na oczy) :wink: co się dzieje na liniach.
  • REKLAMA
  • #5 5527520
    Myrek1
    Poziom 23  
    Po co pod Vcc? Co zobaczę na LEDach przy prędkości ponad 100 000b/s?
    Mam podłączonego LEDa, który włącza się w przerwaniu i zeruje poza nim. I po resecie procka czy włączeniu mu zasilania mryga na ułamek sekundy. Tak więc wchodzi w przerwanie i odbiera dane z "kosmosu". Dlaczego? Tych danych jest tylko kilkadziesiąt bajtów.
  • #6 5527892
    markosik20
    Poziom 33  
    Myrek1 napisał:
    Po co pod Vcc?


    Po to żeby mieć pewniość że problem nie leży po stronie sprzętowej.
  • #7 5528076
    Myrek1
    Poziom 23  
    Ale dlaczego niby sprzętowa? Przecież żeby odebrać daną musi być poprawny bit startu i stopu. Do tego, jakby to była wina sprzętu to te dane przychodziły by w różnym czasie, a przychodzą tylko po uruchomieniu. Później jest ok.

    Działam na przejściówce na FTDI, ale to chyba nie ma znaczenia.
  • #8 5528857
    bobbyAIR
    Poziom 20  
    Żeby odebrać wystarczy bit startu a nawet nie bit tylko jego początkowe zbocze. Potem kotroler sobie próbkuje i jest bajt odebrany. Czy poprawny to druga sprawa - odebrany będzie i zgłosi się przerwanie!!
    FTDI ma wbudowane pullupy która załącza jesli trzeba - na lini Rx kontrolera zawsze, na linii Tx jeśli trzeba

    Mnie ciekawi od samego początku ile wynosi ZAWARTOSC_UBRR oraz jakiego typu jest uart_bufor

    Ja rozumiem ideę umieszczania istotnych fragmentów kodu ale dobrze jeśli sa kompletne
  • REKLAMA
  • #9 5529512
    Myrek1
    Poziom 23  
    Oto te definicje.

    #define FOSC 3686400 //predkosc zegara
    #define BAUD 115200
    #define ZAWARTOSC_UBRR (FOSC/16/BAUD)-1
    
    unsigned char uart_bufor;
    volatile unsigned char flaga=0, flaga2=0;
  • #10 5529899
    bobbyAIR
    Poziom 20  
    po pierwsze pomijając wartości
    
    #define F_CPU            14745600ul
    /// UART
    #define UART_BAUD         115200ul
    #define UART_CONST        (F_CPU/(16ul*UART_BAUD)-1)
    

    ja tu pomijam fakt, że dzielenie to mnożenie przez odwrotnośc tylko chodzi mi o nawiasy których ci brakuje ( i pewnie to żle konfiguruje zegar tworząc przekłamania)

    Po drugie wszystkie zmienne globalne z jakich korzystają przerwania muszą mieć atrybut volatile (looknij w kod avrlibc)
    
    volatile unsigned char uart_bufor; 
    
  • #11 5531214
    Myrek1
    Poziom 23  
    Obliczenie UART_CONST jest ok, działa i taki wzór stosowany jest w wielu projektach. Przy takim dzieleniu nie trzeba nawiasów.

    dodanie volatile do zmiennej nic nie dało, dalej po starcie z RX płyną jakieś dane.
  • #12 5535371
    bobbyAIR
    Poziom 20  
    Może po prostu dołącz cały kod. Bo tak chyba nic nie znajdziemy
REKLAMA