c - 通过USART将数据从atmega324p发送到arduino

标签 c arduino atmega32

我使用 Atmega 324p 每秒向 Arduino 发送字符“0”,但它收到的是:

串行监视器输出:

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

使用的软件:
爱特梅尔7
Arduino 1.8.9
Arvdudess 2.11

爱特梅尔代码:

#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 代码:

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配置:

Avrdudess configuration

电路草图:

circuit pinout

Atmega Datasheet 324p

编辑:当它得到简化并且其代码与网站引用的标签相关时,不理解愚蠢的问题关闭

更新:为了防止进一步混淆,我已将 arduino 代码更改为打印 3 次以及字符、十六进制和二进制结果

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

  }
}

这是 Serial.Monitor 输出:

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

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

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

尝试使用此代码试验“0”后的 30 个字符 >

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

  }
}

并在 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

最佳答案

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

2) 内部振荡器为 8 MHz(请参阅数据表中的 10.6),并且由于您没有提供 FUSE 设置并且代码中没有预分频器设置,因此如果清除 CKDIV8 熔丝位,CPU 可能会以 8MHz 运行( = 1),或者如果该位被编程 (= 0),则为 1 MHz,在任何一种情况下,它都不能像 FOSC 中那样为 1500000

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

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

3) 默认情况下,内部振荡器的工厂校准精度为±10%(参见数据表中的29.4.1.)

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

4) 公式(FOSC/(16*BAUD-1))有错误。除法后应减一。 IE。 (FOSC/(16 * BAUD) - 1)(另请记住,此公式将结果始终向下舍入,尽管这通常不是问题)

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

UCSR0A = (1<<U2X);

并定义

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

这使得 MYUBRR = 12,02 向下舍入为 12,并将波特率设置为每秒 9615 位,误差小于 0.2%

已添加 6) 请参阅数据表8.6。访问 16 位寄存器:

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.

因此而不是

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;

关于c - 通过USART将数据从atmega324p发送到arduino,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59487494/

相关文章:

javascript - 在 Arduino Yún 上使用 JS 根据其他网站的内容更改 CSS 样式

avr - I2C不读取

c - 插入功能

编译时检查 stdint.h 是否存在

c - 在 Unix 和 Windows 中运行程序

c - 删除数据文件中的字符串

c++ - 使用宏来显示宏的字符串化内容

mysql - C编程如何将串口数据保存到mysql数据库