0

我正在使用 Atmega 324p 每秒将字符“0”发送到 Arduino,但它却收到了这个:

串行监视器输出:

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

使用的软件:
Atmel 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
    }
}

Arvdudes 配置:

Avrdudes 配置

粗略的电路草图:

电路引出线

Atmega 数据表 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 个字符 >

爱特梅尔代码

#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
4

1 回答 1

1

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

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

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

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

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

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

4) 公式(FOSC/(16*BAUD-1))有误。除法后应减一。即 (FOSC / (16 * BAUD) - 1) (还要记住这个公式总是向下舍入结果,尽管它通常不是问题)

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

UCSR0A = (1<<U2X);

并定义

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

这使得 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;
于 2019-12-26T14:35:50.740 回答