0

I'm using Atmega 324p to send each second the character '0' to Arduino but instead it receives this:

Serial Monitor output:

Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮

Sofware used:
Atmel 7
Arduino 1.8.9
Arvdudess 2.11

Atmel code:

#include "avr/io.h"
#include "util/delay.h"
#define FOSC 1500000 //Clock speed
#define BAUD 9600
#define MYUBRR (FOSC/(16*BAUD-1))


void USART_Init(unsigned int ubrr){
    /*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/*  Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void USART_Transmit( unsigned char data ){
    /* Wait for empty transmit buffer */
    //while ( !( UCSR0A & (1<<UDRE)) );
    /* Put data into buffer, sends the data */
    UDR0 = data;
}


int main(void)
{
USART_Init(MYUBRR);

/* Replace with your application code */
while (1) 
{
    USART_Transmit('0');
    _delay_ms(1000);
}

Arduino code:

char received_data;   //variable to store read data
void setup() {
  Serial.begin(9600);
}

void loop() { 
  if(Serial.available()>0)  //check for any data received
  { 
      Serial.print("Char :");    
      received_data = Serial.read();  //read received data      
      Serial.println(received_data);  //display received data
    }
}

Arvdudess config:

Avrdudess configuration

Rough circuit sketch:

circuit pinout

Atmega Datasheet 324p

edit: dont understand the dumb question shutdown when this is simplified as it gets and its code related to the tags refered by the website

UPDATE: to prevent futher confusion i' ve changed the arduino code to print 3 times and the char,hex and binary results

char received_data;   //variable to store read data
unsigned long received_data2;   //variable to store read data
byte received_data3;   //variable to store read data
int printed=0;
void setup() {
  Serial.begin(9600, SERIAL_8N2);
}

void loop() { 

    if(printed<3){
      printed++;
      Serial.print("Number of prints :");
      Serial.println(printed);  //display received data   
      while(Serial.available()<=0){ }  //check for any data received
      received_data = Serial.read(); //read received data
      while(Serial.available()<=0) { } //check for any data received
      received_data2 = Serial.read();  //read received data
      while(Serial.available()<=0){ }  //check for any data received
      received_data3 = Serial.read(); //read received data    
      Serial.print("char :");          
      Serial.println(received_data);  //display received data
      Serial.print("hex :");
      Serial.println (received_data2, HEX);   
      Serial.print("binary :");
      Serial.println (received_data3);

  }
}

And this is the Serial.Monitor output:

Number of prints :1
char :
hex :0
binary :0
Number of prints :2
char :
hex :0
binary :0
Number of prints :3
char :
hex :0
binary :0

Edit code on atmega so far

#include "avr/io.h"
#include "util/delay.h"
#define FOSC 1000000UL //Clock speed
#define BAUD 9600
#define MYUBRR (FOSC/(8*BAUD)-1)

void USART_Init(unsigned int ubrr){
    /*Set baud rate */

    UBRR0L = (unsigned char)ubrr; // First - low
    UBRR0H = (unsigned char)(ubrr>>8); // Last - high
    UCSR0A = (1<<U2X0);
    /*  Enable receiver and transmitter */
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    /* Set frame format: 8data, 2stop bit */
    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
    UBRR0 = ubrr;

}

void USART_Transmit( unsigned char data ){
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) );
    /* Put data into buffer, sends the data */
    UDR0 = data;
}


int main(void)
{

    USART_Init(MYUBRR);

    /* Replace with your application code */
    while (1)
    {

        USART_Transmit('0');
        _delay_ms(1000);
    }
}

Tried to experiment with the 30 char after '0' with this code >

Atmel code

#include "avr/io.h"
#include "util/delay.h"
#define FOSC 1000000UL //Clock speed
#define BAUD 9600
#define MYUBRR (FOSC/(8*BAUD)-1)

void USART_Init(unsigned int ubrr){
  /*Set baud rate */

  UBRR0L = (unsigned char)ubrr; // First - low
  UBRR0H = (unsigned char)(ubrr>>8); // Last - high
  UCSR0A = (1<<U2X0);
  /*  Enable receiver and transmitter */
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
  /* Set frame format: 8data, 2stop bit */
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
  UBRR0 = ubrr;

}

void USART_Transmit( unsigned char data ){
  /* Wait for empty transmit buffer */
  while ( !( UCSR0A & (1<<UDRE0)) );
  /* Put data into buffer, sends the data */
  UDR0 = data;
}


int main(void)
{

  USART_Init(MYUBRR);
  int i=0;
  /* Replace with your application code */
  while (1)
  {

      USART_Transmit('0'+i);
      i++;
      _delay_ms(1000);
  }
}

**Arduino code**

char received_data;   //variable to store read data
unsigned long received_data2;   //variable to store read data
byte received_data3;   //variable to store read data
int printed=0;
void setup() {
  Serial.begin(9600, SERIAL_8N2);
}

void loop() { 

    if(printed<30){
      printed++;
      Serial.print("Number of prints :");
      Serial.println(printed);  //display received data   
      while(Serial.available()<=0){}  //check for any data received
      received_data = Serial.read(); //read received data
        while(Serial.available()<=0){}  //check for any data received
      received_data2 = Serial.read();  //read received data
        while(Serial.available()<=0){}  //check for any data received
      received_data3 = Serial.read();  //read received data    
      Serial.print("char :");          
      Serial.println(received_data);  //display received data
      Serial.print("hex :");
      Serial.println (received_data2, HEX);   
      Serial.print("binary :");
      Serial.println (received_data3);

  }
}

And gave me this output on Arduino:

Number of prints :1
char :⸮
hex :C0
binary :0
Number of prints :2
char :⸮
hex :0
binary :0
Number of prints :3
char :⸮
hex :C0
binary :192
Number of prints :4
char :
hex :C0
binary :0
Number of prints :5
char :
hex :C0
binary :192
Number of prints :6
char :
hex :C0
binary :0
Number of prints :7
char :⸮
hex :C0
binary :192
Number of prints :8
char :
hex :C0
binary :192
Number of prints :9
char :
hex :0
binary :192
Number of prints :10
char :⸮
hex :C0
binary :0
Number of prints :11
char :⸮
hex :C0
binary :0
Number of prints :12
char :⸮
hex :C0
binary :192
Number of prints :13
char :⸮
hex :C0
binary :192
Number of prints :14
char :⸮
hex :C0
binary :0
Number of prints :15
char :⸮
hex :C0
binary :192
Number of prints :16
char :⸮
hex :C0
binary :192
Number of prints :17
char :⸮
hex :0
binary :192
Number of prints :18
char :⸮
hex :C0
binary :0
Number of prints :19
char :⸮
hex :C0
binary :0
Number of prints :20
char :⸮
hex :C0
binary :192
Number of prints :21
char :⸮
hex :C0
binary :192
Number of prints :22
char :⸮
hex :0
binary :192
Number of prints :23
char :⸮
hex :C0
binary :192
Number of prints :24
char :⸮
hex :C0
binary :0
Number of prints :25
char :⸮
hex :C0
binary :192
Number of prints :26
char :⸮
hex :C0
binary :0
Number of prints :27
char :⸮
hex :C0
binary :0
Number of prints :28
char :⸮
hex :0
binary :0
Number of prints :29
char :⸮
hex :C0
binary :0
Number of prints :30
char :⸮
hex :0
binary :0
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • Is this correct : `#define FOSC 1500000 //Clock speed` ? Perhaps you start displaying the received char in BIN mode ? – datafiddler Dec 26 '19 at 11:54
  • i mean in the datasheet had this `#define FOSC 1843200 // Clock Speed` on page 229 has a example code but i ' ve changed to 1500000 because of avrdudess configuration, but the change you suggest is it in arduino? – Alexandre Pereira Dec 26 '19 at 12:03
  • i ' ve changed the arduino code from `char` to `byte` and had this result: `byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 byte :0 ` – Alexandre Pereira Dec 26 '19 at 12:13
  • changed the char from '0' to '1' sent in atmel or the atmega and gave the same result – Alexandre Pereira Dec 26 '19 at 12:18

1 Answers1

1

1) On your circuit sketch there is no crystal on XTAL1/XTAL2. I assume it uses internal oscillator.

2) Internal oscillator is 8 MHz (see 10.6 in the datasheet) and, since you have not provided FUSE settings and there is no prescaller setting in your code, then CPU may run either at 8MHz if CKDIV8 fuse bit is cleared (= 1), or 1 MHz if the bit is programmed (= 0), in either case it cannot be 1500000 as it in FOSC

By default the bit is programmed, i.e. it should be:

#define FOSC 1000000UL // note the UL suffix for unsigned-long constants

3) By default the factory calibration accuracy of the internal oscillator is ±10% (see 29.4.1. in the datasheet)

If speed is different more than 4%, UART could not work as expected, therefore you need either to calibrate the speed or to use a crystal oscillator.

4) Formula (FOSC/(16*BAUD-1)) has an error. One should be subtracted AFTER the division. I.e. (FOSC / (16 * BAUD) - 1) (also keep in mind this formula rounds the result always downwards, although it is usually not an issue)

5) (FOSC/(16*BAUD)-1) when FOSC == 1000000 and BAUD == 9600, result will be 5,51 rounded down to 5, causing effective baudrate to be (1000000 / (6 * 16)) = 10416 bits per second, which means error of 8,5% which makes the UART unusable. To solve this issue you can set U2X bit in UCSR0A register:

UCSR0A = (1<<U2X);

and define

#define MYUBRR (FOSC/(8*BAUD)-1)

this makes MYUBRR = 12,02 rouded down to 12, and sets the baudrate to 9615 bits per second, with less that 0,2% error

ADDED 6) Please refer to the datasheet 8.6. Accessing 16-bit Registers:

For a write operation, the low byte of the 16-bit register must be written before the high byte. The low byte is then written into the temporary register. When the high byte of the 16-bit register is written, the temporary register is copied into the low byte of the 16-bit register in the same clock cycle.

Therefore instead of

UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;

it should be

UBRR0L = (unsigned char)ubrr; // First - low
UBRR0H = (unsigned char)(ubrr>>8); // Last - high

But, since avr-gcc can handle that for you, you can make it in the code simpler:

UBRR0 = ubrr;
AterLux
  • 4,566
  • 2
  • 10
  • 13
  • thanks in advance @AterLux but i changed the defines to this `#define FOSC 1000000UL #define BAUD 9600 #define MYUBRR (FOSC/(8*BAUD)-1)` and added `UCSR0A = (1< – Alexandre Pereira Dec 26 '19 at 14:57
  • Make sure the part running 1MHz, not 8 – AterLux Dec 26 '19 at 15:04
  • I'm sorry but how do i check that? – Alexandre Pereira Dec 26 '19 at 15:13
  • 1
    One way to read fuse bits: https://shawnhymel.com/622/quick-tip-reading-fuse-bits-in-an-arduino/ anotherway, add `define #F_CPU 1000000UL` in the beggining (for `_delay_ms` to work properly), and connect some led, and turn it off and on with `_delay_ms(1000)` in between. If the part running faster you'll see faster blinks – AterLux Dec 26 '19 at 15:21
  • i tested with a led on PIND6 and init with the commands ´DDRD=(1<<6); PORTD=(1<<6);´ and inputed the command ´PORTD^=(1<<6);´ after the command ´USART_Transmit('0');´ and seems to blink in 1 second interval – Alexandre Pereira Dec 26 '19 at 15:43
  • 1
    There is an issue in your code: you check `(Serial.available()>0)` for any single byte available. But then call `Serial.read()` three times. Note, if there is no data in the queue, `Serial.read()` returns -1. That's why you get FFFFFFFF and 255 in the result. – AterLux Dec 27 '19 at 12:25
  • Yes you re correct it seems i need to add while(Serial.available()<=0) before each Serial.read() already update on the post the results and the changes on arduino code – Alexandre Pereira Dec 27 '19 at 13:58
  • 1
    `while(Serial.available()<=0) {received_data = Serial.read(); }` now the loop (i.e. `Serial.read()`) runs only if there is no data available. You may want it to be `while(Serial.available()<=0) {} /*empty loop, wait for data */ received_data = Serial.read();` – AterLux Dec 27 '19 at 14:17
  • yep seems back to normal `char: ` after those changes but not a '0' and the same results on hex and byte, updated the post again – Alexandre Pereira Dec 27 '19 at 14:20
  • 1
    I've expanded the answer – AterLux Dec 28 '19 at 19:08
  • i' ve tried to change the code as you' ve advided me to do so and still got the same output. But i ' ve changed the atmel code to send '0'+i char where is incremented and had different values also edited the code on the post with the code i 've used and also the code i ' ve used to get the 30 chars after '0' – Alexandre Pereira Dec 28 '19 at 22:11