C USART从atmega324p向arduino发送数据

C USART从atmega324p向arduino发送数据,c,arduino,atmega32,C,Arduino,Atmega32,我正在使用Atmega 324p每秒将字符“0”发送到Arduino,但它接收到以下内容: 串行监视器输出: Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Char :⸮ Number of prints :1 char : hex :0 binary :0 Number of prints :2 char : hex :0 binary :0 Nu

我正在使用Atmega 324p每秒将字符“0”发送到Arduino,但它接收到以下内容:

串行监视器输出:

Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
Char :⸮
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
使用的软件: 阿特梅尔7号 Arduino 1.8.9 Arvdudess 2.11

Atmel代码:

#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);
}
Arvdudess配置:

电路草图:

编辑:不理解这个愚蠢的问题,当它被简化时,它会被关闭,它的代码与网站引用的标签相关

更新:为了防止进一步的混淆,我已经将arduino代码改为打印3次,并将char、hex和binary结果

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);

  }
}
到目前为止,在atmega上编辑代码


1在电路草图上,XTAL1/XTAL2上没有晶体。我假设它使用内部振荡器

2内部振荡器为8 MHz,见数据表中的10.6,由于您未提供保险丝设置,且代码中没有预调谐器设置,因此,如果CKDIV8保险丝位被清除=1,CPU可能以8 MHz的频率运行;如果位被编程=0,CPU可能以1 MHz的频率运行;在任何情况下,CPU都不能像在FOSC中那样以1500000的频率运行

默认情况下,该位已编程,即应为:

#define FOSC 1000000UL // note the UL suffix for unsigned-long constants
3默认情况下,内部振荡器的出厂校准精度为±10%,见29.4.1。在数据表中

如果速度差超过4%,UART无法按预期工作,因此您需要校准速度或使用晶体振荡器

4公式FOSC/16*波特-1有错误。除法后应减去一。也就是说,FOSC/16*波特-1也要记住,这个公式总是向下舍入结果,尽管这通常不是一个问题

5 FOSC/16*波特-1当FOSC==1000000且波特==9600时,结果将是5,51向下舍入为5,导致有效波特率为1000000/6*16=10416位/秒,这意味着8,5%的错误,这使得UART无法使用。 要解决此问题,可以在UCSR0A寄存器中设置U2X位:

UCSR0A = (1<<U2X);
这使得MYUBRR=12,02被降到12,并将波特率设置为每秒9615位,误差小于0,2%

增加 6请参考数据表8.6。访问16位寄存器:

对于写入操作,16位寄存器的低位字节必须在高位字节之前写入。低字节 然后写入临时寄存器。写入16位寄存器的高位字节时 临时寄存器在同一时钟周期内复制到16位寄存器的低位字节

因此而不是

UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
应该是

UBRR0L = (unsigned char)ubrr; // First - low
UBRR0H = (unsigned char)(ubrr>>8); // Last - high
但是,由于avr gcc可以为您处理这一问题,您可以在代码中简化它:

UBRR0 = ubrr;

这是否正确:定义FOSC 1500000//时钟速度?也许您开始以BIN模式显示收到的字符?我的意思是,在数据表中,第229页的定义为FOSC 1843200//时钟速度有一个示例代码,但由于avrdudess配置,我已更改为1500000,但是你建议的更改是在arduino中?我已经将arduino代码从字符改为字节,结果是:字节:0字节:0字节:0字节:0字节:0字节:0字节:0字节:0字节:0字节:0字节:0字节:0将atmel或atmega中发送的字符从“0”改为“1”,并在@AterLux之前给出了相同的结果,但我更改了定义定义FOSC 1000000UL定义波特率9600定义MYUBRR FOSC/8*波特率-1并添加UCSR0A=1读取熔丝位的一种方法:另一种方法是,在Begining中添加define F_CPU 1000000UL,以使_delay_ms正常工作,并连接一些led,在_delay_ms1000之间关闭和打开。如果部件运行得更快,您将看到更快的闪烁。代码中存在一个问题:您检查Serial.available>0以查看任何可用的单个字节。然后打电话给Serial.read三次。注意,如果队列中没有数据,Serial.read将返回-1。这就是为什么在结果中得到FFFFFFFF和255。whileSerial.available我已经扩展了答案
UCSR0A = (1<<U2X);
#define MYUBRR (FOSC/(8*BAUD)-1)
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
UBRR0L = (unsigned char)ubrr; // First - low
UBRR0H = (unsigned char)(ubrr>>8); // Last - high
UBRR0 = ubrr;