这次来学习一下PWM的用法,从手册中可以看到BL616/BL618有一个PWM生成器支持4组通道
下面用RGB灯珠通过PWM实现红绿蓝的呼吸效果,在手册上找到IO对应的IO通道
代码实现
- #include "bflb_gpio.h"
- #include "bflb_mtimer.h"
- #include "bflb_pwm_v2.h"
- #include "bflb_clock.h"
- #include "board.h"
- #include "bl616_glb.h"
- struct bflb_device_s *gpio;
- struct bflb_device_s *pwm;
- uint8_t rgb_pwmchs[3] = {0};
- uint8_t rgb_index = 0;
- uint16_t rgb_pwm = 0;
- int main(void)
- {
- board_init();
- gpio = bflb_device_get_by_name("gpio");
- pwm = bflb_device_get_by_name("pwm_v2_0");
- bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1); //R CH0P CH2P
- bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1); //G CH2P CH3P
- bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1); //B CH3P CH3N
- struct bflb_pwm_v2_config_s cfg = {
- .clk_source = BFLB_SYSTEM_XCLK,
- .clk_div = 40,
- .period = 1000,
- };
- bflb_pwm_v2_init(pwm, &cfg);
- bflb_pwm_v2_channel_positive_start(pwm, PWM_CH0);
- bflb_pwm_v2_channel_positive_start(pwm, PWM_CH2);
- bflb_pwm_v2_channel_positive_start(pwm, PWM_CH3);
- bflb_pwm_v2_start(pwm);
- rgb_pwmchs[0] = PWM_CH0;
- rgb_pwmchs[1] = PWM_CH2;
- rgb_pwmchs[2] = PWM_CH3;
- while (1) {
- if(rgb_pwm > 1999)
- {
- rgb_index += 1;
- rgb_pwm = 0;
- if(rgb_index > 2)
- rgb_index = 0;
- }
- rgb_pwm += 1;
- if(rgb_pwm>1000)
- {
- bflb_pwm_v2_channel_set_threshold(pwm, rgb_pwmchs[rgb_index], 0, 2000 - rgb_pwm);
- }
- else
- {
- bflb_pwm_v2_channel_set_threshold(pwm, rgb_pwmchs[rgb_index], 0, rgb_pwm);
- }
- bflb_mtimer_delay_ms(1);
- }
- }
复制代码 代码解析:
bflb_device_get_by_name("pwm_v2_0") BL616/BL618只支持PWM_V2,外设支持情况可以看这张图
clk_source = BFLB_SYSTEM_XCLK 设置PWM的时钟源,可以选择bclk、 xclk、 f32k
clk_div = 40 时钟分频,最大65535,0和1都是不分频
period = 1000 PWM 周期 = PWM 源时钟 / pwm_clk_div / pwm_period
bflb_pwm_v2_init(pwm, &cfg) 以指定的参数初始化PWM
bflb_pwm_v2_channel_positive_start 开启正向通道(CHxP)输出,与之相对的是bflb_pwm_v2_channel_negative_start开启负向通道(CHxN)
bflb_pwm_v2_start 开启PWM
bflb_pwm_v2_channel_set_threshold 设置占空比,默认情况下当计数值在第3个参数和第4个参数间时正向通道输出高电平,反之输出低电平
运行效果
上面的示例只用到了正向输出通道,每一路通道还有互补输出,例如G和B就是通道3的互补输出,R和C是通道2的互补输出,为了拍摄看得明显些这里选择R和C,要使用负向通道的话需要用GLB_Set_PWM1_IO_Sel改变PWM的外设选择,代码示例
- #include "bflb_gpio.h"
- #include "bflb_mtimer.h"
- #include "bflb_pwm_v2.h"
- #include "bflb_clock.h"
- #include "board.h"
- #include "bl616_glb.h"
- struct bflb_device_s *gpio;
- struct bflb_device_s *pwm;
- uint16_t rgb_pwm = 0;
- int main(void)
- {
- board_init();
- GLB_Set_PWM1_IO_Sel(GLB_PWM1_IO_DIFF_END);
- gpio = bflb_device_get_by_name("gpio");
- pwm = bflb_device_get_by_name("pwm_v2_0");
- bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1); //R CH0P CH2P
- bflb_gpio_init(gpio, GPIO_PIN_29, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1); //R CH1P CH2N
- struct bflb_pwm_v2_config_s cfg = {
- .clk_source = BFLB_SYSTEM_XCLK,
- .clk_div = 40,
- .period = 1000,
- };
- bflb_pwm_v2_init(pwm, &cfg);
- bflb_pwm_v2_channel_positive_start(pwm, PWM_CH2);
- bflb_pwm_v2_channel_negative_start(pwm, PWM_CH2);
- bflb_pwm_v2_start(pwm);
- while (1) {
- if(rgb_pwm > 1999)
- {
- rgb_pwm = 0;
- }
- rgb_pwm += 1;
- if(rgb_pwm>1000)
- {
- bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, 2000 - rgb_pwm);
- }
- else
- {
- bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH2, 0, rgb_pwm);
- }
- bflb_mtimer_delay_ms(1);
- }
- }
复制代码 运行效果,只控制1个通道的占空比就能让2个LED交替呼吸
|
|