Elektroda.pl
Elektroda.pl
X

Search our partners

Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

polaczenie uC -> MAX232 -> PC

Mr_T_ 28 Jul 2006 16:21 3873 26
  • #1
    Mr_T_
    Level 15  
    zalezy mi tylko na wysylaniu danych z PC do uC, ale nie jestem pewien czy dobrze to lacze. Pytam sie poniewaz nie chce posadzic portu w PC, ani calego ukladu, rowniez nie mam pojecia jak skonfigurowac uC (ATtiny2313 na kwarcu 11,0592MHz) do odbioru takich danych

    ps. przeszukiwalem forum, ale nie znalazlem zadowalajacej odpowiedzi odpowiedzi:(
  • #2
    arnoldziq
    Moderator of Programming
    Przy takim kwarcu najlepsza będzie prędkość 19200 bps.
    Schemat który zamieściłeś jest w miarę poprawny, ale nie uwzględnia kondensatorów niezbędnych do pracy całego urządzenia.

    Zmontuj raczej coś takiego :

    Pamiętaj tylko o sprawdzeniu w nocie katalogowej swojego uC , gdzie ( na których nóżkach ) dokładnie znajduje sie RX i TX.
  • #3
    Procekk
    Level 12  
    Wszystko spoko.. tna prawie wszystko.. a właściwie.. to musisz zamienić połączenia na DB9 miejscami 2<->3 albo na MAX232 13 z 14. Poza tym brak kondensatorków, np. 4x 1uF/16V. Co do konfiguracji rejestrów, wszystko jest w dokumentacji. Włącz przerwanie od odbiornika, włącz odbiornik (rejestr UCSRB). Rejestr UCSRC służy do konfiguracji parametrów transmisji. Przed tym wszystkim skonfiguruj UBRR, na 11,059HHz hesli chcesz transmisję z prędkością 19200kbps musisz wpisać wartość 0x23 (35 dziesiętnie). W czym piszesz?
  • #4
    Mr_T_
    Level 15  
    tzn to uklad uproszczony bo nie wiem tylko jak podlaczyc te 2 kabelki txd i rxd, reszta elementow jest juz zamontowana poprawnie na plytce, bo programy ladowane do procka dzialaja tak jak trzeba.

    Dodano po 38 [minuty]:

    znalazlem cos takiego:
    Code:
    #define F_OSC 11059200                 /* oscillator-frequency in Hz */
    
    #define UART_BAUD_RATE 9600
    #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1)

    void USART_Init()
    {
       // set baud rate
       UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8);
       UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);

       // Enable receiver and transmitter; enable RX interrupt
       UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE)| (1 << TXCIE);

       /* Set frame format: 8data, 2stop bit */
       UCSRC = (1<<USBS)|(3<<UCSZ0);
    }
    A wszystko pisze w C.
    A wracajac do mojego schematu to czy mam zamienic kable 2 z 3 na zlaczu db9?
  • #5
    Procekk
    Level 12  
    Mr_T_: na Twoim schemacie tak mi się wydaje :) Ja tak robię. TXEN i TXCIE mozesz wywalić jeśli nie chcesz nadawać, ale możesz zostawić, napisać sobie coś do odsyłania, dla testów. Dodaj obsługę przerwania:

    SIGNAL(SIG_UART_RECV)
    {
    zrób_coś;
    }

    A gdzieś dalej utwórz funkcję main, daj pętlę nieskończoną (o tym chyba nie musiałem pisać :)).

    Poza tym UBRR wpisuję ręcznie, dla 19200bps w Twoim przypadku musisz wpisać:
    UBRRH = 0x00;
    UBRRL = 0x23;
    Ale to kwestia przyzwyczajeń. UART_BAUD_CALC wydaje mi się OK.
  • #6
    Mr_T_
    Level 15  
    Zamienilem i teraz nozke 14 z max232 mam na 2 w DB9 a 13 na 3.
    NIestety cos musialem namieszac w kodzie. Zalaczam kod. Procekk jesli mialbys chwilke to prosilbym rzuc okiem na ten kod.
  • #7
    Procekk
    Level 12  
    A gdzie masz #include <avr/interrupt.h>? ;-)

    eeeeee... no i jeszcze nie włączyłeś obsługi zmiennych. Zaraz po inicjalizacji uarta dodaj instrukcję sei();
  • #8
    Mr_T_
    Level 15  
    niestety dalej nie chodzi:/
    mam takiego warninga przy kompilacji:
    "../pr_avr_01.c:39: warning: `SIG_UART_RECV' appears to be a misspelled signal handler"

    ktory odnosi sie do funkcji obslugi przerwania.

    a hyperterminal konfiguruje jako 9600 bound, brak bitu parzystosci, 2 stopu i brak kontroli...

    zalamuje mnie to:(
  • #9
    Procekk
    Level 12  
    Pamiętaj jeszcze o sei();
    no i to co pisałem -- #include ...
    Powinno działać. Oczywiście kompilator WinAVR?
    ---
    o i napisz jeszcze w UCSRC zamiast (3<<UCSZ0) troche przejrzyściej (jak dla mnie) czyli: (1<<UCSZ1) | (1<<UCSZ0) od razu widać że te bity są ustawione i własnie one ustawiają 8-bitową transmisję.
    --
    zmień sobie na 1 bit stopu, czyli to co wpisujesz do UCSRC to tylko:
    UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
    Z UCSRB wywal (1 << TXCIE) bo nie potrzebne Ci to?
    A dla pewności wpisz do UBRR w ten sposób:
    UBRRH = 0x00;
    UBRRL = 0x47; //czyli 71 dec, 9600bps(malpa)11.0592MHz
  • #10
    Mr_T_
    Level 15  
    jestem zalamany, nie wiem co robie zle. 10 razy sprawdzam podlaczenie i chyba jest ok, nie wiem czy cos jeszcze w programie siedzi czy nie.
    zalaczam ponownie kod
  • #11
    Procekk
    Level 12  
    Ej Mr_T.. ale UBRR wpisałeś chyba dziesiętnie.. zrobiłeś mixa w zasadzie. Weź 47 zamień na HEX i zapisz 0x2F tak? :) No i wtedy przy 11.0592MHz bedziesz miał prędkość uarta 14.4kbps
    ---------
    W dokumentacji, w tabelce z UBRR masz podane wartości dziesiętne.
    ---------
    Powodzenia
  • #12
    Mr_T_
    Level 15  
    ale przaeciez jak daje 0x przed liczba to jest to zapis w hex.
    a czy moglbys mi podac dokladnie z ktorego pinu uC na ktory pin MAX232 i wejscie DB9 musze sie podlaczyc zeby moc wysylac z PC na uC?? bo juz sam nie wiem czy dobrze podlaczam:/
  • #13
    Procekk
    Level 12  
    Co do hex zgadzam sie, czyli wpisując 0x47 (=71 dec) ustawiasz prędkość 9600 przy swoim kwarcu. A właśnie.. może podłączyłeś sobie kwarc, ale go nie używasz? Ustawiałeś fusy na zewnętrzny rezonator? Bo może chodzisz na 1MHz? Może coś nie tak z oprogramowaniem na kompie/kablem/przedłużką? Teraz akurat moge podać Ci tylko z pamieci połączenia, a więc:
    RXD uP -> #12 MAX232,
    TXD uP -> #11 MAX232,
    #13 MAX232 -> #3 DB9 (łykasz dane)
    #14 MAX232 -> #2 DB9 (tym wyprowadzeniem wysyłasz);
    Program wydaje się być ok. Kompilator nawet do niczego ani troche nie powinien się doczepiać. Ja jeszcze jak pisze to Twoją funkcję init() posłałbym na początek main() ale w tym przypadku to nic nie zmienia.
    Reasumując: sprawdź połączenia, zamiana kolejności linii transmisyjnych nie mogła Ci nic uszkodzić, no i oprogramowanie, teraz masz 9600, 8-bitów danych, 1 stop, brak parzystości, sterowanie przepływem sprzęt.
    -----
    No i jeszcze #5 DB9 do masy układu.
    -----
    Kondensatory przy MAX232 napewno są w porządku?
    -----
  • #14
    Mr_T_
    Level 15  
    co to znaczy?
    Quote:
    Ustawiałeś fusy na zewnętrzny rezonator?

    a i jak sprawdzic czy dziala max232? wymusic na #11 +5V to na #14 powinienem miec +12V?? czy jak??

    ps. kondensatory sa poprawnie podlaczone i nowe takze powinno byc ok
  • #15
    Procekk
    Level 12  
    Chodziło mi o bity CKSEL3..0, czy po zakupie mikrokontrolera od razu zacząłeś go programować, czy może robiłeś jakąś konfigurację fuse bitów? Bo jeśli tego nie robiłeś to (nie ustawiałeś CKSEL3..0) to proc chodzi Ci na innej czestotliwości (1MHz) i przez to musisz inaczej wyliczać UBRR.
    ----
    Odnośnie drugiego pytania to.. ciekawe, ale jakos nigdy się tym nie przejmowałem, po prostu nota katalogowa od MAXa, podłączenie wg niej i wszystko śmiga. Myślę że raczej mało prawdopodobne żeby Ci coś tam padło. Poza tym nie mam teraz za bardzo jak pomóc od tej strony, żeby coś mierzyć, sprawdzać itp.
  • #16
    Mr_T_
    Level 15  
    nic nie zmienialem. poprostu sobie programowalem uklad. jestem bardzo nowy w tym a mam takie zadanie do wykoniania:/ jak ustawic zeby procek korzystal dokladnie z tego kwarcu?

    programuje poprzez ponyprog i czy tam mam zaznaczyc wszystkie CKSEL??
  • Helpful post
    #17
    Procekk
    Level 12  
    Zaznaczenie w PonyProg oznacza zaprogramowanie, czyli wpisanie 0000. Robiąc to stracisz połączenie z prockiem i bedziesz musiał podpinać zewnętrzny sygnał zegarowy na XTAL1. Więc musisz CKSELE 3..0 w PonyProg odznaczyć. Ja tak odruchowo robie w AVRach że pierwsze co to zczytuje (ważne!) fusy, następnie odznaczam CKSELE 3..0 i wszystko gra. Jednak gdzieś na forum ostatnio było o jakiś problemach z ATtiny2313 i programowaniu fusów, ponoć jakiś "bug", niewiem, dawno nie zajmowałem się mniejszaymi AVR od mega16, więc uważaj. Ja kiedyś jak był jeszcze AVR 90S2313 nie miałem problemów z przestawieniem na kwarca. No i żebyś tego kwarca miał dobrze podłączonego :)
    --
    Tak więc nie wiem na ile jest to ryzykowne, ale możesz sobie komunikacje szybko sprawdzić bez ruszania fusów, po prostu odczytujemy z tabelki UBRR w sekcji 1MHz i np. dla 9600 mamy wartość "6" czyli walnij do UBRRH 0x00 a do UBRRL 0x06; Powinno śmigać, skoro piszesz że nie ruszałeś fusów - samo podpięcie rezonatora jeszcze nic nie zmienia w prędkości procka. Jeszcze odczytaj fusy i sprawdź co mówią :wink:
  • #18
    Mr_T_
    Level 15  
    sprawdzalem wszystko i jest dobrze pdolaczone. zaprogramowalem fusy i dalej nic. nie wiem co w tym kodzie jest zle (pisze pod a4studio z pluginem gcc)
    Code:
    #include <avr/io.h>
    
    #include <avr/interrupt.h>
    #include <avr/signal.h>

    unsigned char volatile znak = 0;

    SIGNAL(SIG_UART_RECV){
       znak = 0xFF;   
    }

    SIGNAL(SIG_UART_TRANS){
    }

    int main(void){
       UCSRB = 1 << TXEN;// wlaczenie nadajnika -> wtedy juz nie wazne jest ustawianie DDRD
       UCSRB = 1 << RXEN;// wlaczenie odbiornika
       
       UCSRC = 1 << UCSZ1;// ustawia 8bitowe slowo
       UCSRC = 1 << UCSZ0;
       UCSRC = 1 << USBS;// 2 bity stopu
       UCSRB = 1 << RXCIE;// wlaczenie przerwania od odbiornika
       UCSRB = 1 << TXCIE;// wlaczenie przerwania od nadajnika
       UBRRH = 0x00;
       UBRRL = 0x47;
       DDRB = 0xFF;
       PORTB = 0b01010101;
       
       DDRD = 0x02;
       PORTD = 0x02;

       znak = 0b00000101;
       sei();
       while(1){
          PORTB = znak;
       }
       return 0;
    }   

    i do tego dostaje jakies warningi:
    Quote:
    ..... warning: `SIG_UART_RECV' appears to be a misspelled signal handler
  • Helpful post
    #19
    shg
    Level 35  
    #include <avr/signal.h>
    Wywal, nowa wersja gcc dla avr wymaga juz tylko <avr/interrupt.h>
    Zresztą, dwie poniższe funkcje w ogóle nie korzystaja z przerwań, więc możesz się pozbyć handlerów (SIGNAL(...){}) i uaktywniania przerwań (UCSRB = (1 << RXCIE) | (1 << TXCIE);)
    zresztą cały ten fragment jest źle.
    Code:
       UCSRB = 1 << TXEN;// wlaczenie nadajnika -> wtedy juz nie wazne jest ustawianie DDRD 
    
       UCSRB = 1 << RXEN;// wlaczenie odbiornika
       
       UCSRC = 1 << UCSZ1;// ustawia 8bitowe slowo
       UCSRC = 1 << UCSZ0;
       UCSRC = 1 << USBS;// 2 bity stopu
       UCSRB = 1 << RXCIE;// wlaczenie przerwania od odbiornika
       UCSRB = 1 << TXCIE;// wlaczenie przerwania od nadajnika


    Jak już to tak:
    Code:
       UCSRB = 1 << TXEN;// wlaczenie nadajnika -> wtedy juz nie wazne jest ustawianie DDRD 
    
       UCSRB |= 1 << RXEN;// wlaczenie odbiornika
       UCSRB |= 1 << RXCIE;// wlaczenie przerwania od odbiornika
       UCSRB |= 1 << TXCIE;// wlaczenie przerwania od nadajnika     
       UCSRC = 1 << UCSZ1;// ustawia 8bitowe slowo
       UCSRC |= 1 << UCSZ0;
       UCSRC |= 1 << USBS;// 2 bity stopu

    A jeszcze lepiej tak, to akurat już do przykładów poniżej, bez uaktywniania przerwań:
    Code:
       UCSRB = (1 << TXEN) | (1 << RXEN);// wlaczenie nadajnika i odbiornika za jednym zamachem -> wtedy juz nie wazne jest ustawianie DDRD 
    
       UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << USBS) ;// ustawia 8bitowe slowo i 2 bity stopu


    funkcja wysyłająca bajt:
    Code:
    void send_byte(uint8_t data) {
    
       while((UCSRA & _BV(UDRE)) == 0) {};      /* czeka, az bufor nadajnika zostanie oprozniony (wazne!) */
       UDR = data;                            /* do rejestru UDR, a nie na PORTB! */
    }


    I funkcja odbierajaca bajt:
    Code:
    uint8_t get_byte(void) {
    
       while((UCSRA & _BV(RXC)) == 0) {};      /* czeka az zostanie odebrany caly bajt (wazne!) */
       return UDR;                        /* zwraca znak pobrany z bofora wejsciowego */
    }

    obie funkcje wymagaja albo zainclude'owania <inttypes.h>, albo zmiany uint8_t na unsigned char (to to samo)
    Kod jest pisany dla ATmega8, ale chyba znaczących różnic nie będzie.

    Nie wiem, czemu się tak na te dwa bity stopu uparłeś, najczęściej stosowanym formatem transmisji jest 8N1, czyli 8 bitow danych, brak kontroli parzystosci i 1 bit stopu, przy okazji transmisja z jednym bitem stopu jest okolo 10% szybsza niż z dwoma ;]

    A MAX232 sprawdzisz tak ajk pisałeś - wymyszając mu odpowiednie stany na liniach wejściowych, z tym że logiczna "1" w RS232 to ujemne napięcie, to raz, a dwa - MAX232 podwaja napięcie zasilania dwukrotnie, więc po wymuszeniu logicznej 1 na którymś wejściu powinieneś dostać około -10V na odpowiednim wyjściu.
  • #20
    Mr_T_
    Level 15  
    Przepraszam was wszystkich za to gnebienie, ale okazalo sie ze ATtiny2313 ma problemy z przerwaniami ogolnie. Ustawilem sobie parametry w ATmega8515 i zaczelo smigac od samego poczatku...

    dzieki wszystkim i pozdrawiam!
  • #21
    mistrzluk
    Level 11  
    A jesli chciał bym wysłać z procka przez rs232 do komputera (np na hiperterminal) napis

    "witaj"

    to jak powinien wygladać taki program w C?

    Posiadam Atmega128 i porty TXi RX są na pinach nr 26,27 (max 232 podlaczony jak wschematach powyzej)
    moj kwarc podlaczony do procka to 7,3728MHZ,
    chcial bym przesyłać np predkoscia 9600bps (to chyba UBRR=47). nie chce zadnych przerwan ani nic poprostu przesłać jakis napis na PC? POMOZE KTOS mi w tym?
  • #22
    Tomek-85
    Level 14  
    Aby wysłać napis na terminal, musisz najpierw napisać funkcję, która
    wysyła pojedynczy znak.
    Code:

    void TXD_znak(unsigned char c) // transmisja znaku
    {
       // czekamy aż UDR będzie pusty
       while(!(UCSRA & (1 << UDRE)));
       UDR = c;    // wyślij znak
    }

    A później robisz coś takiego:
    (funkcja pobiera wskaźnik do początku napisu)
    Code:

    void Uart_napisz(char *s) // transmisja napisu
    {
       unsigned char i,a;
       a=strlen(s);
       for(i=0;i<a;i++) TXD_znak(*s++);      
    }

    Życzę powodzenia w projektowaniu oprogramowania . . .
  • #23
    mistrzluk
    Level 11  
    yyy czyli jak to bedzie wygladać w całości bo teraz nie bardzo załapałem
    (ostatni raz w C programowalem 3 lata temu)
    jakie biblioteki tu zastosowac
    i co z tym ustawianiem predkosci przesyłu
    i czestotliwosci kwarcu?
    gdzie w ten program moge wpiasc np "hallo" by ujrzec go w hiperterminalu?
  • #24
    Tomek-85
    Level 14  
    Jeśli chodzi o ustawienie prędkości transmisji to polecam zajrzeć
    do noty katalogowej układu. (Jest na stronie producenta "Atmel").
    Tam masz wszystko napisane czarno na białym.

    Jeżeli masz zamiar programować mikrokontrolery to koniecznie
    musisz odświeżyć znajomość "C" (chyba że wolisz asemblera lub bascoma).
    Jeśli używasz "WinAvr" to w tym pakiecie jest zawarty help do
    poszczególnych funkcji (avr-libc Manual).
    Funkcja strlen(); zwraca długość napisu i jest zawarta w bibliotece
    <string.h>. Wywołanie funkcji Uart_napisz(char *s) może wyglądać np. tak:
    Uart_napisz("Hello world.")
    Powodzenia.
  • #25
    mistrzluk
    Level 11  
    no to juz załapałem ale kompilator czepia mi sie do rejestrow uartu a dokładniej do "UCSRA i UDRE i UDR" ze nie wie co to jest...?! a programowanie w C zaczynam przyswajac ponownie.

    Pozdrawiam

    Dodano po 16 [minuty]:

    Napisałem to tak:

    #define F_CPU 7372816

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



    #define BAUD 9600 // prędkość transmisji po RS232
    #define MYUBRR 47


    void TXD_znak(unsigned char c) // transmisja znaku
    {
    // czekamy aż UDR będzie pusty
    while(!(UCSR1A & (1 << UDRE)));
    UDR1 = c; // wyślij znak
    }


    void Uart_napisz(char *s) // transmisja napisu
    {
    unsigned char i,a;
    a=strlen(s);
    for(i=0;i<a;i++) TXD_znak(*s++);
    }

    void main()
    {
    Uart_napisz("Hello world");
    }

    ********************************

    Tam gdzie było UCSRA zmieniłem na UCSR1A
    ale nie wiem czy to UDRE jest dobrze
    czy czasem nie powinno być UDR1.

    Może być to w takiej formie? (tak sie kompiluje co prawda jest jeden warning ale to dlatego ze gnie mam juz "void main..." to czepia sie by było int a nie void.
  • #26
    Tomek-85
    Level 14  
    Mam nadzieję, że jest to fragment kodu, bo nigdzie nie widzę abyś
    ustawiał prędkość i tryb pracy nadajnika RS Atmegi.

    Jeżeli nie wiesz jak nazywają się poszczególne nazwy rejestrów
    zajrzyj do pliku: ...\Win_AVR\avr\include\avr\iom128.h
    Nie przejmuj się zbytnio ostrzeżeniem, że funkcja main() nie zwraca
    wartości typu int.

    Na przyszłość kod programu zamieszczaj w znacznikach [code]
  • #27
    mistrzluk
    Level 11  
    narazie sie poddaje bo sie wykończe przy tym komputerze... musze chyba to wszytsko przespac i dopiero sie brac bo teraz to juz nic nie rozumiem... pozdrawiam