【发布时间】:2022-11-04 17:30:06
【问题描述】:
我尝试使用硬件计时器定期从外部设备读取数据。 更具体地说,我实现了一个使用 gpio 模拟 SPI 协议的自定义驱动程序,每当发生硬定时器中断时,都会调用该驱动程序来读取 gpio 状态。计时器设置为 2k。
当中断发生时,isr 应将样本数据放入缓冲区。当缓冲区满时,应用程序会暂停定时器,并通过 mqtt 协议将这些数据发送出去。使用信号发生器和示波器,我发现数据很好。整个过程按预期进行。
问题是采样过程不是连续的。当通过wifi发送数据时,定时器暂停,没有数据可以读入缓冲区。
为了解决这个问题,我创建了一个专门的任务来负责向外传输数据。然后我使用乒乓缓冲区来存储样本数据。当一个缓冲区满时,通知发送任务将这些数据发送出去,同时定时器isr不断将数据放入另一个缓冲区。
起初我想只从 isr 发送通知(使用 xQueueSendFromISR()),这被证明是不可靠的。我发现只有少数通知能够发送到发送任务。所以我不得不使用旗帜。当一个缓冲区已满时,该标志设置为真,当一个特殊任务循环这个标志时,只要发现该标志为真,就会通知发送任务。
timer_isr()
{
read_data_using_gpio;
if(one buffer is full)
{
set the flag to true
}
}
task_1()
{
while(1)
{
if(the flag is true)
{
set the flag to false;
xQueueSend;
}
vTaskDelay(50ms)//it will cost 200ms to fill up the buffer
}
}
task_2()
{
while(1)
{
xStatus = xQueueReceive;
if(xStatus==pdPASS) // A message from other tasks is received.
{
transmitting data out using mqtt protocol.
}
}
}
然后我得到了如下可怕的数据。 terroble data 我用示波器检查了isr中的gpio操作。 oscilloscope1 oscilloscope2 所以似乎有些 isr 没有被触发?但发生了什么?
更奇怪的是:我添加了另一个任务,通过 i2s 从音频芯片获取数据。我再次使用乒乓缓冲区并将通知发送到同一个发送任务。
timer_isr()
{
read_data_using_gpio;
if(one buffer is full)
{
set the flag to true
}
}
task_1()
{
while(1)
{
if(the flag is true)
{
set the flag to false;
xQueueSend;
}
vTaskDelay(50ms)
}
}
task_3()
{
while(1)
{
i2s_read_to_buffer;
xQueueSend;
}
}
task_2()
{
while(1)
{
xStatus = xQueueReceive;
if(xStatus==pdPASS) // A message from other tasks is received.
{
if(data from task_1)
{
do something;
transmitting data out using mqtt protocol
}
if(data from task_2)
{
do something;
transmitting data out using mqtt protocol
}
}
}
}
而这一次,前一个任务的数据变好了! data_ok
而且,我在发送任务中注释了任务2相关代码后,数据又变坏了! 所以发生了什么事?有人可以给出任何提示吗?
task_2()
{
while(1)
{
xStatus = xQueueReceive;
if(xStatus==pdPASS) // A message from other tasks is received.
{
if(data from task_1)
{
do something;
transmitting data out using mqtt protocol
}
if(data from task_2)
{
// do something;
// transmitting data out using mqtt protocol
}
}
}
}
【问题讨论】:
标签: wifi esp32 freertos isr esp-idf