我目前正在编写UART接收代码,该代码使用AVR ATtiny87从另一台计算机读取和解析命令。 这个想法是检测起始字符并将其存储在缓冲区中,并继续存储UART字节,直到接收到0x0a(FL)。我这样做没有问题,但是由于某种原因,我的代码读取了每个字节两次。以下是我的函数,该函数由内核循环调用。
z
当我发送* H(CR)(FL)时,我希望decode_vehicle_command()函数吐出* H(CR)(FL)。但是,我一直看到** HH(CR)(CR)(FL)(FL)。我可以通过使用RX_buffer-> buffer [2]而不是RX_buffer-> buffer [1]来解决此问题,但是我很好奇我到底在做什么错。
非常感谢您!
答案 0 :(得分:3)
查看功能vehicle_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_packet.state = BUFFER_RX_IN_PROG
后,您只需输入第二个条件,就可以输入第二个条件。在第二个条件中,您再次将byte
保存到缓冲区-每个
if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
...
通常,对于这些条件,我使用switch
(或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? */
}
答案 1 :(得分:1)
部分问题是您设置了一个状态,然后在同一遍操作中对其进行操作。更改代码以在处理特定字符后退出例程,或者将第二和第三条if
语句更改为else if
。
通过调试器逐步了解我的意思。
将状态设置为空闲,将接收到的字符设置为“ *”,您将获得以下序列:
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,您的状态为“正在进行接收”。
if(compass_packet.state == BUFFER_RX_IN_PROG) {
// TRUE because you just set it in the previous block
compass_packet.buffer[compass_packet.index] = byte;
// here you've now stored the leading character '*' again
(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_IDLE) {
if(byte == '*' || byte == '#') {
compass_packet.buffer[0] = byte;
compass_packet.index = 1;
compass_packet.state = BUFFER_RX_IN_PROG;
}
} else if(compass_packet.state == BUFFER_RX_IN_PROG) {
compass_packet.buffer[compass_packet.index] = byte;
(compass_packet.index)++;
if( byte == 0x0a) {
compass_packet.size = compass_packet.index;
compass_packet.state = BUFFER_RX_DONE;
decode_vehicle_command(&compass_packet);
compass_packet.state = BUFFER_RX_IDLE;
}
}
在状态机中还有其他漏洞,顺便说一句。如果在行尾标记之前输入太多字符会怎样?