本帖最后由 aHaoii 于 2023-11-20 21:40 编辑
继续点灯。。。。。。。
没什么可玩的,其它元件都在家里放着,在学校只能先凑合点灯玩了。
这次的想法是RGB灯珠的红色灯做一个呼吸灯,板载两颗LED灯进行交替闪烁同步进行。
呼吸灯的逻辑是在循环里面每10ms改变一次占空比,LED的闪烁是250ms翻转一次电平状态。
这个逻辑比较简单,其实可以写在一个循环里面,用几个变量进行控制即可。
但是,有现成的FreeRTOS系统给我们用,肯定直接上操作系统啦!!!!
开始。
【1】找例程
官方examples里面提供一份FreeRTOS的示例,里面的大致内容是设置了两个信号量,一个互斥锁,
两个任务,实现了一个生产者消费者模型。我们在此基础上进行改动。
复制该文件夹一份,起名freertos_my,如图:
【2】初始化代码
这部分没什么好说的,前面两个帖子已经做过。包括PWM初始化和LED初始化:
- static void my_pwm_init(void)
- {
- struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
- bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
- ledr_pwm = bflb_device_get_by_name("pwm_v2_0");
- /* period = .XCLK / .clk_div / .period = 40MHz / 40 / 1000 = 1KHz */
- struct bflb_pwm_v2_config_s cfg = {
- .clk_source = BFLB_SYSTEM_XCLK,
- .clk_div = 40,
- .period = 1000,
- };
- bflb_pwm_v2_init(ledr_pwm, &cfg);
- bflb_pwm_v2_channel_set_threshold(ledr_pwm, PWM_CH0, 1, 900); /* duty = (500-100)/1000 = 40% */
- bflb_pwm_v2_channel_positive_start(ledr_pwm, PWM_CH0);
- bflb_pwm_v2_start(ledr_pwm);
- }
- static void my_led_init(void)
- {
- struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
- bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
- bflb_gpio_init(gpio, GPIO_PIN_29, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
- }
复制代码 【3】任务代码
设置两个任务,一个任务调节PWM占空比,一个任务控制LED电平翻转,两个任务同步执行。
其中,VTaskDelay将任务阻塞,单位为毫秒。
- static void pwm_task(void *pvParameters)
- {
- uint32_t val = 20;
- bool flag = true;
- while (1) {
- if(flag){
- val+=10;
- }
- else{
- val-=10;
- }
- if(val>=970 || val <= 20){
- flag = !flag;
- }
- bflb_pwm_v2_channel_set_threshold(ledr_pwm, PWM_CH0, 1, val);
- vTaskDelay(10);
- }
- vTaskDelete(NULL);
- }
- static void led_task(void *pvParameters)
- {
- struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
- while (1) {
- bflb_gpio_set(gpio, GPIO_PIN_27);
- bflb_gpio_reset(gpio, GPIO_PIN_29);
- vTaskDelay(250);
- bflb_gpio_reset(gpio, GPIO_PIN_27);
- bflb_gpio_set(gpio, GPIO_PIN_29);
- vTaskDelay(250);
- }
- vTaskDelete(NULL);
- }
复制代码 【4】编写主函数
主函数比较简单,初始化以后创建任务,开启调度器即可。
其中xTaskCreate函数为创建任务,参数依次为该任务函数名、提示字符串、栈大小、任务函数参数、优先级、任务句柄。
- int main(void)
- {
- board_init();
- my_led_init();
- my_pwm_init();
- configASSERT((configMAX_PRIORITIES > 4));
- xTaskCreate(pwm_task, (char *)"pwm_task", 128, NULL, configMAX_PRIORITIES - 2, &pwm_task_handle);
- xTaskCreate(led_task, (char *)"led_task", 128, NULL, configMAX_PRIORITIES - 3, &led_task_handle);
- vTaskStartScheduler();
- while (1) {
- }
- }
复制代码 【5】注意加头文件和全局变量
这是全局变量,前两个为任务句柄,用来控制任务的挂起恢复删除等。第三个为pwm的设备指针,用来修改pwm参数。如下:
- static TaskHandle_t pwm_task_handle;
- static TaskHandle_t led_task_handle;
- struct bflb_device_s* ledr_pwm;
复制代码 以下头文件包含了一些pwm初始化和gpio初始化所用到的一些函数和宏定义:
- #include "bflb_gpio.h"
- #include "bflb_pwm_v2.h"
- #include "bflb_clock.h"
复制代码 ————————————————————
2023.11.20
|
|