发帖
0 0 0

FreeRTOS学习-01-PWM

干簧管
论坛元老

22

主题

1265

回帖

1万

积分

论坛元老

积分
10627
Ai-M61系列 95 0 2026-5-3 17:20:49
[i=s] 本帖最后由 干簧管 于 2026-5-3 17:21 编辑 [/i]

复制之前的00-led工程目录,重命名为01-pwm,需要修改下述FW bin名称否则烧录有问题

AiPi-Open-Kits\FreeRTOS_study\01-pwm\flash_prog_cfg.ini

image.png

代码参考:https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=279&highlight=pwm

硬件LED pin 上 Ai-M61-32S 和 AiPi_Eyes_DU 一致,泽哥使用裸机程序,我这里改为FreeRTOS的方式


/**
 * @file main.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2023-08-22
 *
 * @copyright Copyright (c) 2023
 *
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include "board.h"
#include "log.h"
#include "bflb_pwm_v2.h"
#include "bflb_clock.h"
#include "bflb_gpio.h"
#include <semphr.h>

struct bflb_device_s *pwm;
struct bflb_device_s *gpio;

static TaskHandle_t BlueLedTask_handle;
static TaskHandle_t RedLedTask_handle;
static TaskHandle_t GreenLedTask_handle;

enum RED_CLOOR{
    RED,
    GREEN,
    BLUE
};

enum RED_CLOOR cloor = RED;

static SemaphoreHandle_t xSemTask1ToTask2 = NULL;
static SemaphoreHandle_t xSemTask2ToTask3 = NULL;
static SemaphoreHandle_t xSemTask3ToTask1 = NULL;

#define PWM_PERIOD_MAX 255

static void BlueLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {

        if (xSemaphoreTake(xSemTask2ToTask3, portMAX_DELAY) == pdTRUE)
        {
            //蓝灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH3);//使能绿灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH3);//失能绿灯通道

            /* 释放信号量,通知 Task1 可以再次运行,形成循环 */
            xSemaphoreGive(xSemTask3ToTask1);
        }

    }   
    vTaskDelete(NULL);
}

static void GreenLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {
        if (xSemaphoreTake(xSemTask1ToTask2, portMAX_DELAY) == pdTRUE)
        {
            //绿灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH2);//使能绿灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH2);//失能绿灯通道

            /* 释放信号量,通知 Task3 可以运行 */
            xSemaphoreGive(xSemTask2ToTask3);
        }
    }   
    vTaskDelete(NULL);
}

static void RedLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {
        if (xSemaphoreTake(xSemTask3ToTask1, portMAX_DELAY) == pdTRUE)
        {
            //红灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0);//使能红灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH0);//失能红灯通道


            /* 释放信号量,通知 Task2 可以运行 */
            xSemaphoreGive(xSemTask1ToTask2);
        }

    }   
    vTaskDelete(NULL);
}

int main(void)
{
    board_init();

    /* 创建二进制信号量,初始状态为不可用 (0) */
    xSemTask1ToTask2 = xSemaphoreCreateBinary();
    xSemTask2ToTask3 = xSemaphoreCreateBinary();
    xSemTask3ToTask1 = xSemaphoreCreateBinary();

    if (xSemTask1ToTask2 == NULL || xSemTask2ToTask3 == NULL || xSemTask3ToTask1 == NULL)
    {
        /* 错误处理:内存不足 */
        for (;;);
    }

    xSemaphoreGive(xSemTask3ToTask1);

    gpio = bflb_device_get_by_name("gpio");

    /*初始化RGB灯,IO15、12、14,对应蓝灯、红灯、绿灯*/
    bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

    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 = PWM_PERIOD_MAX ,
    };
  
    /*初始化PWM输出*/
    bflb_pwm_v2_init(pwm, &cfg);
    bflb_pwm_v2_start(pwm);

    configASSERT((configMAX_PRIORITIES > 4));
    LOG_I("[OS] Starting blue led task...\r\n");
    xTaskCreate(BlueLedTask, (char *)"BlueLedTask", 512, NULL, configMAX_PRIORITIES - 3, &BlueLedTask_handle);
    LOG_I("[OS] Starting red led task...\r\n");
    xTaskCreate(RedLedTask, (char *)"RedLedTask", 512, NULL, configMAX_PRIORITIES - 2 ,&RedLedTask_handle);
    LOG_I("[OS] Starting green led task...\r\n");
    xTaskCreate(GreenLedTask, (char *)"GreenLedTask", 512, NULL, configMAX_PRIORITIES - 3, &GreenLedTask_handle);
    vTaskStartScheduler();
    while (1)
    {
        vTaskDelay(5000);
    }
}

使用变量判断也可实现信号量类似效果

/**
 * @file main.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2023-08-22
 *
 * @copyright Copyright (c) 2023
 *
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include "board.h"
#include "log.h"
#include "bflb_pwm_v2.h"
#include "bflb_clock.h"
#include "bflb_gpio.h"


struct bflb_device_s *pwm;
struct bflb_device_s *gpio;

static TaskHandle_t BlueLedTask_handle;
static TaskHandle_t RedLedTask_handle;
static TaskHandle_t GreenLedTask_handle;

enum RED_CLOOR{
    RED,
    GREEN,
    BLUE
};

enum RED_CLOOR cloor = RED;

#define PWM_PERIOD_MAX 255

static void BlueLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {
        if(cloor == BLUE)
        {
        //蓝灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH3);//使能绿灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH3);//失能绿灯通道

            cloor = RED;
        }

        vTaskDelay(500);

    }   
    vTaskDelete(NULL);
}

static void GreenLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {
        if(cloor == GREEN)
        {
            //绿灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH2);//使能绿灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH2);//失能绿灯通道
            cloor = BLUE;

        }

        vTaskDelay(500);

    }   
    vTaskDelete(NULL);
}

static void RedLedTask(void *pvParameters)
{
    int i;
  
    while (1) 
    {
        if(cloor == RED)
        {
            //红灯呼吸亮灭  
            bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0);//使能红灯通道
            for(i=0;i<PWM_PERIOD_MAX ;i++)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 0, i);

                vTaskDelay(5);
            } 
            for(i=PWM_PERIOD_MAX ;i>0;i--)
            {
                bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH0, 0, i); 
  
                vTaskDelay(5);
            }
            bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH0);//失能红灯通道
            cloor = GREEN;
        }
        vTaskDelay(500);

    }   
    vTaskDelete(NULL);
}


int main(void)
{
    board_init();

    gpio = bflb_device_get_by_name("gpio");

    /*初始化RGB灯,IO15、12、14,对应蓝灯、红灯、绿灯*/
    bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

    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 = PWM_PERIOD_MAX ,
    };
  
    /*初始化PWM输出*/
    bflb_pwm_v2_init(pwm, &cfg);
    bflb_pwm_v2_start(pwm);

    configASSERT((configMAX_PRIORITIES > 4));
    LOG_I("[OS] Starting blue led task...\r\n");
    xTaskCreate(BlueLedTask, (char *)"BlueLedTask", 512, NULL, configMAX_PRIORITIES - 3, &BlueLedTask_handle);
    LOG_I("[OS] Starting red led task...\r\n");
    xTaskCreate(RedLedTask, (char *)"RedLedTask", 512, NULL, configMAX_PRIORITIES - 2 ,&RedLedTask_handle);
    LOG_I("[OS] Starting green led task...\r\n");
    xTaskCreate(GreenLedTask, (char *)"GreenLedTask", 512, NULL, configMAX_PRIORITIES - 3, &GreenLedTask_handle);
    vTaskStartScheduler();
    while (1)
    {
        vTaskDelay(5000);
    }
}
──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 30957 个
  • 话题数: 44900 篇