[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

代码参考: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);
}
}