原因:
我们在使用FreeRtos时,经常会遇到两个任务要使用同一个变量,举一个最简单的例子,任务一任务二同时运行,任务一为写入当前X,Y坐标值,任务二为读取当前X,Y坐标值,如果当任务一运行到刚刚更改完X坐标,还没来得及更改Y坐标值时被任务二打断,任务二运行,读取到的是当前X,坐标和老的Y坐标值,而这已经是一个新的不存在的坐标值了,数据出现错误,所以我们需要用队列来保护这些数据。
使用:
(更改自韦东山老师的课程代码)
首先在初始化时创建队列
void DHT11_Init(void)
{
DHT11_PinCfgAsOutput();
DHT11_PinSet(1);
g_xQueueDHT11 = xQueueCreate(5, sizeof(struct dht11_data));
//mdelay(2000);
}
在写入任务中写入队列
定义结构体
/*
数据结构体
*/
struct dht11_data {
int32_t humi;
int32_t temp;
};
void DHT11_Test(void)
{
int hum, temp;
int ret;
struct dht11_data data;
while (1)
{
GetI2C();
ret=DHT11_Read(&hum, &temp)
PutI2C();
if (ret !=0)
{
//printf("\n\rdht11 read err!\n\r");
DHT11_PinCfgAsOutput();
DHT11_PinSet(1);
}
else
{
data.humi=hum;
data.temp=temp;
xQueueSend(g_xQueueDHT11, &data, 0);
}
vTaskDelay(200); /* 读取周期是2S, 不能读太频繁 */
}
}
在读取队列中读取队列(显示任务)
void show_data()
{
struct input_data input;
struct led_data led;
struct dht11_data dht11;
g_xQueueDHT11=GetQueueDHT11(); /* DHT11队列 */
g_xQueueled=GetQueueled();
int len,ret,ret2;
while(1)
{
ret=xQueueReceive(g_xQueueDHT11, &dht11, 0);
ret2=xQueueReceive(g_xQueueled, &led, 0);
input.humi=dht11.humi;
input.temp=dht11.temp;
input.val=led.val;
if(ret==1)
{
GetI2C();
LCD_PrintString(0, 0, "Humidity Temp");
len = LCD_PrintSignedVal(0, 2, input.humi);
LCD_PutChar(len, 2, '%');
LCD_PrintSignedVal(9, 2, input.temp);
PutI2C();
}
if(ret2==1)
{
GetI2C();
LCD_PrintSignedVal(9, 4, input.val);
LCD_PrintString(0, 4, "LED:");
PutI2C();
}
vTaskDelay(100);
}
}