C AVR UART读取单个字节两次
我目前正在编写一个UART接收代码,使用AVR ATtiny87读取和解析来自另一台机器的命令。 其思想是检测起始字符并将其存储在缓冲区中,并一直存储UART字节,直到接收到0x0a(FL)。我不反对这样做,但出于某种原因,我的代码每个字节读取两次。下面是我的函数,它由我的内核循环调用C AVR UART读取单个字节两次,c,avr,uart,C,Avr,Uart,我目前正在编写一个UART接收代码,使用AVR ATtiny87读取和解析来自另一台机器的命令。 其思想是检测起始字符并将其存储在缓冲区中,并一直存储UART字节,直到接收到0x0a(FL)。我不反对这样做,但出于某种原因,我的代码每个字节读取两次。下面是我的函数,它由我的内核循环调用 void vehicle_recv(void) { uint8_t n = 0; char byte; byte = LINDAT; //Reads and stores the content of the
void vehicle_recv(void) {
uint8_t n = 0;
char byte;
byte = LINDAT; //Reads and stores the content of the UART data register.
if(compass_packet.state == BUFFER_RX_IDLE) {
if(byte == '*' || byte == '#') {
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
}
if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
if(byte == 0x0a) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
compass_packet.size = compass_packet.index;
compass_packet.state = BUFFER_RX_DONE;
}
}
if(compass_packet.state == BUFFER_RX_DONE) {
decode_vehicle_command(&compass_packet);
compass_packet.state = BUFFER_RX_IDLE;
}
}
uint8_t decode_vehicle_command(struct compass_comm_packet *RX_buffer) {
debugChar(debug_str);
sendChar(RX_buffer->buffer[0]);
sendCRLF();
sendChar(RX_buffer->buffer[1]);
sendCRLF();
sendChar(RX_buffer->buffer[2]);
sendCRLF();
sendChar(RX_buffer->buffer[3]);
sendCRLF();
sendChar(RX_buffer->buffer[4]);
sendCRLF();
sendChar(RX_buffer->buffer[5]);
sendCRLF();
sendChar(RX_buffer->buffer[6]);
sendCRLF();
sendChar(RX_buffer->buffer[7]);
sendCRLF();
uint8_t return_value = 0;
if(RX_buffer->buffer[0] == '*') {
switch(RX_buffer->buffer[1]) {
case 'H':
strcpy(debug_str, "Heading\r\n");
debugChar(debug_str);
break;
case 'R':
strcpy(debug_str, "Reset\r\n");
debugChar(debug_str);
break;
case 'S':
strcpy(debug_str, "Stop\r\n");
debugChar(debug_str);
break;
case 'C':
strcpy(debug_str, "Calibrate\r\n");
debugChar(debug_str);
break;
}
}
当我发送*H(CR)(FL)时,我希望decode_vehicle_command()函数会吐出*H(CR)(FL)。然而,我一直看到**HH(CR)(CR)(FL)(FL)。我可以通过使用RX_buffer->buffer[2]而不是RX_buffer->buffer[1]来解决这个问题,但我很好奇我到底做错了什么。部分问题在于,您设置了一个状态,然后在同一过程中对其进行操作。处理特定字符后,将代码更改为退出例程,或将第二个和第三个
if
语句更改为else if
用调试器一步一步地检查它,看看我的意思
将状态设置为idle,将接收的字符设置为“*”,您将得到以下序列:
if(compass_packet.state == BUFFER_RX_IDLE) {
// TRUE
if(byte == '*' || byte == '#') {
// TRUE
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
}
此时,前导字符存储在缓冲区中,索引为1,您的状态为“正在接收”
换行符终止字符也有类似的问题
尝试:
顺便说一句,您的状态机中还有其他漏洞。如果在行尾标记之前有太多字符,会发生什么情况?查看函数
vehicle\u recv()
,您有:
if(compass_packet.state == BUFFER_RX_IDLE) {
if(byte == '*' || byte == '#') {
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
}
if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
if(byte == 0x0a) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
compass_packet.size = compass_packet.index;
compass_packet.state = BUFFER_RX_DONE;
}
}
if(compass_packet.state == BUFFER_RX_DONE) {
decode_vehicle_command(&compass_packet);
compass_packet.state = BUFFER_RX_IDLE;
}
在第一个条件中设置compass\u packet.state=BUFFER\u RX\u(在_PROG
中)后,输入第二个条件,因为您刚刚设置了要这样做的状态。在第二个条件中,您再次将字节保存到缓冲区---每个字节都保存相同的字节
if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
...
通常,我对这些条件使用开关
(或if…else
);这可能也是您的需要:
switch(compass_packet.state) {
case BUFFER_RX_IDLE:
if(byte == '*' || byte == '#') {
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
break;
case BUFFER_RX_IN_PROG:
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
if(byte == 0x0a) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
compass_packet.size = compass_packet.index;
compass_packet.state = BUFFER_RX_DONE;
}
break;
case BUFFER_RX_DONE:
decode_vehicle_command(&compass_packet);
compass_packet.state = BUFFER_RX_IDLE;
break;
default:
/* WTF? */
}
如果不看你的代码,另一台设备可能会回显接收到的字符吗?我不这么认为。我给sendChar打了8次电话,我得到了8个字符。你应该添加compass\u comm\u packet
结构的最小定义,以及vehicle\u recv()
的使用及其上下文。天哪,我觉得自己很笨。非常感谢你抓住了我的错误。非常感谢!是的,你是对的。我当然也应该处理好这种情况。
if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
...
switch(compass_packet.state) {
case BUFFER_RX_IDLE:
if(byte == '*' || byte == '#') {
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
break;
case BUFFER_RX_IN_PROG:
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
if(byte == 0x0a) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
compass_packet.size = compass_packet.index;
compass_packet.state = BUFFER_RX_DONE;
}
break;
case BUFFER_RX_DONE:
decode_vehicle_command(&compass_packet);
compass_packet.state = BUFFER_RX_IDLE;
break;
default:
/* WTF? */
}