Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

RS232 komunikacja z PC, ATmega8

17 Wrz 2006 14:06 3845 5
  • Poziom 14  
    Napisałem taki program do komunikacji z komputerem. Zakładam ze wysyłane znaki będą widoczne w HyperTerminalu. Jednak nic się nie dzieje. Jaki popełniam błąd. Poniżej jest listing programu.

    Code:
    #include <avr/io.h>
    

    #define CPU_Hz   16000000            // częstotliwość zegara w Hz
    #define OSC    16                  // częstotliwość zegara w MHz

    #define BAUD   9600               // prędkość transmisji po RS232
    #define MYUBRR  CPU_Hz/16/(BAUD-1)   


    // **** fukcje dla RS232 ****
    void UART_init(unsigned int ubrr)       // inicjalizacja
    {
       UBRRH = (unsigned char) (ubrr>>8);   // ustawienie prędkości
       UBRRL = (unsigned char) ubrr;
       UCSRB = (1<<RXEN)|(1<<TXEN);         // transmisja dwukierunkowa, odbieranie/nadawanie
       UCSRC = (1<<USBS)|(3<<UCSZ0);      // ustawienie 8 bitów danych i 2 bity stopu
    }


    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
    }



    // **** program główny ****
    int main(void)                       
    {
       UART_init(MYUBRR);               // Inicjalizacja RS232
       while(1) {                     // Nieskończona pętla
          USART_out(39);
          waitms(250);
         USART_out(13);   
          waitms(250);
         waitms(250);
         waitms(250);
       }
    }
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Poziom 14  
    Patrz dokumentacja:
    UCSRC =(1<<URSEL)| (1<<USBS)|(3<<UCSZ0);
  • Poziom 14  
    To nie to, jest zły wzór na obliczenie prędkości transmisji ;( i wzięte akurat głupie symbole ASCII...

    wystarczyło wpisać na stałe
    Code:
    #define MYUBRR  103   
  • Poziom 14  
    Nie zgadzam się z Tobą! Według Twojego wzoru (błędnego to fakt) otrzymamy 104, taki błąd nie jest w stanie uniemożliwić transmisji co działo się w przypadku twojego kodu. To jedna sprawa. Druga, czytaj dokumentacje! W przypadku atmega8 adres rejestru UCSRC i UBRRH jest współdzielony, wybór dokonywany jest poprzez znacznik URSEL. Do czego zmierzam: w twoim kodzie dokładnie gdzie tak pięknie napisałes "// ustawienie 8 bitów danych i 2 bity stopu " faktycznie wcale nie wykonujesz operacji na UCSRC tylko na rejestrze UBRRH. Ot cała filozofia, polecam manuala i jakiś debuger. Pozdrawiam.
  • Poziom 11  
    ...
    /* Set UBRRH to 2 */
    UBRRH = 0x02;
    ...
    /* Set the USBS and the UCSZ1 bit to one, and */
    /* the remaining bits to zero. */
    UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1);
    ...

    To z manuala. Jeśli zapisujesz UBRRH URSEL zostawiasz zero.
    Jeśli UCSRC URSEL=1.
    Sprawdzone przeze mnie na atmega16 i działa.
  • Poziom 14  
    Cytat:
    Ot cała filozofia, polecam manuala i jakiś debuger.

    Te fragmenty kodu który widzisz (procedury obsługujące RSa) pochodza własnie z manuala dla procesora ATmega8.

    Korzystam z AVR Studio 4.

    Działający program przedstawiam ponizej.

    Code:
    #include <avr/io.h>
    

    #define CPU_Hz   16000000               // częstotliwość zegara w Hz
    #define OSC    16                  // częstotliwość zegara w MHz

    #define BAUD   9600               // prędkość transmisji po RS232
    #define MYUBRR  CPU_Hz/16/BAUD-1   


    // **** fukcje dla RS232 ****
    void UART_init(unsigned int ubrr)       // inicjalizacja
    {
       UBRRH = (unsigned char) (ubrr>>8);   // ustawienie prędkości
       UBRRL = (unsigned char) ubrr;
       UCSRB = (1<<RXEN)|(1<<TXEN);         // transmisja dwukierunkowa, odbieranie/nadawanie
       UCSRC = (1<<URSEL)|(3<<UCSZ0);      // ustawienie 8 bitów danych i 1 bity stopu
    }


    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
    }



    // **** program główny ****
    int main(void)                       
    {
       unsigned char Zm = 0;
       UART_init(MYUBRR);               // Inicjalizacja RS232
       while(1) {                     // Nieskończona pętla
          USART_out(Zm);
          waitms(250);
          waitms(250);
          waitms(250);
          waitms(250);
          Zm++;
       }
    }



    Dzieki za pomoc.

    Zamykam temat i pozdrawiam