Coop
20.11.2010, 22:49
Hallo,
versuche mir zur Zeit eine sichere UART-Verbindung aufzubauen.
Die Grundlagen dazu, habe ich mir mit eigen geschriebenen Quellcode erarbeitet, was auch beim Senden von Einzelzeichen ganz gut funktioniert hatte.
Nun wollte ich mir die Herangehensweise mittels Buffer anhand des von Peter Fleury bereitgestellten UART-Quellcodes erarbeiten. Dazu habe ich versucht, diesen Code an den Prozessor (ATMega16) anzupassen, den ich benutzen will und alles andere an QC wegzulassen (den, den ich nicht benötige).
Leider klappt nicht alles so, wie ichs mir erhofte - den Fehler habe ich leider nicht finden können.
Das Programm funktioniert quasi bis zur while(1) Schleife - das heißt, die Ausgaben werden ordentlich an ein Terminalprogramm übergeben.
Allerdings werden keine Zeichen, die im Terminalprogramm eingegeben werden, "geechot".
Vielleicht habe ich schon zu lange drauf geschaut - ich hoffe mir kann jemand zur Lösung verhelfen.
Hier der genutzte Quellcode (ohne uart.h, da daran nix geändert wurde):
/*
* Notes:
* Based on Atmel Application Notes AVR306 and the library of Peter Fleury
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "uart.h"
/*
* constants and makros
*/
#define F_CPU 8000000UL
/* 9600 baud */
#define UART_BAUD_RATE 9600
//size of RX/TX buffers
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE-1)
#define UART_TX_BUFFER_MASK (UART_RX_BUFFER_SIZE-1)
/*ATmega with one USART*/
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE //USART Data Register Empty Interrupt Enable
/*
* modul global variables
*/
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;
ISR(UART0_RECEIVE_INTERRUPT)
/************************************************** ************************************************** ****/
// Function: UART Receive Complete Int
// Purpose : called, when the UART has received a character
/************************************************** ************************************************** ****/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/*read UART status register and UART data register*/
usr = UART0_STATUS;
data = UART0_DATA;
lastRxError = (usr & ( (1<<FE) | 1<<DOR) );
/*calculate buffer index*/
tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
if(tmphead == UART_RxTail)
{
lastRxError = UART_BUFFER_OVERFLOW >> 8;
}
else
{
/*store new index*/
UART_RxHead = tmphead;
/*store received data in buffer*/
UART_RxBuf[tmphead] = data;
}
UART_LastRxError = lastRxError;
}
ISR(UART0_TRANSMIT_INTERRUPT)
/************************************************** ************************************************** ****/
// Function: UART Data Register Empty Int
// Purpose : called, when the UART is ready to transmit the next byte
/************************************************** ************************************************** ****/
{
unsigned char tmptail;
if(UART_TxHead != UART_TxTail)
{
/*calculate and store new buffer index*/
tmptail = (UART_TxTail +1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;
/*get one Byte from buffer and write it to UART*/
UART0_DATA = UART_TxBuf[tmptail]; //start transmission
}
else
{
/*tx buffer empty, disable UDRE interrupt*/
UART0_CONTROL &= ~(1<<UART0_UDRIE);
}
}
void uart_init(unsigned int baudrate)
/************************************************** ************************************************** ****/
// Function: uart_init()
// Purpose : initialize UART and set baudrate
// Input : baudrate using macro UART_BAUD_SELECT
// Returns : none
/************************************************** ************************************************** ****/
{
/*first definition of buffer indicies*/
UART_TxHead = 0;
UART_RxTail = 0;
UART_RxHead = 0;
UART_TxTail = 0;
/*set baudrate*/
if(baudrate & 0x8000)
{
UART0_STATUS = (1<<U2X); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRRH = (unsigned char)(baudrate>>8);
UBRRL = (unsigned char)(baudrate);
/*Enable UART receiver, transmitter and receive complete interrupt*/
UART0_CONTROL = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN);//
/*Set frame format: asynchronous, 8databits, no parity, 1Stopbit*/
#ifdef URSEL
UCSRC = (1<<URSEL) | (3<<UCSZ0);
#else
UCSRC = (3<<UCSZ0);
#endif
// Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
do
{
UART0_DATA;
}
while (UART0_STATUS & (1 << RXC));
}
unsigned int uart_getc(void)
/************************************************** ************************************************** ****/
// Function: uart_getc()
// Purpose : returns byte from ringbuffer
// Input : none
// Returns : lower byte: received byte from ringbuffer / higher byte: last receive error
/************************************************** ************************************************** ****/
{
unsigned char tmptail;
unsigned char data;
if(UART_RxHead == UART_RxTail)
{
return UART_NO_DATA; //no data available
}
/*calculate and store buffer index*/
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;
/*get data from receive buffer*/
data = UART_RxBuf[tmptail];
return (UART_LastRxError<<8) + data;
}
void uart_putc(unsigned char data)
/************************************************** ************************************************** ****/
// Function: uart_putc()
// Purpose : write byte to ringbuffer for transmitting via UART
// Input : byte to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
unsigned char tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while(tmphead == UART_TxTail); //wait for free space in puffer
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/*enable UDRE interrupt*/
UART0_CONTROL |= (1<<UART0_UDRIE);
}
void uart_puts(const char *s)
/************************************************** ************************************************** ****/
// Function: uart_puts()
// Purpose : transmit string to UART
// Input : string to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
while(*s)
{
uart_putc(*s++);
}
}
void uart_puts_p(const char *progmem_s)
/************************************************** ************************************************** ****/
// Function: uart_puts_p()
// Purpose : transmit string from program memory to UART
// Input : programm memory string to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
register char c;
while( (c = pgm_read_byte(progmem_s++)) )
{
uart_putc(c);
}
}
int main(void)
{
unsigned int c=0;
char buffer[7];
int num=134;
DDRB=0xFF; //for debugging
/*
* Initialize UART library, pass baudrate and AVR cpu clock
* with the macro
* UART_BAUD_SELECT() (normal speed mode )
* or
* UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
*/
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
/*
* now enable interrupt, since UART library is interrupt controlled
*/
sei();
/*
* Transmit string to UART
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* uart_puts() blocks if it can not write the whole string to the circular
* buffer
*/
uart_puts("String stored in SRAM\n");
/*
* Transmit string from program memory to UART
*/
uart_puts_P("String stored in FLASH\n");
/*
* Use standard avr-libc functions to convert numbers into string
* before transmitting via UART
*/
itoa( num, buffer, 10); // convert interger into string (decimal format)
uart_puts(buffer); // and transmit string to UART
PORTB=0x55;
/*
* Transmit single character to UART
*/
uart_putc('>');
while(!(c = uart_getc()));
uart_putc( (unsigned char)c );
while(1)
{
c = uart_getc();
if ( c & UART_NO_DATA )
{PORTB=~0x55;//for debugging
}
else
{
if ( c & UART_FRAME_ERROR )
{
/* Framing Error detected, i.e no stop bit detected */
uart_puts_P("UART Frame Error: ");
}
if ( c & UART_OVERRUN_ERROR )
{
uart_puts_P("UART Overrun Error: ");
}
if ( c & UART_BUFFER_OVERFLOW )
{
uart_puts_P("Buffer overflow error: ");
}
/*
* send received character back
*/
uart_putc( (unsigned char)c );
}
}
}
Also, hoffe es schaut sich jemand an und schaffts auch noch den fehlenden Hinweis zu geben.
Danke...
@Edit Tippfehler in ISR_RXC UART_TxHead = tmphead;<-->UART_RxHead = tmphead;
versuche mir zur Zeit eine sichere UART-Verbindung aufzubauen.
Die Grundlagen dazu, habe ich mir mit eigen geschriebenen Quellcode erarbeitet, was auch beim Senden von Einzelzeichen ganz gut funktioniert hatte.
Nun wollte ich mir die Herangehensweise mittels Buffer anhand des von Peter Fleury bereitgestellten UART-Quellcodes erarbeiten. Dazu habe ich versucht, diesen Code an den Prozessor (ATMega16) anzupassen, den ich benutzen will und alles andere an QC wegzulassen (den, den ich nicht benötige).
Leider klappt nicht alles so, wie ichs mir erhofte - den Fehler habe ich leider nicht finden können.
Das Programm funktioniert quasi bis zur while(1) Schleife - das heißt, die Ausgaben werden ordentlich an ein Terminalprogramm übergeben.
Allerdings werden keine Zeichen, die im Terminalprogramm eingegeben werden, "geechot".
Vielleicht habe ich schon zu lange drauf geschaut - ich hoffe mir kann jemand zur Lösung verhelfen.
Hier der genutzte Quellcode (ohne uart.h, da daran nix geändert wurde):
/*
* Notes:
* Based on Atmel Application Notes AVR306 and the library of Peter Fleury
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "uart.h"
/*
* constants and makros
*/
#define F_CPU 8000000UL
/* 9600 baud */
#define UART_BAUD_RATE 9600
//size of RX/TX buffers
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE-1)
#define UART_TX_BUFFER_MASK (UART_RX_BUFFER_SIZE-1)
/*ATmega with one USART*/
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE //USART Data Register Empty Interrupt Enable
/*
* modul global variables
*/
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;
ISR(UART0_RECEIVE_INTERRUPT)
/************************************************** ************************************************** ****/
// Function: UART Receive Complete Int
// Purpose : called, when the UART has received a character
/************************************************** ************************************************** ****/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/*read UART status register and UART data register*/
usr = UART0_STATUS;
data = UART0_DATA;
lastRxError = (usr & ( (1<<FE) | 1<<DOR) );
/*calculate buffer index*/
tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
if(tmphead == UART_RxTail)
{
lastRxError = UART_BUFFER_OVERFLOW >> 8;
}
else
{
/*store new index*/
UART_RxHead = tmphead;
/*store received data in buffer*/
UART_RxBuf[tmphead] = data;
}
UART_LastRxError = lastRxError;
}
ISR(UART0_TRANSMIT_INTERRUPT)
/************************************************** ************************************************** ****/
// Function: UART Data Register Empty Int
// Purpose : called, when the UART is ready to transmit the next byte
/************************************************** ************************************************** ****/
{
unsigned char tmptail;
if(UART_TxHead != UART_TxTail)
{
/*calculate and store new buffer index*/
tmptail = (UART_TxTail +1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;
/*get one Byte from buffer and write it to UART*/
UART0_DATA = UART_TxBuf[tmptail]; //start transmission
}
else
{
/*tx buffer empty, disable UDRE interrupt*/
UART0_CONTROL &= ~(1<<UART0_UDRIE);
}
}
void uart_init(unsigned int baudrate)
/************************************************** ************************************************** ****/
// Function: uart_init()
// Purpose : initialize UART and set baudrate
// Input : baudrate using macro UART_BAUD_SELECT
// Returns : none
/************************************************** ************************************************** ****/
{
/*first definition of buffer indicies*/
UART_TxHead = 0;
UART_RxTail = 0;
UART_RxHead = 0;
UART_TxTail = 0;
/*set baudrate*/
if(baudrate & 0x8000)
{
UART0_STATUS = (1<<U2X); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRRH = (unsigned char)(baudrate>>8);
UBRRL = (unsigned char)(baudrate);
/*Enable UART receiver, transmitter and receive complete interrupt*/
UART0_CONTROL = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN);//
/*Set frame format: asynchronous, 8databits, no parity, 1Stopbit*/
#ifdef URSEL
UCSRC = (1<<URSEL) | (3<<UCSZ0);
#else
UCSRC = (3<<UCSZ0);
#endif
// Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
do
{
UART0_DATA;
}
while (UART0_STATUS & (1 << RXC));
}
unsigned int uart_getc(void)
/************************************************** ************************************************** ****/
// Function: uart_getc()
// Purpose : returns byte from ringbuffer
// Input : none
// Returns : lower byte: received byte from ringbuffer / higher byte: last receive error
/************************************************** ************************************************** ****/
{
unsigned char tmptail;
unsigned char data;
if(UART_RxHead == UART_RxTail)
{
return UART_NO_DATA; //no data available
}
/*calculate and store buffer index*/
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;
/*get data from receive buffer*/
data = UART_RxBuf[tmptail];
return (UART_LastRxError<<8) + data;
}
void uart_putc(unsigned char data)
/************************************************** ************************************************** ****/
// Function: uart_putc()
// Purpose : write byte to ringbuffer for transmitting via UART
// Input : byte to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
unsigned char tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while(tmphead == UART_TxTail); //wait for free space in puffer
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/*enable UDRE interrupt*/
UART0_CONTROL |= (1<<UART0_UDRIE);
}
void uart_puts(const char *s)
/************************************************** ************************************************** ****/
// Function: uart_puts()
// Purpose : transmit string to UART
// Input : string to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
while(*s)
{
uart_putc(*s++);
}
}
void uart_puts_p(const char *progmem_s)
/************************************************** ************************************************** ****/
// Function: uart_puts_p()
// Purpose : transmit string from program memory to UART
// Input : programm memory string to be transmitted
// Returns : none
/************************************************** ************************************************** ****/
{
register char c;
while( (c = pgm_read_byte(progmem_s++)) )
{
uart_putc(c);
}
}
int main(void)
{
unsigned int c=0;
char buffer[7];
int num=134;
DDRB=0xFF; //for debugging
/*
* Initialize UART library, pass baudrate and AVR cpu clock
* with the macro
* UART_BAUD_SELECT() (normal speed mode )
* or
* UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
*/
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
/*
* now enable interrupt, since UART library is interrupt controlled
*/
sei();
/*
* Transmit string to UART
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* uart_puts() blocks if it can not write the whole string to the circular
* buffer
*/
uart_puts("String stored in SRAM\n");
/*
* Transmit string from program memory to UART
*/
uart_puts_P("String stored in FLASH\n");
/*
* Use standard avr-libc functions to convert numbers into string
* before transmitting via UART
*/
itoa( num, buffer, 10); // convert interger into string (decimal format)
uart_puts(buffer); // and transmit string to UART
PORTB=0x55;
/*
* Transmit single character to UART
*/
uart_putc('>');
while(!(c = uart_getc()));
uart_putc( (unsigned char)c );
while(1)
{
c = uart_getc();
if ( c & UART_NO_DATA )
{PORTB=~0x55;//for debugging
}
else
{
if ( c & UART_FRAME_ERROR )
{
/* Framing Error detected, i.e no stop bit detected */
uart_puts_P("UART Frame Error: ");
}
if ( c & UART_OVERRUN_ERROR )
{
uart_puts_P("UART Overrun Error: ");
}
if ( c & UART_BUFFER_OVERFLOW )
{
uart_puts_P("Buffer overflow error: ");
}
/*
* send received character back
*/
uart_putc( (unsigned char)c );
}
}
}
Also, hoffe es schaut sich jemand an und schaffts auch noch den fehlenden Hinweis zu geben.
Danke...
@Edit Tippfehler in ISR_RXC UART_TxHead = tmphead;<-->UART_RxHead = tmphead;