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.

ATMEGA-8 i RS232 nie chca wspolpracowac

07 Lut 2009 19:36 3707 16
  • Poziom 10  
    Witam, mam taki projekt do zrobienia w którym muszę miedzy innymi wysłać informacje z ATMEGI-8 do komputera.

    Napisałam krótki program który powinien wysyłać co 5 sekund znak '5' przez TxD procesora:

    Code:

    #include <avr/io.h>
    #include <util/delay.h>
    #define F_CPU      1000000    //częstotliwość zegara w Hz
    #define UART_BAUD   600         //prędkość transmisji
    #define UART_CONST   (F_CPU/(16ul*UART_BAUD)-1)

    void putchar (char c)
    {
      UDR=c;
      loop_until_bit_is_set(UCSRA,TXC);
      UCSRA |= _BV(TXC);         //sbi(USR,TXC);
    }

    void UART_init(void)
    {
      UBRRL = (unsigned char)UART_CONST;  // ustaw prędkość transmisji
      UCSRB = _BV(RXEN)|_BV(TXEN);        // załącz tx, rx
    }

    int main(void)
    {
    DDRD=0x02;
    PORTD=0x02;
    UART_init();
      while(1)
      {
       putchar('5');
       _delay_ms(5000); 
      }
    }


    Program jest oparty na przykładach z tej strony:
    http://avr.elektroda.eu/?q=node/16
    przy czym tutaj jest Atmega16 więc są inne rejestry i nie wiem czy dobrze je pozamieniałam.

    oczywiście coś nie działa i właśnie chciałam się zapytać co robię źle?
    program kompiluję w AVR Studio 4 z AVR-GCC
    a stan na RSie sprawdzam programem Terminal v1.9b , który znalazłam tutaj na elektrodzie

    wtyczka i układ są na pewno dobrze połączone bo dostałam je od prowadzącego. Używane są tu tylko piny 2,3,4 i 5 RSa, zgodnie z tym obrazkiem http://pl.wikipedia.org/wiki/RS232
  • Pomocny post
    Poziom 23  
    Masz błąd w funkcji usart_init().
    Brakuje Ci ustawień starszegi bajtu danych UBBRH oraz jednej najważnejszej rzeczy nie ustawiłeś ramki danych tzn bitów stopu, kontroli parzystości oraz wielkości ramki :)
    Funkcja usart_init() powinna wyglądać mniejwięcej tak:
    Code:


    void USART_Init()
    {
      /* Ustawianie prędkości*/
      UBRRH = (unsigned char)(UART_CONST >>8);
      UBRRL = (unsigned char)UART_CONST ;
      /*Zezwolenie na nadawanie i odbiór danychr */
      UCSRB = (1<<RXEN)|(1<<TXEN);
      /* Ustaienia 1bit stopu i 8bitów danych */
      UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
    }


    a funkcja wysyłania danych mniejwięcej tak:
    Code:


    void putchar(unsigned char c)
    {
      while ( !( UCSRA & (1<<UDRE)) ) ;// albo jeżeli się nie myle to loop_until_bit_is_set(UCSRA,UDRE)
      UDR = c;
    }
  • Poziom 10  
    O dziękuje, poustawiałam to tak jak powiedziałeś i uruchomiłam.
    Jest już jakaś transmisja, ale teraz w komputerze otrzymuje cały czas jakieś FF, FF, FF, FF i tak ciągle.. wysyła bez zatrzymania.

    teraz mój kod wygląda tak:
    Code:

    #include <avr/io.h>
    #include <util/delay.h>
    //#define F_CPU      1000000    //częstotliwość zegara w Hz
    #define F_CPU 1000000UL
    #define UART_BAUD   1200         //prędkość transmisji
    #define UART_CONST   (F_CPU/(16ul*UART_BAUD)-1)

    void USART_Transmit( unsigned char data )
    {
       while ( !( UCSRA & (1<<UDRE)) );   /* Wait for empty transmit buffer */
       UDR = data;                  /* Put data into buffer, sends the data */
    }

    void USART_Init( unsigned int ubrr )
    {
       UBRRH = (unsigned char)(ubrr>>8);         /* Set baud rate */
       UBRRL = (unsigned char)ubrr;   
       UCSRB = (1<<RXEN)|(1<<TXEN);      /* Enable Receiver and Transmitter */   
       UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);   /* Set frame format: 8data, 2stop bit */
    }

    int main(void)
    {
    DDRD=0x0f;
    USART_Init(UART_CONST);
     
      while(1)
      {
       USART_Transmit('a');
       _delay_ms(5000); 
      }
    }
  • Pomocny post
    Poziom 18  
    jaki masz podłączony kwarc? Ew wewnętrzny rezonator
  • Poziom 10  
    mam tylko to co wewnątrz, i z tego co wiem to powinien on mieć częstotliwość 1 MHz, chociaż w symulacji w AVR Studio pokazuje ze niby 4 MHz, wiec nie jestem pewna. W programie napisałam:
    #define F_CPU 1000000UL
    bo gdzieś widziałam ze tak to powinno być opisane.
  • Pomocny post
    Specjalista - Mikrokontrolery
    w symulatorze pokazuje ci 4, bo masz ustawione 4 dla symulatora w opcjach projektu - nie ma to nic wspolnego z prockiem. pogrzeb w opcjach projektu (takie kolko zebate w dolnej linijce po prawej) i sobie to zmien.

    masz ustawione takie same parametry w terminalu? 2 bity stopu, 1200, 8bitow, brak parzystosci i kontroli przeplywu?

    4\/3!!
  • Poziom 10  
    tak, mam ustawione w terminalu wszystko tak jak powiedziałeś.
    a nawet podczas transmisji sobie zmieniałam te parametry i wtedy troche inne rzeczy sie wysyłaly ale ciągle to byly wartości z FF i FC FE FD takie tam...

    ale mnie martwi to ze w moim programie ma być nadawany jeden znak raz na 5 sekund. a jak to włączam to te znaki FF sa odczytywane baardzo szybko.. w sekunde to mi sie takich z 20 wyświetla.
  • Pomocny post
    Poziom 23  
    W 99% procentach masz złe ustawienia kwarcu w procku (albo jeżeli używasz max232 to źle dobrane jego kondensatorki :idea: ) :) Sprawdź fusy bo jak to bywa w atmegach jeżeli sam ich nie ustawisz to czasem szwankują (sam się z tym meczyłem chyba z tydzień) :) Jeżeli masz taką możliwość to podepnij jakiś kwarc zewnętrzny + 2 kondensatorki, ustaw w opcjach kompilacji że masz kwarc zewnętrzny, jego wartość i nie zapomnij o zmianie fusów na kwarc zewnętrzny :)

    Pozdrawiam maly_elektronik
  • Pomocny post
    Poziom 18  
    Spróbuj takiego kodu. U mnie on działa, tyle że na Atmega8535(nie mam ósmej atmegi luzem).

    Code:

    #include <avr/io.h>
    #include <util/delay.h>

    static void uart(void)   //konfiguracja UART wzięta z dokumentacji avr-gcc
    {
       #define BAUD 1200
       #include <util/setbaud.h>
       UBRRH = UBRRH_VALUE;
       UBRRL = UBRRL_VALUE;
       #if USE_2X
       UCSRA |= _BV(U2X);
       #else
       UCSRA &= ~_BV(U2X);
       #endif
       UCSRB |= _BV(TXEN);
    }

    void write_char(unsigned char bajt)
    {
       while ((UCSRA & _BV(UDRE)) == 0);
       UDR = bajt;
    }

    int main(void)
    {
       uart();
       while(1)
       {
          write_char('a');
          unsigned char i;
          for(i = 0; i < 100; i++) _delay_ms(50);  //starsze wersje gcc miały problem z długimi opóźnieniami
       }
    }


    Pamiętaj żeby w ustawieniach projektu włączyć optymalizację na dowolnym poziomie byle nie zerowym :) W przeciwnym razie kompilator będzie się burzył że będzie problem z opóźnieniami.
    ATMEGA-8 i RS232 nie chca wspolpracowac
    Oczywiście procesor należy ustawić na Atmega8. Menu konfiguracji projektu można znaleźć tak jak Freddie pisał ewentualnie w menu Project -> Configuration options.

    Następna kwestia to taktowanie procesora. Domyślnie jest 1MHz z wewnętrznego generatora RC, sprawdź o ile masz możliwość czy tak rzeczywiście jest.
    ATMEGA-8 i RS232 nie chca wspolpracowac

    Widać przy okazji że skoro procesor chodzi na wewnętrznym generatorze RC to są cztery możliwe częstotliwości, jeżeli nie wiadomo na jakiej pracuje można próbować ustawić na chybił trafił. Nie trzeba pisać #define F_CPU xxxxx, można wpisać częstotliwość pracy w polu Frequency widocznym na rys. 1 ;)
  • Pomocny post
    Poziom 23  
    Krzemowy napisał:
    Cytat:
    Nie trzeba pisać #define F_CPU xxxxx

    Nawet należy to pisać bo czasami (nawet często kod nie jest kompilowany tylko i wyłącznie w AVRStudio, czasem jest to WinAVR albo w ogóle na innym systemie operacyjnym) nie zaskakuje #include<util/delay> bez tego i zaczynają się problemy z szukaniem głupiego błędu :)

    Pozdrawiam maly_elektronik
  • Poziom 10  
    Już wszystko mi działa, dziękuje za pomoc, faktycznie problem tkwił w fusebitach, mam tam ustawiony zegar 8 MHz i tak już sobie zostawiłam. No i jeszcze był włączony Watchdog, dlatego procesor tak szybko wysyłał te "FF".

    teraz mój program wygląda tak: (wklejam gdyby ktoś miał taki kłopot jak ja)
    działa komunikacja w obie strony,
    a mój procesor to Atmega 8 - 16AU 08096

    Code:

    #include <avr/io.h>
    #include <util/delay.h>
    #define F_CPU 8000000UL
    #define UART_BAUD   9600         //prędkość transmisji
    #define UART_CONST   (F_CPU/(16ul*UART_BAUD)-1)
    unsigned char x=0;

    void USART_Transmit( unsigned char data )
    {
       while ( !( UCSRA & (1<<UDRE)) );   /* Wait for empty transmit buffer */
       UDR = data;                  /* Put data into buffer, sends the data */
    }

    unsigned char USART_Receive( void )
    {
       while ( !(UCSRA & (1<<RXC)) );            /* Wait for data to be received */
       return UDR;                           /* Get and return received data from buffer */
    }

    void USART_Init( unsigned int ubrr )
    {
       UBRRH = (unsigned char)(ubrr>>8);         /* Set baud rate */
       UBRRL = (unsigned char)ubrr;   
       UCSRB = (1<<RXEN)|(1<<TXEN);      /* Enable Receiver and Transmitter */   
       UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);   /* Set frame format: 8data, 2stop bit */
    }

    int main(void)
    {
    DDRD=0x02;
    PORTD=0x00;
    USART_Init(UART_CONST);

       while(1)
      {
       USART_Transmit('a');
       _delay_ms(500); 
       x=USART_Receive();
          while(x=='7')
         {
         USART_Transmit('4');
         _delay_ms(500); 
         x=USART_Receive();
         }
         while(x=='1')
         {
         USART_Transmit('3');
         _delay_ms(500); 
         x=USART_Receive();
         }
      }
    }


    Pozdrawiam,
    Ania
  • Poziom 11  
    Niestety tez mam drobny problem z transmisja RS232 i juz nie wiem co może być źle. Kod wzorowany na dokumentacji i jeżeli chodzi o wysyłanie slów czy pojedynczych znaków do komputera to wszystko jest ok, jednakże problem pojawia się gdy chcę te dane odebrać i wyslać je ponownie do terminala. Wtedy też niestety nic się nie dzieje, gdyż program utyka w pętli
    Code:
    while(!(UCSRA & (1<<RXC)) );

    Poniżej zamieszczam napisany przezemnie kod jeżeli ktoś widzi bląd w tym kodzie proszę o pomoc
    Code:

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <util/delay.h>
    #define FOSC 11059200
    #define BAUD 9600
    #define MYUBRR FOSC/16/BAUD-1

    void usart_init(unsigned int ubrr)
    {
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)ubrr;
    UCSRB = (1<<RXEN)|(1<<TXEN);
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
    }

    void nadaj_znak(unsigned char data)
    {
    while(!(UCSRA&(1<<UDRE)));
    UDR=data;
    }

    unsigned char odbierz_znak(void)
    {
    while(!(UCSRA & (1<<RXC)) );
    return UDR;
    }

    void wyslij_slowo(char *dana)
    {
    int dlugosc_slowa, k=0;
    dlugosc_slowa=strlen(dana);
    for(k=0;k<dlugosc_slowa;k++)
       {
       nadaj_znak(dana[k]);
       }
    }

    int main(void)
    {
    DDRD=0x02;
    PORTD=0x00;
    usart_init(MYUBRR);
    _delay_ms(100);
    nadaj_znak(0x0D);
    wyslij_slowo("Witam w programie testowym ");
    while(1)
       {
       wys=odbierz_znak();
       _delay_ms(100);
       nadaj_znak(wys);
       _delay_ms(100);
       }
    }
  • Poziom 13  
    mam pytanie... jak mam atmega z dwoma Uart'ami w jaki sposob moge sczytywac z obydwu wejsc i wysylac rozniez niezaleznie prze dwa wyjascia?
  • Poziom 11  
    Czy spotkal się może ktoś z problemem podobnym do mojego?? siedze już nad tym trochę i już za bardzo nie mam pomysłu gdzie szukać błędu. A więc..
    Korzystam z przejściówki USB=>RS232 i przejściówka ta jest na bank OK bo po zwarciu nóg MAXA232 (nogi 13 i 14) w terminalu i Realterm jest echo. Problem zaczyna się w momencie gdy chce uzyskać echo (Zwierając końcówki 11 i 12 MAXA232) oraz odebrać znaki z kompa. Program zachowuje się tak jakby zawieszał się w pętli while(). Po odcięciu końcówki TXD atmegi8 i zwarciu końcówek 11 i 12 MAXA232 echo już jest;/ Czy jest ktoś w stanie chociaż mi napisać gdzie powinienem szukać błędu??
  • Poziom 11  
    Witam ;) otóż problem rozwiązany. Niestety programowo wszystko jest ok. Problem był po stronie programatora (USBASP) tzn gdy jest on podłączony do układu nie ma możliwości wysyłania i odbierania znaku gdyż USBASP "niby" korzysta z tych pinów jednakże po odłączeniu od programatora pinów RXD oraz TXD wszystko śmiga ;d i o dziwo piny te nie mają znaczenia na pracę programatora.
  • Poziom 27  
    Jak podłączyłeś ten programator? :o On korzysta tylko z Sck, MISO, MOSI, RST i GND układu programowanego. Sam ostatnio z ATmegi8 do kompa (i w druga stronę) robiłem komunikację przy podpiętym stale programatorze i było wszystko ok - uC odsyłał echo.
  • Poziom 11  
    hmm.. skladalem to według schematu znajdującego się na stronie
    Code:
    http://www.fischl.de/usbasp/
    Nie mam pojęcia czemu te piny są wyprowadzone do złącza programatora skoro tak naprawdę nie są one nawet używane.