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

Problem z komunikacją UART

xyzboro 24 Lut 2011 21:48 2335 18
  • #1 9199743
    xyzboro
    Poziom 10  
    Witam szanownych kolegów i koleżanki!

    Jestem początkującym forumowiczem i zaczynam swoją przygodę z mikrokontrolerami AVR.
    Całkiem nie tak dawno wpadł mi do łap procek AT90PWM3b i docelowo chciałbym sterować PWMami. Natomiast teraz zatrzymałem się nad komunikacją tego mikrokontrolera z ATMEGA16.
    Poniżej wklejam cod, który napisałem do AT90PWM i pokazuje mi na atmedze16 jakiś krzaczki...;/
    Proszę o pomoc, co jest nie tak.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 9200091
    LordBlick
    VIP Zasłużony dla elektroda
    xyzboro napisał:
    pokazuje mi na atmedze16 jakiś krzaczki...;/
    A może je ujawnisz, czy to jakiś niecenzuralny tekst ? ;)
    xyzboro napisał:
    Proszę o pomoc, co jest nie tak.
    Tak na pierwszy rzut oka:
    #define F_CPU 6400000UL                    // 1MHz wewnetrzny 
    1. Takie sprawy to podaje się w Makefile obok "modelu" procesora...
    2. Skoro jest 1MHz, to dlaczego zdefiniowano 6.4MHz ?
    #define BAUD 9600UL                        // predkosc transmisji 
    Drobna korekta definicji BAUDRATE i powinno być dobrze:
    #define MYUBRR (F_CPU/BAUD/16-1)
    Jako pracę domową polecam w google hasło "volatile site:elektroda.pl", zwłaszcza dla zmiennych a i c...
  • #3 9204780
    xyzboro
    Poziom 10  
    Nie bardzo te zmiany pomogły... Może coś źle napisałem w tym drugim procesorze atmedze 16 ? Do niego wgrałem program napisany w bascomie:

    
    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 9600
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , Rs = Porta.2 , E = Porta.3
    
    Dim Num As Byte
    Cls
    Cursor Off
    
    Locate 1 , 1
    
    Do
    
    'Home
    
    
    Print "Abc"
    Num = Waitkey()
    
    
    Lcd Chr(num)
    
    Wait 1
    
    Loop
    End
    



    A pokazuje teraz na wyświetlaczu jakieś: x, psi, ksi, suma, coś podobnego do literki A, ale ogólnie wszystkie wyglądają na cenzuralne 'krzaczki' ;)
  • #4 9204884
    Konto nie istnieje
    Konto nie istnieje  
  • #5 9209471
    Fredy
    Poziom 27  
    zmienna a,oraz zmienna c musi być typu volatile - to dotyczy programu w C.
    W bascomie to program musi mieć buforowanie włączone.Inaczej znaki ci uciekną zanim je zauważysz (poczytaj o config serialin bufered).
  • #6 9219049
    namlooc
    Poziom 15  
    xyzboro napisał:

    char c;
    int a=0;

    ISR(USART_RX_vect)
    {
    c = UDR;
    a = 1;
    }


    Zmienne c oraz a isnieja tylko w przerwaniu. Po zakonczeniu przerwania giną...
    Aby przerwanie moglo ingerowac w zmienne globalne:
    volatile char c;
    volatile int a;
  • #7 9223778
    xyzboro
    Poziom 10  
    Zrobiłem tak jak szanowni koledzy doradzili jednak dalej jest coś nie tak i już szczerze mówiąc brak mi pomysłów na jakieś inne rozwiązanie. Poniżej załączam kod który wgrany jest do procka AT90PWM3b:
    
    #include <avr/io.h> 
    #include <util/delay.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <avr/interrupt.h>
    
    //#define F_CPU 64000000UL                    // 64MHz wewnetrzny 
    #define BAUD 9600UL                        // predkosc transmisji 
    #define MYUBRR (F_CPU/BAUD/16-1)
    
    void UART_init(unsigned int ubrr);         // inicjalizacja UArta 
    void USART_out (unsigned char data);       // wysłanie pojedynczego znaku 
    void wysString(unsigned char z[]); 
    
    volatile char c;
    volatile int a;
    
    ISR(USART_RX_vect)
    {
    c = UDR;
    a = 1;
    }
    
    void main()
    {
    a = 0;
    UART_init(MYUBRR); 
    while(1)
    {
     if(a) USART_out(c); 
      
    }
    }
    
    void UART_init(unsigned int ubrr)         // inicjalizacja UArta 
    { 
      UBRRH = (unsigned char) (ubrr>>8);    // ustawienie prędkości transmisji 
      UBRRL = (unsigned char)ubrr; 
      UCSRB = (1<<RXEN)|(1<<TXEN);          // włączenie odbiornika oraz nadajnika 
      UCSRC = (0<<UMSEL0)|(0<<UPM0)|(1<<USBS)|(3<<UCSZ0);       // 8 bitów danych, 1 bity stopu, brak parzystości 
    } 
    
    void USART_out (unsigned char data)       // wysłanie pojedynczego znaku 
    { 
      _delay_ms(1); 
      while((UCSRA&(1<<UDRE)) == 0); 
      UDR = data; 
    } 
    
    void wysString(unsigned char z[]) 
    { 
      int i = 0; 
      while(i < 64) 
      { 
         if( z[i] == '\0' ) break; 
         USART_out(z[i++]); 
      } 
    } 
    
  • #9 9226849
    xyzboro
    Poziom 10  
    piotrva napisał:
    Dalej źle zdefiniowane F_CPU


    to akurat jest tylko w komentarzu i zostało zmienione w Makefile na 16MHz
  • #11 9227221
    Konto nie istnieje
    Konto nie istnieje  
  • #12 9227508
    xyzboro
    Poziom 10  
    Nasunęły mi się jeszcze dwa pytania; mianowicie czy UART może działać na wewnętrznym oscylatorze? (układ z AT90PWM3b jest na wew. oscylatorze).
    Drugie pytanie to czy pętla PLL działa na zewnątrznym kwarcu?
    Dodam tylko, że z tego co wyczytałem to UART powinien działać na wewnętrznym oscylatorze jednak wolałbym się upewnić od kogoś mądrzejszego w tych sprawach niż ja;)
  • #14 9242866
    xyzboro
    Poziom 10  
    Ma ktoś jeszcze jakiś pomysł bo musze pilinie to zrobić, a nie bardzo wiem co jeszcze może być nie tak;/ ? Dodam, że po tych wszystkich zmianach na wyświatlaczu pojawia się ciągle literka p, np.: "pppppppppppppppp ppp pp p" itd.
    Proszę o jakieś wskazówki.
  • Pomocny post
    #15 9243352
    tmf
    VIP Zasłużony dla elektroda
    Jeśli procesor nie jest taktowany z kwarcu tylko wewnętrznego RC to takie błędy są normalne. Trzeba go dokładnie skalibrować a i to nic nie gwarantuje. Odbierając znak sprawdź rejestr stanu, zapewne będziesz miał FE albo PE.
  • #16 9244953
    xyzboro
    Poziom 10  
    Dziwne bo wcześniej kolega Light-I twierdział, że może być wew oscylator. Ja też gdzieś, kiedyś słyszałem, że przy komunikacji powinien być zewnętrzny kwarc, więc już sam nie wiem jak to jest z tymi oscylatorami(???).
    W takim razie jeszcze jedno pytanie: czy jak dorzuce do tego procka AT90PWM zewnętrzny kwarc to powinno wszystko działać poprawnie?
    Albo chociaż proszę o pomoc jak się kalibruje taki procek?
    Do programowania używam Khazama przez programator USBasp.
  • #17 9245114
    tmf
    VIP Zasłużony dla elektroda
    Wewnętrzny generator RC czasami działa, problem w tym, że jego częstotliwość określona jest z tolerancją większą niż wymagana do poprawnej pracy UART. Można go skalibrować, pisząc odpowiednie procedury kalibracyjne do UART, np. nadając sekwencyjnie 0xAA i mierząc czasy 0 i jedynek, po czym odpowiednio zaprogramować UBRR. Zewnętrzny kwarc daje wymaganą stabilność i dokładność, oczywiście oba procesory muszą być taktowane z kwarcu.
  • #18 9251737
    LordBlick
    VIP Zasłużony dla elektroda
    xyzboro napisał:
    Dziwne bo wcześniej kolega Light-I twierdział, że może być wew oscylator.
    Z zastrzeżeniem, że rozmawiamy o zadeklarowanej w kodzie prędkości 9600bps...
  • #19 9256236
    xyzboro
    Poziom 10  
    Light-I napisał:
    Z zastrzeżeniem, że rozmawiamy o zadeklarowanej w kodzie prędkości 9600bps...

    ale taka prędkość jest zadeklarowana...
REKLAMA