#include "stm32f10x.h" // Device header #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" #include "LED.h" #include "DHT11.h" #include "USART3.h" #include "LoRa.h" #include "Relay.h" /* 在创建任务前,需要创建一个任务句柄,每个任务句柄与任务一一对应。 */ TaskHandle_t xStateLedTaskHdlr; TaskHandle_t xDht11TaskHdlr; TaskHandle_t xRelayCtrlTaskHdlr; TaskHandle_t xLoRaToGateTskHdlr; /* 创建队列句柄 */ QueueHandle_t xTempQueueHdlr; QueueHandle_t xHumiQueueHdlr; /* 闪烁LED任务函数,参数为空指针,返回NULL。 */ void vStateLedTask(void *pvParameters) { while(1) { vPc13LedOn(); vTaskDelay(1000); vPc13LedOff(); vTaskDelay(1000); } } void vDht11Task(void *pvParameters) { DHT11Data_t xDHT11Data; /* 数据存储数组。要求与队列参数设置大小一一对应。 */ uint8_t ucSendTempBuffer[5] = {0}; uint8_t ucSendHumiBuffer[5] = {0}; while (1) { /* code */ if (vDht11Init() != 0) { /* 初始化失败,进行错误处理 */ // vUsart3Printf("DHT11 Init Failed\r\n."); for (int iIndex = 0; iIndex < 5; iIndex++) { ucSendTempBuffer[iIndex] = 0xAA; vTaskDelay(50); ucSendHumiBuffer[iIndex] = 0xAA; vTaskDelay(50); } } if (vDht11ReadData(&xDHT11Data.ucTemp,&xDHT11Data.ucHumi) == 0) { /* code */ for (int iIndex = 0; iIndex < 5; iIndex++) { /* code */ ucSendTempBuffer[iIndex] = xDHT11Data.ucTemp; vTaskDelay(50); ucSendHumiBuffer[iIndex] = xDHT11Data.ucHumi; vTaskDelay(50); } /* 写队列。第一个参数是队列句柄,第二个是写入队列的地址(如数组),第三个是因队列满造成阻塞时的等待时长,也就是无法写入数据时的等待时长,以操作系统默认时钟节拍为准。 */ xQueueSend(xTempQueueHdlr, ucSendTempBuffer, 0); xQueueSend(xHumiQueueHdlr, ucSendHumiBuffer, 0); } else { // vUsart3Printf("DHT11 Read Data Failed\r\n."); for (int iIndex = 0; iIndex < 5; iIndex++) { ucSendTempBuffer[iIndex] = 0xAB; vTaskDelay(50); ucSendHumiBuffer[iIndex] = 0xAB; vTaskDelay(50); } } } } void vRelayControlTask(void *pvParameters) { } void vLoRaToGatePktTask(void *pvParameters) { uint8_t ucRecTempBuffer[5] = {0}; uint8_t ucRecHumiBuffer[5] = {0}; /* 定义一个返回值判断是否接收成功 */ BaseType_t xQueueTempRetval, xQueueHumiRetval; while (1) { /* code */ /* 接收队列:队列句柄、给哪个接收数据缓冲区和未接收到数据的等待时长,分3种情况,分别为0、0~portMAX_DELAY和portMAX_DELAY三种,分别对应 * 一点不等、等一点时间和等最大时间。在等待队列数据的情况下,该接收队列所在的任务会一直处于阻塞态。 */ xQueueTempRetval = xQueueReceive(xTempQueueHdlr, ucRecTempBuffer, 0); xQueueHumiRetval = xQueueReceive(xHumiQueueHdlr, ucRecHumiBuffer, 0); /* 发送 */ vLoRaConnectionPkt(); vLoRaToGateIdPkt(xLoRaNode1Config.ucLoRaNode1Identifier); vLoRaToGateSenIdPkt(xLoRaSensorID.ucIdDht11); /* 检测接收队列是否成功 */ if (xQueueTempRetval == pdTRUE && xQueueHumiRetval == pdTRUE) { /* code */ vUsart3SendArray(&ucRecTempBuffer[1], 1); vUsart3SendArray(&ucRecHumiBuffer[1], 1); } // uint32_t value = (ucQueueRecHumiBfData[1] << 24) | (ucQueueRecTempBfData[1] << 16) | // (xLoRaSensorID.ucIdDht11 << 8) | (xLoRaNode1Config.ucLoRaNode1Identifier); vTaskDelay(1500); } } void vTasksList(void) { /* 进入临界区 */ taskENTER_CRITICAL(); /* 创建任务,参数分别为任务函数名称、任务名字、栈大小、返回参数值、优先级、任务句柄。 */ xTaskCreate( (TaskFunction_t ) vStateLedTask, (char * ) "StateLedTask", (configSTACK_DEPTH_TYPE) 512, (void * ) NULL, (UBaseType_t ) 2, (TaskHandle_t * ) &xStateLedTaskHdlr); xTaskCreate( (TaskFunction_t ) vDht11Task, (char * ) "DHT11Task", (configSTACK_DEPTH_TYPE) 1024, (void * ) NULL, (UBaseType_t ) 2, (TaskHandle_t * ) &xDht11TaskHdlr); xTaskCreate( (TaskFunction_t ) vLoRaToGatePktTask, (char * ) "LoRaToGatePktTask", (configSTACK_DEPTH_TYPE) 1024, (void * ) NULL, (UBaseType_t ) 2, (TaskHandle_t * ) &xLoRaToGateTskHdlr); /* 退出临界区 */ taskEXIT_CRITICAL(); } void vMainQueuesList(void) { /* 创建队列有两个参数,第一个是队列的长度,也就是这个队列能存放多少个数据; * 第二个参数就是每个数据的大小,单位为字节,在stm32中uint8_t指针的长度一般是4字节。 * 原函数的返回值就是队列句柄的结构体,所以需要在上面定义一个变量接收队列句柄。 */ xTempQueueHdlr = xQueueCreate( (UBaseType_t) 5, (UBaseType_t) sizeof(uint8_t *)); xHumiQueueHdlr = xQueueCreate( (UBaseType_t) 5, (UBaseType_t) sizeof(uint8_t *)); if (xTempQueueHdlr == NULL || xHumiQueueHdlr == NULL) { /* code */ vUsart3Printf("Queue Init Failed.\r\n"); } } int main(void) { vFanRelayInit(); vDelayInit(); vPc13LedInit(); vUsart3Init(115200); vMainQueuesList(); vTasksList(); vTaskStartScheduler(); while(1) { } }