UART w ATmega8

Nov 15, 2004 7 Replies

Witam. Mecze sie juz jakis czas z oprogramowaniem UARTu w atmedze na przerwaniach. Napisalem takie cos:



______________________________________________________________ #define UART_TX_DATA_INT_ENABLE UCSRB = UCSRB | (1<<UDRIE) #define UART_TX_DATA_INT_DISABLE UCSRB = UCSRB & 223 #define UART_IN_BUFF_SIZE 10 #define UART_OUT_BUFF_SIZE 10 #define CRYSTAL 11059200 #define BAUDRATE 9600



void uartInit(unsigned long crystal, unsigned long baudrate) { unsigned char ubrr_value = 0; UCSRB = 0; cli(); ubrr_value = (((crystal/baudrate)/16)-1); UBRRH = (unsigned char) ((ubrr_value)>>8); UBRRL = (unsigned char) ubrr_value; UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); UCSRB = (1<<RXEN)|(1<<TXEN); sei(); }



unsigned char uartSendCharacter(unsigned char character) { if(uart_out_filling != UART_OUT_BUFF_SIZE) { uart_out_buff[uart_out_wr_ptr] = character; uart_out_wr_ptr == (UART_OUT_BUFF_SIZE - 1) ? uart_out_wr_ptr = 0 : uart_out_wr_ptr++; uart_out_filling++; UART_TX_DATA_INT_ENABLE; return 0; } else return 1; }



SIGNAL(SIG_UART_DATA) { if(uart_out_filling) { UDR = uart_out_buff[uart_out_rd_ptr]; uart_out_rd_ptr == (UART_OUT_BUFF_SIZE - 1) ? uart_out_rd_ptr = 0 : uart_out_rd_ptr++; uart_out_filling--; } else { UART_TX_DATA_INT_DISABLE; } }



int main(void) //program główny { uartInit(CRYSTAL, BAUDRATE); uartSendCharacter(60); uartSendCharacter(61); uartSendCharacter(62); uartSendCharacter(63); uartSendCharacter(64); uartSendCharacter(65); while(1); } ______________________________________________________________



Ladnie sie kompiluje, ale nie dziala. W debugerze w AVRStudio widac ze w przerwaniach dwa kolejne znaki sa ladowane do UDR, potem jednak flaga UDRE przyjmuje wartosc 0 i koniec. Dalej nic juz nie wychodzi z bufora, a flaga nie zmienia stanu na 1 nie zglaszajac tym samym przerwania. Nie wiem co z ta flaga bo przeciez ona podobno jest ustawiana na 1 gdy sie oprozni bufor. Gdzie jest "byk" ? Na sprzecie rowniez nie dziala, nie pojawiaja sie nawet te dwa znaki ktore wedlug debugera sa ladowane do UDR.


Nie wnikam w Twoj program. Zobacz moj -- moze dojdziesz, co jest nie tak u Ciebie.

#include <avr/io.h>

#include <avr/interrupt.h>

#include <avr/signal.h>

#include <string.h>

#include "uart.h"

enum { RECVBUF_MAX = 16, /* max. rozmiar bufora odbiorczego

*/ RECVBUF_USER_MAX = RECVBUF_MAX + 2, VUBRR = 19 /* wpis do UBRR, 18.4320MHz, 57600 */ };

/* initUART: inicjalizuje UART */ void initUART(void) { /* zabronienie przerwan na czas inicjalizacji */ cli();

/* ustawienie predkosci transmisji */ UBRRH = (unsigned char)(VUBRR >> 8); UBRRL = (unsigned char)VUBRR;

/* zezwolenie na przerwania od odbiornika i nadajnika */ UCSRB = (1 << RXCIE) | (1 << TXCIE) | (1 << RXEN);

/* ustawienie formatu ramki: 8, 1 stop */ UCSRC = (1 << URSEL) | (3 << UCSZ0);

/* zezwolenie na przerwania */ sei(); }

char recvBuf[RECVBUF_USER_MAX] = "\0"; volatile char *recvBufPtr = recvBuf; volatile unsigned char zzz;

/* SIG_UART_RECV: obsluguje odbiornik */ SIGNAL (SIG_UART_RECV) { // cbi(UCSRB, RXEN); /* zablokowanie odbiornika */

if (recvBufPtr - recvBuf < RECVBUF_MAX) *recvBufPtr++ = zzz = UDR;

// sbi(UCSRB, RXEN); /* zablokowanie odbiornika */ }

/* recvTxt: zwraca odczytany napis */ int recvTxt(char *s) { int p;

if ((recvBufPtr == recvBuf) || (*(recvBufPtr - 1) != '\0')) return 0;

cbi(UCSRB, RXEN); /* zablokowanie odbiornika */

strncpy(s, recvBuf, p = (recvBufPtr - recvBuf)); s[p] = '\0';

recvBufPtr = recvBuf;

sbi(UCSRB, RXEN); /* odblokowanie odbiornika */

return p; }

//volatile char txt[RECVBUF_USER_MAX] = "\0"; volatile char *txt = NULL; volatile unsigned char flagTrans = 0;

/* SIG_UART_TRANS: obsluguje nadajnik * -- wywolywana automatycznie po wyslaniu znaku */ SIGNAL (SIG_UART_TRANS) { if (flagTrans == 0) { if (*txt == '\0') flagTrans = 1;

UDR = *txt++; } else {

cbi(UCSRB, TXEN); /* wylaczanie nadajnika */ flagTrans = 0; // cbi(UCSRB, UDRIE); } }

/* sendTxt: wysyla napis */ void sendTxt(const char *s) { if ((s == NULL) || (s[0] == '\0')) return;

/* oczekiwanie na wyslanie calego poprzedniego lancucha */ while (!(UCSRA & (1 << UDRE))) ;

flagTrans = 0;

// strcpy((char *)_txt, (char *)s); // txt = _txt;

txt = (char *)s;

sbi(UCSRB, TXEN); /* wlaczanie nadajnika */ UDR = (unsigned char)*txt++; /* wyslanie pierwszego znaku, reszta przez przerw. */ }

Vicky napisał(a):

Dzieki. Na pewno sie przyda, szczegolnie jak nie uda mi sie uruchomic mojego. Roznica miedzy nimi jest taka ze ja uzywam przerwania od oproznienia rejestru przesuwnego nadajnika, a w Twoim wykorzystane jest przerwanie od oproznienia bufora.

To moze zerknij jeszcze na moj kod:

formatting link
bardzo podobny mechanizm jak twoj. Bufor kolowy i asynchroniczne wysylanie/obdieranie w przerwaniach. Napisalem ten modulik w ramach zabawy z AVRka i nie meczylem go specjalnie testami, ale jak do tej pory dziala w miare bezblednie

pzdr. j.

chodzi o tx? /ja to nawet w maile nie wnikam :), taki len :)

a jesli chodzi o tx to ja do transferu uzywam "udr empty" a nie "tx comlete", praktycznie nie zauwazysz roznicy, jednak ja uzywam tak, bo uwazam, ze to bardziej "logiczne" :)

U¿ytkownik "Q" snipped-for-privacy@gazeta.gov.pl> napisa³ w wiadomo¶ci news:cnbo98$s5o$ snipped-for-privacy@atlantis.news.tpi.pl...

Raczej pozwala na wyeliminowanie "dziur" miêdzy wysy³anymi bajtami, czyli nieco przyspiesza transfer. :)

QmX.

______________________________________________________________

Napisa³em kiedys podobny kod tzn te¿ chcia³em za³±czeniem przerwania od TX uruchamiaæ wysy³anie kolejnych znaków i po opró¿nieniu bufora wy³±czaæ przerwanie. ALE TEZ MI NIE dzia³a³o. Byæ mo¿e to jakis b³±d procesora, albo po prostu nie mo¿na sobie tak machaæ t± flag± jak by nam pasowa³o ;-)

Ja t± metodê porzuci³em. Zrob tak jak inni - uruchamiaj nadajnik przez bezposrednie wpisanie pierwszego bajtu do UDR ( lub zrob to w obs³udze przerwania od timera ). jfk

Jeszcze raz ja. Moze to nie potrzebne, ale dodam, ze mialem problemy z UART, jesli niewlasciwie ustawione byly kierunki Tx i Rx poprzez DDR.

Vicky.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required