Dobrý den,
začínám programovat AVR a rád bych požádal o radu ohledně opuštění nekonečné smyčky po přerušení. Používám nejnovější AVR STUDIO 5 a ATmega88-20PU.
Jde o v celku jednoduchý program s bufrovanou RS232 komunikací s PC.
Problém tkví v tom, že pokud program spustím, okamžitě začne cyklicky nabíhat main() znovu a znovu. Na terminál se mi odesílají v nekonečné smyčce znaky 0xAA.
Na fórech jsem četl o FUSE compatibility mode, nicméně jsem nic takového mezi FUSE bity v datasheetu nenašel.
Můžete mi prosím poradit kde dělám chybu?
Díky moc.
code:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define BUFFER_LENGHT 8
#define USART_BAUD 9600ul
#define BAUD_PRESCALE (((F_CPU / (USART_BAUD * 16UL))) - 1)
static volatile unsigned char RX_buffer[BUFFER_LENGHT];
static volatile unsigned char TX_buffer[BUFFER_LENGHT];
static volatile unsigned char RX_buffer_write_pos=0;
static volatile unsigned char TX_buffer_write_pos=0;
static volatile unsigned char RX_buffer_read_pos=0;
static volatile unsigned char TX_buffer_send_pos=0;
void init_usart(void)
{
UCSR0A=0x00;
//baud rate 9600
UBRR0L = (unsigned char)BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRR0H = (unsigned char)(BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
/* Receive complete interrupt enable, Receiver & Transmitter enable */
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0);
// Set frame format to 8 data bits, no parity, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}
SIGNAL(USART_RX_vect)
{
unsigned char c = UDR0;
unsigned char i = (unsigned char)(RX_buffer_write_pos + 1) % BUFFER_LENGHT;
//when not enough space in buffer throw it out
if (i != RX_buffer_read_pos)
{
RX_buffer[RX_buffer_write_pos] = c;
RX_buffer_write_pos = i;
SETBIT(IDEOS_sreg, USART_RX_DATA_REDY);
}
}
SIGNAL(USART_UDRE_vect)
{
//sending complete
if (TX_buffer_send_pos == TX_buffer_write_pos)
{
//disable UDR empty interrupt
UCSR0B &= ~(1<<UDRIE0);
}
//continue sending
else
{
unsigned char c = TX_buffer[TX_buffer_send_pos];
TX_buffer_send_pos = (TX_buffer_send_pos + 1) % BUFFER_LENGHT;
UDR0 = c;
}
}
void USART_SendByte(unsigned char s)
{
unsigned char i = (unsigned char)(TX_buffer_write_pos + 1) % BUFFER_LENGHT;
//wait for empty buffer
while(i == TX_buffer_send_pos)
{
;
}
//add char to buffer
TX_buffer[TX_buffer_write_pos]= s;
TX_buffer_write_pos = i;
//wait for empty UDR, enable UDR empty interrupt
UCSR0B |= (1<<UDRIE0);
}
void USART_SendBytes(unsigned char *s)
{
while (*s)
{
TX_buffer_write_pos %= BUFFER_LENGHT;
TX_buffer[TX_buffer_write_pos]= *( (unsigned char *)s );
TX_buffer_write_pos++;
s++;
}
//disable UDR empty interrupt
UCSR0B &= ~(1<<UDRIE0);
//UDR empty?
if ((UCSR0A & (1<<UDRE0)))
{
UDR0 = TX_buffer[TX_buffer_send_pos];
TX_buffer_send_pos++;
}
//wait for empty UDR, enable UDR empty interrupt
UCSR0B |= (1<<UDRIE0);
}
unsigned char USART_ReceiveByte()
{
unsigned char tmp;
//nothing to read
if(RX_buffer_read_pos == RX_buffer_write_pos)
{
return -1;
}
tmp = RX_buffer[RX_buffer_read_pos];
RX_buffer_read_pos = (unsigned char)(RX_buffer_read_pos + 1) % BUFFER_LENGHT;
return tmp;
}
unsigned char USART_RXDataReady(void)
{
return (unsigned char)(BUFFER_LENGHT + RX_buffer_write_pos - RX_buffer_read_pos) % BUFFER_LENGHT;
}
int main(void)
{
unsigned char byte;
// Init USART
cli();
init_usart();
sei();
// Send string
USART_SendByte(0xAA);
// Repeat indefinitely
for (;;)
{
if(USART_RXDataReady() > 0)
{
byte = USART_ReceiveByte();
USART_SendByte(byte);
}
}
return 0;
}