繁体   English   中英

AVR UART 读取一个字节两次

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM