如何修复Particle与ATMEGA8535之间的UART通信异常问题
UART通信数据异常:ATMEGA8535发送至Particle时数值跳变
问题背景
硬件连接:ATMEGA8535的RX、TX引脚通过双向逻辑电平转换器连接到Particle对应引脚,防止Particle被损坏。
异常现象
发送整数序列0、1、2、3……时,Particle初始能正确解析,但出现如下跳变:
- 计数到31后,下一个接收值变为0
- 第二个0之后计数到63,跳变为32
- 计数到95时跳变为64,127时跳变为96
两端代码
Particle端代码
void setup() { // Start the serial connection Serial1.begin(9600); } void loop() { // put your main code here, to run repeatedly: if (Serial1.available()) { // Reading the received byte and publishing it to the particle cloud int in = Serial1.read(); Particle.publish("test", String(in)); } }
ATMEGA8535端代码
#define F_CPU 1000720UL //CPU frequency #include <xc.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #define BAUD 9600 // baud #define BRC ((F_CPU/16/BAUD) - 1) int main(void) { /* Set baud rate */ UBRRH = (BRC >> 8); UBRRL = BRC; /* Enable receiver and transmitter and Set frame format: 9data, 2stop bit */ UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<UCSZ2); UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)|(1<<USBS); // The counter variable int i = 0; while(1){ // Setting the UART data register to send the counter and incrementing the counter UDR = i; i++; _delay_ms(400); } }
已排查操作
- 示波器检测显示,跳变时ATMEGA发送的信号规律正常
- 修改帧格式:使用少于9位数据时异常更严重(8位数据时从128开始计数),停止位数量对异常无明显影响
- ATMEGA未连接晶振,通过
_delay_ms()调整时钟频率
问题原因
ATMEGA配置了9位数据位(UCSRB的UCSZ2置1,UCSRC的UCSZ1和UCSZ0置1,对应9位数据帧),但Particle的Serial1.begin(9600)默认使用8位数据位,两端帧格式不匹配,导致高比特位被丢弃或解析错误,出现数值跳变。
解决方案
方案1:修改ATMEGA为8位数据位
调整ATMEGA的UART配置代码,去掉9位数据位的设置:
// 原UART配置代码 UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<UCSZ2); UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)|(1<<USBS); // 修改为8位数据位、2停止位(保持停止位一致) UCSRB = (1<<RXEN)|(1<<TXEN); // 移除UCSZ2位 UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)|(1<<USBS);
方案2:修改Particle为9位数据位
在Particle端初始化Serial1时指定9位数据位(Particle的Serial支持Serial1.begin(baud, config)格式):
void setup() { // 配置9位数据位、2停止位、无校验,与ATMEGA匹配 Serial1.begin(9600, SERIAL_9N2); }
注意:优先选择方案1,因为8位数据位是UART通用格式,兼容性更好;若必须使用9位数据位,再选择方案2。
内容的提问来源于stack exchange,提问作者M_Kotamech
相关产品推荐
相关产品推荐

