0
\$\begingroup\$

I'm trying to make an ATMega328P to send serial data to my computer and print onto Putty using an arduino board to do the USB to serial conversions. The data that's printed, however is garbage data. I've tried changing the number of stop bits, checked the serial communications in putty, checked the Baud error rates, and have also added a delay so that the computer can read the serial data easier. Here's the code:

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>

#define USART_BAUDRATE 9600
#define F_CPU 7372800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void printString(const char myString[]){
    uint8_t i = 8;
    while(myString[i]){
       while ((UCSR0A &(1<<UDRE0)) == 0){}//do nothing until transmission flag is set
          UDR0 = myString[i];
          i++;
    }    
}

int main(void)
{
    //--------------init usart----------------//
    UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Enables the USART transmitter and receiver
    _delay_ms(10);
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(USBS0<<1); //tells it to send 8bit characters (setting both USCZ01 and UCSZ00 to one)
    //now it has 2 stop bits.

    UBRR0H = (BAUD_PRESCALE >> 8); //loads the upper 8 bits into the high byte of the UBRR register
    UBRR0L = BAUD_PRESCALE; //loads the lower 8 bits
    //----------------------------------------//
    _delay_ms(10);


    for(;;){
    printString("Hello World!\r\n");
    }
return (0);
}

And the data that's displayed in putty is as follows. First there's a bunch of this: àà àà à à àà àà àà à. Then there's a bunch of this: f,Mün$M´M,M´M$M´M,M´M,M´M,M´M and other similar characters. I don't know why these are getting printed. Thanks.

edit: here's the datasheet

\$\endgroup\$
  • \$\begingroup\$ That looks like a case of setting the wrong baud rate. Or Setting Putty to the wrong baud rate. Are you sure your BAUD_PRESCALE is correct? \$\endgroup\$ – John Honniball Nov 25 '14 at 10:09
  • \$\begingroup\$ The datasheet sais that the baud prescale value needs to be equal to the system clock divided by the desired baud rate times sixteen. Then one is subtracted. BAUD_PRESCALE = (clock/(16(BAUD)))-1. Entering 7372800 for the clock and 9600 for the baud rate, I get 47. I chose this to get a 0.0% Baud rate error. I'm not sure what would be wrong with it. Could you elaborate? Also, I checked putty and its set for a baud of 9600 with 2 stop bits. \$\endgroup\$ – Cate Nov 25 '14 at 10:26
  • \$\begingroup\$ The CKDIV8 fuse is set by default, make sure that it's disabled or your cpu clock will be 1/8 of what it should be and UART calculations will be wrong. \$\endgroup\$ – alexan_e Nov 25 '14 at 10:41
  • \$\begingroup\$ Ok, I added this line to the beginning of the main code: "CLKPR = (0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);" and it still outputs the same thing (garbage data). It doesn't seem to be the problem, but I was unaware of this the clock division. Thanks though. \$\endgroup\$ – Cate Nov 25 '14 at 10:51
  • 1
    \$\begingroup\$ To set for clock prescaling factor it is necessary to access the CLKPR twice within 4 clock cycles. Try adding #include <avr/power.h> and then use clock_prescale_set(clock_div_1);. Refer to electronics.stackexchange.com/a/93209/33841. \$\endgroup\$ – alexan_e Nov 25 '14 at 10:57
2
\$\begingroup\$

This line looks suspicious:

UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(USBS0<<1);

You probably want that to be:

UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(1<<USBS0);

\$\endgroup\$
  • \$\begingroup\$ Now the nonsense in repeating on a single line instead of filling up putty's whole screen. Thanks for catching that. It's a start, but it doesn't solve my problem. \$\endgroup\$ – Cate Nov 25 '14 at 20:52
  • \$\begingroup\$ @Cate You have uint8_t i = 8; but shouldn't it be uint8_t i = 0; ? Zero rather than eight? \$\endgroup\$ – John Honniball Nov 25 '14 at 22:10
  • \$\begingroup\$ Nope, it still doesn't work. \$\endgroup\$ – Cate Nov 25 '14 at 22:36
0
\$\begingroup\$

I asked the people at AVR Freaks and they said that F_CPU doesn't actually change the clock speed; it only is used to set the baud prescale. Since the arduino runs at 16MHz, I just had to change F_CPU to 16000000 and then change uint8_t i=8; to uint8_t i=0;.

\$\endgroup\$
0
\$\begingroup\$
((UCSR0A &(1 << UDRE0)) == 0)

check this line on the atmega328 datasheet > UART > UART initialization code available there. I think that might be your problem, I think it should be

((!(UCSR0A &(1 << UDRE0)))

don't add == 0.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.