Reputation: 1969
Below is a code ran on an ATmega328P. It's supposed to send "abcdef" to my computer every second. However, it sent me only "ab" every second. What is wrong here?
#include <avr/io.h>
#include <util/delay.h>
void USART_transmit(unsigned char data);
void print(const unsigned char *buffer, size_t n);
void print(const char* str);
int main(void) {
// Serial.begin(115200)
UCSR0B |= (1<<TXEN0);
UBRR0L = 8;
while(1){
// Serial.write(i)
print("abcdef");
_delay_ms(1000);
}
}
void USART_transmit(const uint8_t data) {
/* wait for empty transmit buffer */
while (!UCSR0A & (1<<UDRE0));
UDR0 = data;
}
void print(const uint8_t *buffer, size_t n) {
while(n--){
USART_transmit(*buffer++); //**
}
}
void print(const char *str) {
if(strlen(str) != 0) print((const uint8_t *) str, strlen(str));
}
The code resulted in:
ababababababababababab...
Changing from USART_transmit(*buffer++);
to USART_transmit(n + 48);
(+48 to convert to char) resulted in:
5454545454545454545454545454...
So I guess the loop shouldn't be stopping?
Upvotes: 0
Views: 529
Reputation: 6092
The "data register empty" check is wrong.
while (!UCSR0A & (1<<UDRE0));
should be
while (!(UCSR0A & (1 << UDRE0)));
In your case, the check is not blocking until the buffer is empty. I think one byte is buffered in the USART output buffer and one byte is pending in UDR. Every additional byte is then discarded, this is why you see only "ab".
Upvotes: 2