我正在使用Tiva Launchpad EK-TM4C123GXL和ESP8266 WIFI模块。
当这个模块得到一个wifi数据包时,它会通过UART端口将它发送给微控制器。
ESP8266用于发送数据包(通过UART发送到uC )的格式是:
+IPD,n:xxxxx\r\nOK\r\n
其中:
n是数据包的长度(以字节为单位)。:表示下一个字节将是第一个数据字节。xxxxx是数据包\r\nOK\r\n是6个字节,对我来说是无用的。例如:
+IPD,5:hello\r\nOK\r\n
这里是我的情况:
我正在做一个现有的项目,在那里我不能改变这两件事:
1- UART模块已经配置为在接收FIFO ( 16字节)半满时产生中断。
2-处理此中断的ISR (中断服务例程):
现在,我必须用C语言编写这个名为rx_data()的函数。
因此,来自ESP8266模块的消息一次传递给这个函数,rx_data(),一个字节,这个函数必须能够:
+IPD,nxxxxx (位于:字符之后和第一个\r字符之前)保存到缓冲区中。\r\nOK\r\n (这6个字节对我来说是无用的,但无论如何,我必须读取它们以从接收FIFO中删除它们)我想一步一步地工作,所以现在我在推理:
如何识别+IPD,,考虑到一次只有一个字节,被传递给这个函数?
发布于 2016-06-02 00:17:10
现在是建立状态机的时候了。每次调用rx_data时,您都会更新状态机的状态,最终您会知道您已经收到了字符串"+IPD,“。
可以工作的最简单的事情是这样的,假设从UART接收的字节作为参数传递给rx_data。
void rx_data(uint8_t byte)
{
static uint8_t state = 0;
if (byte == '+') { state = 1; }
else if (state == 1 && byte == 'I') { state = 2; }
else if (state == 2 && byte == 'P') { state = 3; }
else if (state == 3 && byte == 'D') { state = 4; }
else if (state == 4 && byte == ',') {
state = 0;
handleIPDMessage(); // we received "+IPD,"
}
else { state = 0; }
}您可以看到,只有当最后接收到的字符是"+IPD,“时才调用handleIPDMessage()。
但是,您应该考虑编写一个更通用的状态机,它可以在行上操作,而不是只查找这个字符串。这可能会更容易编写和更健壮。当收到完整的行时,您将调用一个名为handleLineReceived()的函数来处理该行。该函数可以访问整个行的缓冲区,并且可以以任何它想要的方式解析它。(只是要小心,不要在缓冲区的末尾写东西。)
顺便说一句,我不会把这样的逻辑放在ISR里。通常最好保持ISRs的简单和快速。如果您还没有这样做,请将字节存储到ISR中的循环缓冲区中,然后从主循环中的循环缓冲区读取,并且每次从循环缓冲区读取字节时,都调用类似上述的rx_data函数来处理该字节。
https://stackoverflow.com/questions/37580655
复制相似问题