Krzysztof Urbanski
Guest
Mon Nov 15, 2004 6:05 pm
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)>>

;
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.
--
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl
Vicky
Guest
Mon Nov 15, 2004 9:06 pm
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 >>

;
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. */
}
Krzysztof Urbanski
Guest
Mon Nov 15, 2004 9:46 pm
Vicky napisał(a):
Quote:
Nie wnikam w Twoj program.
Zobacz moj -- moze dojdziesz, co jest
nie tak u Ciebie.
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.
--
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl
Jacek R. Radzikowski
Guest
Tue Nov 16, 2004 12:03 am
Krzysztof Urbanski <krzysztof-u@[usun_to]wp.pl> wrote:
Quote:
Vicky napisał(a):
Nie wnikam w Twoj program.
Zobacz moj -- moze dojdziesz, co jest
nie tak u Ciebie.
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:
http://joanna.gmu.edu/~jacek/software/avr/8535/usart/
Zaimplementowalem 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.
Q
Guest
Tue Nov 16, 2004 2:22 am
Quote:
mojego. Roznica miedzy nimi jest taka ze ja uzywam przerwania od
oproznienia rejestru przesuwnego nadajnika, a w Twoim wykorzystane jest
przerwanie od oproznienia bufora.
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"
QmX
Guest
Tue Nov 16, 2004 5:56 am
Użytkownik "Q" <oink@gazeta.gov.pl> napisał w wiadomości
news:cnbo98$s5o$1@atlantis.news.tpi.pl...
Quote:
a jesli chodzi o tx
to ja do transferu uzywam "udr empty" a nie "tx complete",
praktycznie nie zauwazysz roznicy,
jednak ja uzywam tak, bo uwazam, ze to bardziej "logiczne"
Raczej pozwala na wyeliminowanie "dziur" między wysyłanymi bajtami, czyli
nieco przyspiesza transfer. :)
QmX.
jfk
Guest
Tue Nov 16, 2004 7:07 am
Quote:
void uartInit(unsigned long crystal, unsigned long baudrate) {
unsigned char ubrr_value = 0;
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;
}
}
______________________________________________________________
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" ?
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
Vicky
Guest
Tue Nov 16, 2004 9:38 am
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.