[英]AVR UART reads a single byte twice
我目前正在编写一个 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 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] 来解决这个问题,但我很好奇我在这里做错了什么。
查看函数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? */
}
部分问题在于您设置了一个状态,然后在同一次传递中对其进行操作。 更改代码以在处理特定字符后退出例程,或者将第二个和第三个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,您的状态为“RX in progress”。
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;
}
}
顺便说一句,您的状态机中还有其他漏洞。 如果在行尾标记之前获得太多字符会怎样?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.