可以和中断 人物间发送和接受不定长的消息,在消息队列中会使任务进入阻塞。 可以在调度器开始前,创建消息队列。
#include "FreeRTOS.h"
#include "queue.h"
//创建成功返回消息队列句柄,失败返回NULL
QueueHandle_t xQueueCreate(
UBaseType_t uxQueueLength, //消息队列最大长度
UbaseType_t uxItemSize //队列中每个消息的大小
);
消息队列发送xQueueSend , xQueueSendToFront / xQueueSendToBack
BaseType_t xQueueSend(
QueueHandle_t xQueue, //消息队列句柄
const void * pvItemToQueue, //要发送消息的地址
TickType_t xTicksToWait //阻塞等待时间
);
在中断中往队列传入消息
xQueueSendFromISR(
QueueHandle_t xQueue, //消息队列句柄
const void * pvItemToQueue, //要发送消息的地址
NULL
);
读取消息队列消息
成功pdPASS 失败errQUEUE_EMPTY
BaseType_t xQueueReceive(
QueueHandle_t xQueue, //消息队列句柄
void * pvBuffer, //要发送消息的地址
TickType_t xTicksToWait //阻塞等待时间
);
信号量有很多种,用于同步和互斥。二值信号量底层是消息队列,只不过只有空和满两种状态,底层大多是宏实现。
没有参数 返回值是 SemaphoreHandle_t
类型(void *)
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore )
在中断中必须使用带FromISR的函数!!!
BaseType_t xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime)
在中断中必须使用带FromISR的函数!!!
BaseType_t xSemaphoreTakeFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
#include
#include
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#define LED_RED_PIN 4
#define LED_BLUE_PIN 16
#define BUTTON_PIN 5
#define BUF_SIZE (1024) //小于1024会报奇怪的错误
static xQueueHandle led_evt_queue = NULL;
static SemaphoreHandle_t intr_sem = NULL;
/**
* - 功能:从UART读取字符串,放入消息队列,LED任务读取队列,设置LED状态。
- 板载一个蓝色LED,是gpio16,外接一个红色LED在IO4.
- IO5有一个外接按键(中断方式),按键短按打开蓝色LED,长按(1s)关闭蓝色LEDBrief:
*/
static void button_isr_handler(void *arg)
{
xSemaphoreGiveFromISR(intr_sem,NULL); //给
}
static void Button_task()
{
TickType_t last_tick = xTaskGetTickCount();
TickType_t this_tick= xTaskGetTickCount();
const char red_on[8] = "RED_ON";
const char red_off[8] = "RED_OFF";
while (1)
{
last_tick = xTaskGetTickCount();
xSemaphoreTake(intr_sem,portMAX_DELAY); //拿
if(gpio_get_level(BUTTON_PIN) == 0)
{
vTaskDelay(2);
if(gpio_get_level(BUTTON_PIN) == 0)
{
continue;
}
}
this_tick = xTaskGetTickCount();
if(this_tick - last_tick >=0 && this_tick - last_tick < 50 )
{
//短按
for(int i = 0;i< 8;++i)
xQueueSend(led_evt_queue,red_on+i,1);
}
else if(this_tick - last_tick >= 50 && this_tick - last_tick < 200 )
{
//长按
for(int i = 0;i< 8;++i)
xQueueSend(led_evt_queue,red_off+i,1);
}
}
}
static void LED_task()
{
gpio_config_t io_conf;
memset(&io_conf,0,sizeof(gpio_config_t));
io_conf.mode = GPIO_MODE_OUTPUT;//设置为输出
io_conf.pin_bit_mask = ((1ULL<<LED_RED_PIN)|(1ULL<<LED_BLUE_PIN)) ;
gpio_config(&io_conf);
char *data = (char *) malloc(BUF_SIZE);
while(1)
{
int i = 1;
memset(data,0,BUF_SIZE);
//阻塞等待接收队列的第一个元素
xQueueReceive(led_evt_queue, data, portMAX_DELAY);
//循环接收第二个开始的元素,直到10个tick没收到数据
while(xQueueReceive(led_evt_queue, data+i, 10))
i++;
//解析
if(strstr(data,"RED_ON") != NULL)
{
gpio_set_level(LED_RED_PIN,0);//设置GPIO 点亮LED
}
else if(strstr(data,"RED_OFF") != NULL)
{
gpio_set_level(LED_RED_PIN,1);
}
else if(strstr(data,"BLUE_ON") != NULL)
{
gpio_set_level(LED_BLUE_PIN,0);
}
else if(strstr(data,"BLUE_OFF") != NULL)
{
gpio_set_level(LED_BLUE_PIN,1);
}
}
}
#if 1
static void UART_task()
{
//串口配置
uart_config_t uart_config = {
.baud_rate = 74880,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_0, &uart_config);
uart_driver_install(UART_NUM_0, BUF_SIZE * 2, 0, 0, NULL, 0);
// 分配临时空间
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
while (1) {
memset(data,0,BUF_SIZE);
// Read data from the UART
int len = uart_read_bytes(UART_NUM_0, data, BUF_SIZE, 20 / portTICK_RATE_MS);
// Write data back to the UART
for(int i = 0; i < len; ++i)
{
xQueueSend(led_evt_queue,data+i,portMAX_DELAY);
}
}
}
#endif
void app_main(void)
{
//1. 按键中断设置
gpio_config_t io_conf;
memset(&io_conf,0,sizeof(gpio_config_t));
io_conf.mode = GPIO_MODE_INPUT;//设置为输入
io_conf.pin_bit_mask = 1ULL<<BUTTON_PIN;
//io_conf.intr_type = GPIO_INTR_POSEDGE;
io_conf.intr_type = GPIO_INTR_ANYEDGE; //上升沿下降沿均触发
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
//2. 创建队列
led_evt_queue = xQueueCreate(BUF_SIZE, sizeof(uint8_t));
intr_sem = xSemaphoreCreateBinary();
//3. 启动任务
xTaskCreate(LED_task, "LED_task", 2048, NULL, 2, NULL);
xTaskCreate(UART_task, "UART_task", 2048, NULL, 3, NULL);
xTaskCreate(Button_task, "Button_task", 2048, NULL, 3, NULL);
//4. 连接IO中断服务函数
gpio_set_intr_type(BUTTON_PIN, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(BUTTON_PIN, button_isr_handler, NULL);
//5. 主任务空闲
while(1)
{
vTaskDelay(1000 / portTICK_RATE_MS);
}
}