1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、消息队列是什么?
队列是任务间通信的主要形式。它们可用于在任务之间以及中断和任务之间发送消息。在大多数情况下,它们用作线程安全的 FIFO(先进先出)缓冲区,将新数据发送到队列的后面,尽管数据也可以发送到前面。
二、消息队列的作用
使用丰富的API23个函数可以实现 FreeRTOS 的消息队列 重要函数理解: 函数 xQueueCreate 函数返回类型为指针QueueHandle_t所以需要提前定义一个指针QueueHandle_t queuex;用于函数的返回,即 QueueHandle_t xQueueCreate ( UBaseType_t uxQueueLength, /* 消息个数 */ UBaseType_t uxItemSize ); /* 每个消息大小,单位字节 */ 函数 xQueueSend BaseType_t xQueueSend( QueueHandle_t xQueue, /* 消息队列句柄 */ const void * pvItemToQueue, /* 要传递数据地址 */ TickType_t xTicksToWait /* 等待消息队列有空间的最大等待时间 */ ); 重点:
函数 xQueueReceive BaseType_t xQueueReceive( QueueHandle_t xQueue, /* 消息队列句柄 */ void *pvBuffer, /* 接收消息队列数据的缓冲地址 */ TickType_t xTicksToWait /* 等待消息队列有数据的最大等待时间 */ ); */ ); 函数 xQueueSendFromISR BaseType_t xQueueSendFromISR ( QueueHandle_t xQueue, /* 消息队列句柄 */ const void *pvItemToQueue, /* 要传递数据地址 */ BaseType_t *pxHigherPriorityTaskWoken /* 高优先级任务是否被唤醒的状态保存 */ ); 中断函数里面调用发送队列的信息 函数 uxQueueMessagesWaiting UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue); 函数 uxQueueSpacesAvailable UBaseType_t uxQueueSpacesAvailable(QueueHandle_t xQueue); 函数 xQueuePeek BaseType_t xQueuePeek( QueueHandle_t xQueue, 无效 *pvBuffer, TickType_t xTicksToWait ); 函数 xQueueOverwrite BaseType_t xQueueOverwrite( QueueHandle_t xQueue, const void * pvItemToQueue ); 接收到消息以后不会自动删除当前已经接收的消息不会接收下一个队列里面的消息,一直卡在了队头 四、基于esp32-idf实验 这个实验不拘泥于任何单片机,可以在任何单片机上运行 #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" TaskHandle_t myTask1Handle = NULL; TaskHandle_t myTask2Handle = NULL; //队列句柄 QueueHandle_t queue1; void task1(void *arg){ char txbuff[50]; queue1= xQueueCreate(5, sizeof(txbuff)); //创建队列返回已创建队列的句柄 if( queue1 == 0 ) { printf("failed to create queue1= %p n",queue1); // Failed to create the queue. } sprintf(txbuff,"hello world! 1");//c语言库赋值 xQueueSend(queue1, (void*)txbuff,(TickType_t)0 ); sprintf(txbuff,"hello world! 2"); xQueueSend(queue1, (void*)txbuff,(TickType_t)0 ); sprintf(txbuff,"hello world! 3"); xQueueSendToFront(queue1, (void*)txbuff,(TickType_t)0 ); while(1){ printf("data waiting to be read : %d available spaces: %d n", uxQueueMessagesWaiting(queue1),//队列中待读取的消息 uxQueueSpacesAvailable(queue1));//队列剩余空间 vTaskDelay(pdMS_TO_TICKS(1000)); } } void task2(void *arg) { char rxbuff[50]; while(1) { //if(xQueuePeek(queue1, &(rxbuff) , (TickType_t)5 )) if(xQueueReceive(queue1, &(rxbuff) , (TickType_t)5 )){ printf("got a data from queue! === %s n",rxbuff); } vTaskDelay(pdMS_TO_TICKS(1000)); } } void app_main(){ xTaskCreate(task1, "task1", 4096, NULL, 10, &myTask1Handle); xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &myTask2Handle,1); } 进一步实验 按键中断通信里面发送消息给队列与增加发送检测 【if(xQueueSend(queue1, (void*)txbuff,(TickType_t)0 ) !=1】为什么这么写呢?根据官方解释返回值 #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #define ESP_INTR_FLAG_DEFAULT 0 #define CONFIG_LED_PIN 32 #define CONFIG_BUTTON_PIN 0 TaskHandle_t myTask1Handle = NULL; TaskHandle_t myTask2Handle = NULL; QueueHandle_t queue1; TaskHandle_t ISR = NULL; // interrupt service routine, called when the button is pressed void IRAM_ATTR button_isr_handler(void* arg) { //响应中断服务程序的函数: //发送数据需要用xQueueSendFromISR函数 //不可以实验xQueuesend char txbuff[50]; sprintf(txbuff,"hello from ISR!"); xQueueSendFromISR(queue1, &txbuff, NULL); } void task1(void *arg){ char txbuff[50]; queue1= xQueueCreate(1, sizeof(txbuff)); if( queue1 == 0 ) { printf("failed to create queue1= %p n",queue1); // Failed to create the queue. } sprintf(txbuff,"hello world! 1"); if(xQueueSend(queue1, (void*)txbuff,(TickType_t)0 ) !=1){ printf("could not sended this message = %s n",txbuff); } sprintf(txbuff,"hello world! 2"); if(xQueueSend(queue1, (void*)txbuff , (TickType_t)0 ) !=1) { printf("could not sended this message = %s n",txbuff); } sprintf(txbuff,"hello world! 3"); if(xQueueOverwrite(queue1, (void*)txbuff ) !=1) { printf("could not sended this message = %s n",txbuff); } while(1){ vTaskDelay(pdMS_TO_TICKS(10)); printf("data waiting to be read : %d available spaces: %d n",uxQueueMessagesWaiting(queue1),uxQueueSpacesAvailable(queue1)); vTaskDelay(pdMS_TO_TICKS(1000)); }} void task2(void *arg){char rxbuff[50];while(1) { if(xQueueReceive(queue1, &(rxbuff) , (TickType_t)5 )) { printf("got a data from queue! === %s n",rxbuff); } vTaskDelay(pdMS_TO_TICKS(1000)); } } void app_main(){ gpio_pad_select_gpio(CONFIG_BUTTON_PIN); gpio_pad_select_gpio(CONFIG_LED_PIN); gpio_set_direction(CONFIG_BUTTON_PIN, GPIO_MODE_INPUT); gpio_set_direction(CONFIG_LED_PIN, GPIO_MODE_OUTPUT); // enable interrupt on falling (1->0) edge for button pin gpio_set_intr_type(CONFIG_BUTTON_PIN, GPIO_INTR_NEGEDGE); //Install the driver’s GPIO ISR handler service, which allows per-pin GPIO interrupt handlers. // install ISR service with default configuration gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);// attach the interrupt service routine gpio_isr_handler_add(CONFIG_BUTTON_PIN, button_isr_handler, NULL); xTaskCreate(task1, "task1", 4096, NULL, 10, &myTask1Handle); xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &myTask2Handle,1); } 五、总结
|
|
|
|
只有小组成员才能发言,加入小组>>
3323 浏览 9 评论
3000 浏览 16 评论
3498 浏览 1 评论
9073 浏览 16 评论
4093 浏览 18 评论
1194浏览 3评论
614浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
603浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2343浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1902浏览 2评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-30 19:00 , Processed in 1.010622 second(s), Total 50, Slave 41 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号