I seem to be getting random character in my USART output with an ATMEGA8
uart.c
#define FOSC 8000000
#define BAUD_RATE 9600
#define UBRR_VALUE (uint16_t)(FOSC/16/BAUD_RATE-1)
#include "uart.h"
volatile u8buf UART_RCV_BUFFER;
FILE uart0_str = FDEV_SETUP_STREAM(UARTSendByte, UARTReceiveByte, _FDEV_SETUP_RW);
ISR(USART_RXC_vect)
{
//got a byte from USART. add to buffer
volatile uint8_t data;
scanf("%c",&data);
if((UART_BUFFER_WRITE(&UART_RCV_BUFFER, data)==1) || (data=='.'))
{
//either buffer full or '.' received
//stop the UART receiver unit + disable interrupt
UCSRB &= ~((1<<RXEN) | (1<<RXCIE));
}
}
ISR(USART_UDRE_vect)
{
volatile uint8_t data;
if(UART_BUFFER_READ(&UART_RCV_BUFFER, &data)==1)
{
//end of buffer reached. nothing more to transmit
//disable RX
UCSRB &= ~((1<<RXEN) | (1<<RXCIE));
//reset buffer
UART_BUFFER_INIT(&UART_RCV_BUFFER);
//enable RX side
UCSRB |= ((1<<RXEN) | (1<<RXCIE));
}
else printf("%c",&data);
}
void UART_WRITE_STRING(char* str)
{
//Sending a string without any command
//disable RX/TX interrupts
UCSRB &= ~((1<<RXCIE) | (1<<UDRIE));
printf("%s",str);
//re-enable RX/TX interrupts
UCSRB |= (1<<RXCIE) | (1<<UDRIE);
}
void UART_INIT(void)
{
UBRRH = (uint8_t)(UBRR_VALUE>>8); //set UBRR register
UBRRL = (uint8_t)UBRR_VALUE;
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);//set frame format: asynchronous,8data,1stop,no parity
UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE) | (1<<UDRIE);
UART_BUFFER_INIT(&UART_RCV_BUFFER);
stdin=&uart0_str;
stdout=&uart0_str;
}
void UART_BUFFER_INIT(volatile u8buf *buf)
{
buf->index = 0;
}
uint8_t UART_BUFFER_WRITE(volatile u8buf *buf, volatile uint8_t data)
{
if(buf->index<UART_RCV_BUF_SIZE)
{
buf->index = data;
buf->index++;
return 0;
}
else return 1;
}
uint8_t UART_BUFFER_READ(volatile u8buf *buf, volatile uint8_t *data)
{
if(buf->index>0)
{
buf->index--;
*data = buf->buffer[buf->index];
return 0;
}
else return 1;
}
int UARTSendByte(char u8data, FILE *stream)
{
if(u8data=='\n')
{
UARTSendByte('\r',0);
}
while(!(UCSRA&(1<<UDRE))){};
UDR = u8data;
return 0;
}
int UARTReceiveByte(FILE *stream)
{
uint8_t data;
// Wait for byte to be received
while(!(UCSRA&(1<<RXC))){};
data=UDR;
//echo input data
UARTSendByte(data,stream);
// Return received data
return data;
}
main.c
#include "uart.h"
#include "twi.h"
int main (void)
{
DDRC = 0x01; //set PC0 as output
PORTC = 0x01; //turn on PC0
//PD0 = RXD = INPUT
//PD1 = TXD = OUTPUT
DDRD = 0x03;
UART_INIT(); //initialize UART
sei(); //Enable global interrpts
//_delay_ms(500);
UART_WRITE_STRING("Hello World ! 1:)\n");
UART_WRITE_STRING("Hello World ! 2:)\n");
UART_WRITE_STRING("Hello World ! 3:)\n");
for(;;)
{
}
}
This upon execution should give me
Hello World ! 1:)
Hello World ! 2:)
Hello World ! 3:)
But what i get is
\n\nHello World ! 1:)
Hello World ! 2:)
Hello World ! 3:)
the number of \n is random. Sometimes there is none, sometimes 1 or 2 or 3. Any idea what I am doing wrong here?
printf
? I don't see what you did there. YourUSART_WRITE_STRING()
just callsprintf
. Without proper spacing and indentions the code is a bit hard to read. Check out an earlier version of a USART implementation I wrote for the AtMega328p here. I think I had some issues with setting the baud rate with that code, so just change that part and it should work just fine. I can post my final version later if you want once I have access to it. I also appear to have left outusart_writeString()
at that point. \$\endgroup\$usart_writeByte()
in a loop until thechar*
points to'\0'
since the passed string literals are always null-terminated. \$\endgroup\$