642|2

76

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

在Beetle ESP32 C6迷你开发板实现消息队列通讯 [复制链接]

本帖最后由 aramy 于 2024-7-31 09:42 编辑

 

Beetle ESP32 C6迷你开发板搭载了160MHz的高性能RISC-V 32位处理器。如果使用单任务处理问题,大多数时间都会浪费在各类传感器和外设的等待上,为了更好地利用处理器,引入了操作系统,可以让用户使用多任务处理问题,提升了处理器的利用率。ESP32 C6中使用了FreeRTOS操作系统。用户可以在FreeRTOS操作系统创建多个任务去处理不同的问题。这里实现了在FreeRTOS操作系统上创建两个任务,两个任务之间使用消息队列进行通讯的功能。

 

需求描述:通过Beetle ESP32 C6开发板上的按键,控制板载的LED灯的亮灭。需求很简单,但是是使用两个任务来实现的。

任务1:LED控制任务,负责控制LED灯的亮灭。任务阻塞在读取消息队列上,当读取到消息时,通过消息内容进行判断。当消息内容为0时,关闭LED灯,为1时,点亮LED灯。

任务2:按键读取任务。负责读取按键值。设置一个状态位,当按键按下时,就取反状态位的值,然后将状态位封装进消息队列,丢到消息队列中发送出去。

具体实现:实习使用了esp-idf编程。这里我使用的esp-idf版本是5.1.2。使用vscode作为编辑器。使用官方例程blink作为项目基础进行修改。

第一步:先修改芯片类型,将芯片类型修改为esp32c6,然后修改串口号,选中Beetle ESP32 C6迷你开发板插入电脑后分配的串口号。参考开发板的电路图定义好LED的管脚和按键的管脚。

#define LED1_IO 15
#define BUTTON_PIN 9

第二步:定义多个任务。

void buttontask(void *arg)
{
    gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BUTTON_PIN, GPIO_PULLUP_ONLY);
    char s_led_state[1];
    while (1)
    {
        if (gpio_get_level(BUTTON_PIN) == 0)
        {
            xQueueSend(queue1, &s_led_state, portMAX_DELAY);
            s_led_state[0] = !s_led_state[0];
            ESP_LOGI(TAG, "Button Pressed!\n");
        }
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
    vTaskDelete(NULL); // 在本函数中删除,不需要传递句柄
}

void ledBlinkTask(void *pvParam)
{
    char led_state[1];
    gpio_set_direction(LED1_IO, GPIO_MODE_OUTPUT);
    while (1)
    {
        if (xQueueReceive(queue1, &led_state, portMAX_DELAY))
        {
            gpio_set_level(LED1_IO, led_state[0]);
            ESP_LOGI(TAG, "Get mesage %d!",led_state[0]);
        }
    }
    vTaskDelete(NULL); // 在本函数中删除,不需要传递句柄
}

这里定义了两个任务。一个是用来接收按键的任务,一个是用来控制LED的任务。可以看出任务首先对GPIO进行初始化,设置GPIO方向为为输入或输出。然后就是一个死循环,任务将在这个循环内一直执行,直至退出或被杀死。在按键任务中定义了一个s_led_state的变量,当检测到按键有按下后,就将这个变量发送到消息队列中。然后将s_led_state取反。在led控制任务中,任务会阻塞在接收消息队列位置,当消息队列中有消息了,就取出消息,并修改LED灯的状态。

第三步:启动任务。

void app_main(void)
{
    queue1 = xQueueCreate(5, sizeof(char));
    xTaskCreate(ledBlinkTask, "ledBlinkTask", 2048, NULL, 1, NULL); // 传出任务句柄
    xTaskCreate(buttontask, "buttontask", 2048, NULL, 1, NULL);
    while (1)
    {
        vTaskDelay(10000 / portTICK_PERIOD_MS);
    }
}

在main方法中首先是定义了一个消息队列,这里消息队列的最大容量为5,意味着最多可以容纳5个消息。当消息队列中消息数量等于5时,就无法在容纳新的消息了。消息队列使用了一个全局变量名称,这样在所有的任务中都能直接通过变量名访问到这个消息队列了。然后是启动子任务。主函数自身也是一个任务,但是这个任务没有做任何功能。

第四步:效果展示.。通过vscode编译,然后烧录。按板子右下角的按键即可控制LED灯的亮灭。

 

 

VID_20240727_104906

 

blink.zip (68.74 KB, 下载次数: 3)
此帖出自RF/无线论坛

最新回复

消息队列是RTOS比较常用的一个功能。   详情 回复 发表于 2024-7-31 18:13
点赞 关注
 

回复
举报

1

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
点赞
此帖出自RF/无线论坛
 
 

回复

7116

帖子

2

TA的资源

版主

板凳
 

消息队列是RTOS比较常用的一个功能。

此帖出自RF/无线论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表
  缈昏瘧锛