Komunikace UART ATmega8
Napsal: 25 pro 2011, 19:04
Zdravím začal jsem se sériovým portem na atmega8 a pokouším zatím posílat jen znaky jako echo, mám to propojené přes max232, funguje to, ale chová se to divně, hlavně to vrací úplně jiné znaky než tam tomu pošlu a někdy to nevrátí nic. ten program je takhle: Navíc se mi zdá že ty znaky zůstávají na portu
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#define UART_BAUD_RATE 2400
#define F_CPU 1000000
#define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16l)-1)
#define RBUFFLEN 40 //Pufferlänge für seriellen Empfang
volatile unsigned char rbuff[RBUFFLEN]; // Ringpuffer
volatile uint8_t rbuffpos, // Position, die als nächstes gelesen werden muß im Ringpuffer
rbuffcnt, // Anzahl zu lesender Zeichen im Puffer
udr_data; // Daten aus dem UART (volatile, damit nicht wegoptimiert wird vom Präprozessor)
// Interruptroutine, die Zeichen aus dem UART sofort ausliest, wenn empfangen
SIGNAL (SIG_UART_RECV)
{
udr_data= UDR; //Byte auf jeden Fall abholen, sonst Endlosinterrupt
if(rbuffcnt < RBUFFLEN) // keinen Zeichen in einem vollen Ringpuffer überschreiben
rbuff[(rbuffpos+rbuffcnt++) % RBUFFLEN] = udr_data; // welche Position? Gelesene Zeichenpos + Anzahl Zeichen MODULO Pufferlänge
// (von 0 wieder anfangen, wenn Ende erreicht)
}
// Nächstes zu lesendes Zeichen aus Ringpuffer zurückgeben
unsigned char ser_getc (void)
{
unsigned char c;
while(!rbuffcnt); // Warte bis ein Zeichen vorhanden ist
cli(); // Interruptbehandlung kurz aussetzen. Ab jetzt muß es schnell gehen (wenig Befehle), damit Zeichen, die
// ab jetzt eintreffen nicht verloren gehen.
rbuffcnt--; // anschl. ein Zeichen weniger zum ausgeben
c = rbuff [rbuffpos++]; // Zeichen holen, was nach dem bereits gelesenen liegt
if (rbuffpos >= RBUFFLEN) rbuffpos = 0; // wenn hinterstes Zeichen (rechts im Puffer) gelesen wurde, dann wieder vorne anfangen
sei(); // Interruptbehandlung wieder aktivieren
return (c); // Zeichen zurückgeben
}
void uart_putc(unsigned char c)
{
while(!(UCSRA & (1 << UDRE))); // warte, bis UDR bereit
UDR = c; // sende Zeichen
}
void uart_puts (char *s)
{
while (*s)
{ // so lange *s != NULL
uart_putc(*s);
s++;
}
}
void uart_ini ()
{
sei(); // Interruptbehandlung aktivieren
UCSRB |= (1 << TXEN); // UART TX (senden) einschalten
UCSRB |= (1 << RXEN ); // UART RX (empfangen) einschalten
UCSRB |= (1 << RXCIE); // Interruptauslösung für eingehende Daten aktivieren
UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron, 8N1
UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8); // tady je 8
UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);
}
void main()
{
unsigned char zeichen;
DDRC=0x02;
uart_ini();
//lcd_ini();
int g;
unsigned int h;
while (1)
{
zeichen = ser_getc();
h=atoi(zeichen);
uart_putc (zeichen);
PORTC = 0X02;
for(g=0;g<2000;g++);
PORTC=0x00;}
}
}
nevíte někdo co s tím? Díky
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#define UART_BAUD_RATE 2400
#define F_CPU 1000000
#define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16l)-1)
#define RBUFFLEN 40 //Pufferlänge für seriellen Empfang
volatile unsigned char rbuff[RBUFFLEN]; // Ringpuffer
volatile uint8_t rbuffpos, // Position, die als nächstes gelesen werden muß im Ringpuffer
rbuffcnt, // Anzahl zu lesender Zeichen im Puffer
udr_data; // Daten aus dem UART (volatile, damit nicht wegoptimiert wird vom Präprozessor)
// Interruptroutine, die Zeichen aus dem UART sofort ausliest, wenn empfangen
SIGNAL (SIG_UART_RECV)
{
udr_data= UDR; //Byte auf jeden Fall abholen, sonst Endlosinterrupt
if(rbuffcnt < RBUFFLEN) // keinen Zeichen in einem vollen Ringpuffer überschreiben
rbuff[(rbuffpos+rbuffcnt++) % RBUFFLEN] = udr_data; // welche Position? Gelesene Zeichenpos + Anzahl Zeichen MODULO Pufferlänge
// (von 0 wieder anfangen, wenn Ende erreicht)
}
// Nächstes zu lesendes Zeichen aus Ringpuffer zurückgeben
unsigned char ser_getc (void)
{
unsigned char c;
while(!rbuffcnt); // Warte bis ein Zeichen vorhanden ist
cli(); // Interruptbehandlung kurz aussetzen. Ab jetzt muß es schnell gehen (wenig Befehle), damit Zeichen, die
// ab jetzt eintreffen nicht verloren gehen.
rbuffcnt--; // anschl. ein Zeichen weniger zum ausgeben
c = rbuff [rbuffpos++]; // Zeichen holen, was nach dem bereits gelesenen liegt
if (rbuffpos >= RBUFFLEN) rbuffpos = 0; // wenn hinterstes Zeichen (rechts im Puffer) gelesen wurde, dann wieder vorne anfangen
sei(); // Interruptbehandlung wieder aktivieren
return (c); // Zeichen zurückgeben
}
void uart_putc(unsigned char c)
{
while(!(UCSRA & (1 << UDRE))); // warte, bis UDR bereit
UDR = c; // sende Zeichen
}
void uart_puts (char *s)
{
while (*s)
{ // so lange *s != NULL
uart_putc(*s);
s++;
}
}
void uart_ini ()
{
sei(); // Interruptbehandlung aktivieren
UCSRB |= (1 << TXEN); // UART TX (senden) einschalten
UCSRB |= (1 << RXEN ); // UART RX (empfangen) einschalten
UCSRB |= (1 << RXCIE); // Interruptauslösung für eingehende Daten aktivieren
UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron, 8N1
UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8); // tady je 8
UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);
}
void main()
{
unsigned char zeichen;
DDRC=0x02;
uart_ini();
//lcd_ini();
int g;
unsigned int h;
while (1)
{
zeichen = ser_getc();
h=atoi(zeichen);
uart_putc (zeichen);
PORTC = 0X02;
for(g=0;g<2000;g++);
PORTC=0x00;}
}
}
nevíte někdo co s tím? Díky