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

[ATmega8][C][RS-232]brak transmisji na PC

10 Lis 2008 20:34 3471 19
  • Poziom 10  
    Witam

    Posiadam zestaw uruchomieniowy ATmega8 zl2avr taktowany 1MHz(fabrycznie) i chciałem napisac program przesyłajacy dowolny znak na PC, ma byc odczytywane w hyperterminal. Ale niestety nie mia transmisji zadanego przeze mnie znaku. W trakcie transmisji (wskazuje ją świecaca się dioda) kursor w hyperterminalu mryga szybciej, czyli wnioskuje ze cos sie na tym RS-ie dzieje. Zadany przeze mnie w programie na sztywno baud rate wynosu 2400, bo przy czestotliwosci 1MHz błąd wynosi 0.2%, wiec raczej transmisja powinna zostac odebrana poprawnie, ale jak pisałem wyzej nic nie jest odbierane.

    Oto kod mojego programu:

    main.c
    Code:
    #include "projdat.h"
    
    // dane :

    // funkcje :

    //====================
    // funkcja main()
    int main(void)               
    {
     // inicjalizacja

     //== start ======================= inicjalizacja portów =======================
     
     DDRB = 0xFF; //--- inicjalizacja portu B jako output na wszystkich flagach
     PORTB = 0xFF; //---
     
     DDRC = 0xFF;     //--- inicjalizacja portu C jako output
     PORTC = 0xFF;    //--- port C obsługuje wysw 7 seg, stan niski oznacza zapaloną "pałke" wyswietlacza
     
     DDRD = 0;      //--- inicjalizacja portu D jako intput
     PORTD = 0xFF; // port D obsluguje przyciski, kiedy przycisk jest załaczony mamy stan niski czyli 0, port musi byc zainicjalizowany z jedynkami
     
     //== stop ======================== inicjalizacja portów =======================
     
     init_usart(25);
     //sei();
     
     //char *string = "usart dziala jak ulal";
     
     // pętla główna
     while (1)
      {
        if(BUTTON4_CLICK)
        {
         PORTC &=~ _BV(5);     //-- zapala diode by zasygnalizowac wysyłanie
         //transmit_string_usart(string);
         transmit_usart('W');
         PORTC |= _BV(5);      //--- gasi diode gdy dane zostaną wyslane
        }
      }
    }


    funkcje.c
    Code:
    //--------------------------------------- 
    

    void init_usart(uint baud_rate)//--- funkcja inicjalizujaca USART
    {
     //UCSRC &=~ _BV(UMSEL);              //--- ustawienie trybu aynchronicznego
     
     UBRRH = (uchar)(baud_rate>>8);     //--- ustawienie baud rate pobranego z parametru funkcji
     UBRRL = (uchar) baud_rate;
     
     UCSRB = _BV(RXEN) | _BV(TXEN);     //--- ustawienie Transmiter'a i Receivere'a
     
     UCSRC = _BV(UCSZ0) | _BV(UCSZ1);   //--- ustawienie ramki, kolejno: długosc slowa - 8bitów
     UCSRC |= _BV(USBS);                //--- ilosc bitów stop - 2
     UCSRC |= _BV(URSEL);               //--- zapis/odczyt danych z/do UCSRC
     
              //---
    }

    //---------------------------------------

    void transmit_usart(uchar data)//--- funkcja transmitujaca dane przez usart
    {
     while(!(UCSRA & _BV(UDRE)));      //--- sprawdzanie czy rejest UDR jest pusty zanim bedzie mogła nastąpic kolejna transmisja, jest nie jest pusty, wykonuje pusta petle
     UDR = data;                       //--- załadowanie nowych danych do wysłania
     //_NOP;
     //_NOP;                       
    }

    //---------------------------------------

    void transmit_string_usart(uchar *data)//--- funkcja transmitujaca słowo danych
    {
     while(*data) transmit_usart(*(data++));
    }

    //---------------------------------------


    projdat.h
    Code:
    // plik nagłówkowy globalnych danych projektu
    
    #ifndef _PROJ_DAT_H_
    #define _PROJ_DAT_H_
    // #include :

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

    // #define :
    #define F_CPU 1000000

    #define BUTTON4_CLICK (!(PIND & _BV(3)))
                       
    // deklaracje funkcji
    // extern char Myfunc(int,char);

    extern void init_usart(uint baud_rate);
    extern void transmit_usart(uchar data);
    extern void transmit_string_usart(uchar *data);

    #endif


    Prosze o pomoc, bo nie wiem co juz robic
  • Poziom 14  
    Mam pytanie formalne: jaka jest prędkość transmisji ustawiona na porcie w PC? Czy domyślna nie jest 9600?
  • Poziom 10  
    leszek1550 napisał:
    Mam pytanie formalne: jaka jest prędkość transmisji ustawiona na porcie w PC? Czy domyślna nie jest 9600?


    W hyperterminalu 2400 bodów

    Dodano po 29 [minuty]:

    jeszcze jedna mi rzecz przyszła do głowy, czy jest jakis inny sposób odebrania danych z RS-232

    Dodano po 4 [minuty]:

    zmieniłem w menedzerze uzadzeń we własciwosciac systemu w ustawieniach portu COM1 predkosc transmisji na 2400 bodów oraz ustawiłem 2 bity stopu tak jak w programie i hyper terminalu, ale dalej nic z tego
  • Poziom 14  
    Czy ta procedura nie ma być tak:

    kod:
    Code:
    void transmit_usart(uchar data)//--- funkcja transmitujaca dane przez usart
    
    {
     while(!(UCSRA & _BV(UDRE)))      //--- sprawdzanie czy rejest UDR jest pusty zanim bedzie mogła nastąpic kolejna transmisja, jest nie jest pusty, wykonuje pusta petle
    {
     UDR = data;                       //--- załadowanie nowych danych do wysłania
     //_NOP;
     //_NOP;
    }                       
    }


    Proszę umieszczać listingi programów w znacznikach "Code". [c_p]
  • Poziom 10  
    zdecydowanie nie, petla sprawdza czy UDR jest juz pusty, i dopiero wtedy przypisuje kolejne dane do UDR.

    Dodano po 54 [minuty]:

    po pewnym czasie analizowania programu na porcie za pomoca programu: "RS-232 Monitor" oraz symulacjach w AvrStudio, doszedłem do dziwnych wniosków, ze usart mi transmituje same 0... nie wiem juz co jest nie tak, czy jest problem z inicjalizacją czy do UDR nic nie jest wpisywane... Pomocy!!!
  • Poziom 26  
    DDRD = 0x02//przecież tym pinem wysyłasz [TXD]
    wywal ten uchar i wpisz normalnie unsigned char
    wywal F_CPU i w project->conf options-> frequency wpisz 1000000

    do odbioru użyj programu realterm, ostatnią wersję 2.0.0.64 pobierzesz z http://www.i2cchip.com/realterm/

    powinno ruszyć
  • Poziom 10  
    Niestety, nie działa :cry: dalej mam na wyjsciu te misie. poza tym działa mi to jakoś dziwnie bo wyglada na to ze RS wysyła po... 9 bajtów i kazdy zerowy(8 zer). Ja tego nie rozumiem.
  • Poziom 26  
    zastosowałeś układ max232 ?
    czy korzystasz może z przejściówki ?
    spróbuj wysyłać liczbę 1
    i wysyłaj przez transmit_usart
    w czasie odboiru świeci ci BREAK lub error
  • Poziom 10  
    w czasie transmisji na kompa swiecił sie Break

    Dodano po 2 [minuty]:

    układ zastosowany przeze mnie to MAX232CPE +0621 (to wszytko pisze a układzie scalonym)

    a korzystam z portu w kompie bo takowy mam

    Dodano po 4 [minuty]:

    przy transmisji znaku 1 odebrał mi 6 zerowych bajtów
  • Poziom 9  
    Witam, czy moglby ktos sprawdzic mi czy taki program powinien zadziałac i co robie zle ze nie działa
    Code:

    #include <avr/io.h>

    #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


    #define FOSC 8000000ul //         // Clock Speed
    #define BAUD 9600ul //                  9600
    #define MYUBRR FOSC/16/BAUD-1


    #define LED_PORT        PORTD                // port diody LED
    #define LED_BIT                4                // bit diody LED

    #define DDR(x) _SFR_IO8(_SFR_IO_ADDR(x)-1) // adr. rej. kier. PORTx
    #define PIN(x) _SFR_IO8(_SFR_IO_ADDR(x)-2) // adr. rej. wej. PORTx

    #define LED_PORT_O        LED_PORT             // rejestr wyjściowy
    #define LED_PORT_D        DDR(LED_PORT)   // rejestr kierunkowy
    #define LED_PORT_I        PIN(LED_PORT)   // rejestr wejściowy


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

    }



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

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


    int main( void )
    {

       USART_Init ( MYUBRR );
       sbi(LED_PORT_D,LED_BIT);        // użyj linii jako wyjścia
       
       while(1)
       {
          cbi(LED_PORT_O,LED_BIT);        // zapal diodę LED
         USART_Transmit('1');                // wyślij '1' na port szeregowy
        USART_Receive();                // czekaj na znak z portu szeregowego
        sbi(LED_PORT_O,LED_BIT);        // zgaś diodę LED
        USART_Transmit('0');                // wyślij '0' na port szeregowy
        USART_Receive();                // czekaj na znak z portu szeregowego
       }
    }


    ustawiam w project->configuration options->freqency na 8000 000

    w menadżerze urzadzen ustawiam odpowiednio COM1 zgodnie z tym co mam w programie czyli 2bity stopu, 8data, parzystosc nie, szybkosc 9600 i jeszcze sterowanie przeplywem brak

    korzystam z terminala br@y termial i tam ustawiam tez wszystko

    czy bład w programie czy moze raczej cos zle podłaczone?
  • Poziom 26  
    -> ruzumek BREAK mrugnie się jeżeli transmisja kończy się przed czasem np. wysyłasz szybciej niż możesz odebrać[źle ustawiony BAUD], przerwanie transmisji, error mrugnie jężeli transmisja jest nie poprawna np. stak bitu stopu, niepasująca ilość tych bitów itp.

    -> iluzione
    Code:
    #define FOSC 8000000ul //         // Clock Speed

    powinno być definiowane w makefile.
    jak automatycznie nie dorzuci to
    project->configuration options->Custom->wpisujesz "-DF_CPU=8000000UL"[bez cudzysłowia] i klikasz Add powinno się dodać do 2 kolumny.

    dodaj do swojego programu
    Code:
    #include   <util/delay.h>

    i spróbuj zdefiniować usart wpisując mu wartość
    Code:
    USART_Init(1665);//a w kompie ustaw baud na 300

    sbi zakomentuj
    testuj czy działa przez
    Code:
    while(1) 
    
       {
        USART_Transmit(1);                // wyślij '1' na port szeregowy
        _delay_ms(1000);
       }

    co sekundę powinieneś dostawać 1, użyj programu real term i ustaw na odbiór binarny, w zakładce port ustaw baud 300 stop bits 2, i zatwierdź Change
  • Poziom 10  
    skynet_2 napisał:
    -> ruzumek BREAK mrugnie się jeżeli transmisja kończy się przed czasem np. wysyłasz szybciej niż możesz odebrać[źle ustawiony BAUD], przerwanie transmisji, error mrugnie jężeli transmisja jest nie poprawna np. stak bitu stopu, niepasująca ilość tych bitów itp.


    Ale w programie ustawiłem UBRR na 25 czyli przy 1MHz jest to 2400 baudów, w ustawieniach portu w windowsie we własciwosciach systemów w menedzerze urzadzeń tez ustatwiłem 2400, oraz tak samo w Realterm, to co jest nie tak w koncu?
  • Poziom 9  
    znalazlem przyczyne, poniewaz nie mam akurat kwarcu, korzystam z wewnetrznego generatora, dlatego program ruszy jedynie przy malych predkosciach, jak ustawilem 2400 bit/s i 1MHz, i pamietajcie by w fuse bitach tez ustawic 1MHz, wtedy powinno ruszyc
  • Pomocny post
    Poziom 34  
    Co do pierwszego kodu, prawdopodobnie uart działa zbyt wolno - błąd jest tutaj:
    Code:
     UCSRC = _BV(UCSZ0) | _BV(UCSZ1);   //--- ustawienie ramki, kolejno: długosc slowa - 8bitów 
    
     UCSRC |= _BV(USBS);                //--- ilosc bitów stop - 2
     UCSRC |= _BV(URSEL);               //--- zapis/odczyt danych z/do UCSRC

    Nie ma dowolności kiedy co ustawić, ustawiać bitami czy jak - wpisanie do UCSRC musi wystąpić w jednej instrukcji bez doświecania bitów! Wpisanie do UCSRC bez ustawionego górnego bitu (pierwsza instrukcja) jest w rzeczywistości zapisem do UBRRH. Drugie powoduje ustawienie odpowiedniego bitu w UBRRH (dostęp bez ustawionego bitu). Trzecie powoduje przepisanie UBRRH do UCSRC - uart będzie skonfigurowany, ale dzielnik będzie zły. Bardziej poprawne będzie:
    Code:
     UCSRC = _BV(URSEL) | _BV(UCSZ0) | _BV(UCSZ1) | _BV(USBS);


    -- edit: nie przeczytałem tematu, nie zauważyłem że są dwa kody.
  • Poziom 26  
    A to ciekawe ja tak ustawiałem UCSRC[wszystko na raz] za pierwszym razem jak bawiłem się usartem i ruszyło od razu.
  • Poziom 10  
    BoskiDialer napisał:
    Co do pierwszego kodu, prawdopodobnie uart działa zbyt wolno - błąd jest tutaj:
    Code:
     UCSRC = _BV(UCSZ0) | _BV(UCSZ1);   //--- ustawienie ramki, kolejno: długosc slowa - 8bitów 
    
     UCSRC |= _BV(USBS);                //--- ilosc bitów stop - 2
     UCSRC |= _BV(URSEL);               //--- zapis/odczyt danych z/do UCSRC

    Nie ma dowolności kiedy co ustawić, ustawiać bitami czy jak - wpisanie do UCSRC musi wystąpić w jednej instrukcji bez doświecania bitów! Wpisanie do UCSRC bez ustawionego górnego bitu (pierwsza instrukcja) jest w rzeczywistości zapisem do UBRRH. Drugie powoduje ustawienie odpowiedniego bitu w UBRRH (dostęp bez ustawionego bitu). Trzecie powoduje przepisanie UBRRH do UCSRC - uart będzie skonfigurowany, ale dzielnik będzie zły. Bardziej poprawne będzie:
    Code:
     UCSRC = _BV(URSEL) | _BV(UCSZ0) | _BV(UCSZ1) | _BV(USBS);


    -- edit: nie przeczytałem tematu, nie zauważyłem że są dwa kody.


    Po tak dlugiej nieobecnosci w temacie wracam by podac najwazniejsza informacje ze działa:D... dzieki postowi powyzej, moge juz spokojnie wysyłac przez usart na kompa stringi i odbierac je w hyperterminalu.
    WIELKIE DZIEKI

    Proponuje zostawic post potomnym i nie tylko

    Jakby ktos chciał gotowy kod z poprawkami... niech pisze na priv
  • Poziom 10  
    Temat troch nieaktualny ale caly czas walcze z tym samym problemem. mozna prosic o gotowy kod? (nie wiem co nie dziala).

    Pozdrawiam
  • Poziom 26  
    datasheet, rozdział UART, masz kody w C.