【M61笔记】PWM

[复制链接]
查看515 | 回复10 | 2024-6-13 22:44:07 | 显示全部楼层 |阅读模式

M61 模组是 BL618 芯片,基于 LHAL 库**只支持 PWM_V2**,该 PWM 版本支持四个 PWM 通道。

PWM 频率: 一秒钟内,信号完整的从高电平到低电平的次数(完整的一个脉冲周期),单位是 Hz。1Hz 也就是一秒钟一个脉冲周期,周期是 1000ms。

PWM 周期: 周期=1/频率,也就是周期与频率互为倒数,单位一般是 ms,若频率为 5Hz,周期也就是 1/5=0.2S=200ms。

PWM 占空比: 一个脉冲周期内,高电平的时间占整个周期时间的比例。单位是 %,高电平时间是 50ms,周期是 100ms。占空比就是 50/100*100%=50%。

(****)以下没懂,多了解

PWM V2 版本输出有效极性。当正向通道阈值位于设置的低阈值和高阈值之间,为有效极性,如果设置有效极性为高,则输出高电平,反之输出低电平。反向通道相反,阈值位于设置的低阈值和高阈值之外,为有效极性,如果设置有效极性为高,则输出高电平,反之输出低电平。

// bflb_pwm_v2.h
/** @defgroup 极性定义 (PWM_POLARITY pwm polarity definition)
  * @{
  */
#define PWM_POLARITY_ACTIVE_LOW  0
#define PWM_POLARITY_ACTIVE_HIGH 1

PWM配置

bflb_pwm_v2_config_s PWM初始化配置结构体

pwm_v2 初始化配置结构体

PWM 最终产生的频率为 clk_source/clk_div/period

/**bflb_pwm_v2.h
 * @brief PWM配置结构
 *
 * @param clk_source PWM时钟源, use @ref BFLB_SYSTEM_CLOCK  bflb_clock.h
 * @param clk_div    PWM时钟分频器,应在1~65535
 * @param period     PWM周期数,应在2~65535
 */
struct bflb_pwm_v2_config_s {
    uint8_t clk_source;
    uint16_t clk_div;
    uint16_t period;
};

clk_source 时钟源选择范围 可选 2,3,4

/** bflb_pwm_v2.h
  * @defgroup BFLB_SYSTEM_CLOCK 系统时钟定义
  * @{
  */
#define BFLB_SYSTEM_ROOT_CLOCK 0
#define BFLB_SYSTEM_CPU_CLK    1
#define BFLB_SYSTEM_PBCLK      2
#define BFLB_SYSTEM_XCLK       3    // 40MHz
#define BFLB_SYSTEM_32K_CLK    4

bflb_pwm_v2_channel_config_s 通道初始化配置结构体

通道初始化配置结构体

/**bflb_pwm_v2.h
 * @brief PWM通道配置结构
 *
 * @param positive_polarity    正向输出极性PWM posotive channel polarity, use @ref PWM_POLARITY
 * @param negative_polarity    反向输出极性PWM negative channel polarity, use @ref PWM_POLARITY
 * @param positive_stop_state  正向输出空闲状态 PWM posotive channel state when stop, use @ref PWM_STATE
 * @param negative_stop_state  反向输出空闲状态 channel state when stop, use @ref PWM_STATE
 * @param positive_brake_state 正向输出刹车状态PWM posotive channel state when brake, use @ref PWM_STATE
 * @param negative_brake_state 反向输出刹车状态PWM negative channel state when brake, use @ref PWM_STATE
 * @param dead_time            死区时间PWM channel dead time
 */
struct bflb_pwm_v2_channel_config_s {
    uint8_t positive_polarity;
    uint8_t negative_polarity;
    uint8_t positive_stop_state;
    uint8_t negative_stop_state;
    uint8_t positive_brake_state;
    uint8_t negative_brake_state;
    uint8_t dead_time;
};

PWM函数

bflb_pwm_v2_init 初始化 pwm

初始化 pwm。使用之前需要选择 gpio 为 pwm 功能。

/**bflb_pwm_v2.h
 * @brief 初始化PWM
 *
 * @param [in] dev 设备句柄
 * @param [in] config 配置项 用于保存PWM配置的指针
 */
void bflb_pwm_v2_init(struct bflb_device_s *dev, const struct bflb_pwm_v2_config_s *config);

bflb_pwm_v2_deinit 复位 pwm

复位 pwm

/**bflb_pwm_v2.h
 * @brief 复位PWM
 *
 * @param [in] dev 设备句柄
 */
void bflb_pwm_v2_deinit(struct bflb_device_s *dev);

bflb_pwm_v2_start 启动 pwm 输出

启动 pwm 输出

/**bflb_pwm_v2.h
 * @brief 启动PWM输出
 *
 * @param [in] dev 设备句柄
 */
void bflb_pwm_v2_start(struct bflb_device_s *dev);

bflb_pwm_v2_stop 关闭 pwm 输出

关闭 pwm 输出

/**bflb_pwm_v2.h
 * @brief 关闭PWM输出
 *
 * @param [in] dev 设备句柄
 */
void bflb_pwm_v2_stop(struct bflb_device_s *dev);

bflb_pwm_v2_set_period 修改 pwm 周期值,从而更改 pwm 输出的频率

/**bflb_pwm_v2.h
 * @brief 设置 pwm 周期以更改 pwm 频率。频率(hz) = pwm 源时钟 /div/period。
          Set pwm period to change pwm frequence. Frequcence(hz) = pwm source clock /div/period.
 *
 * @param [in] dev 设备句柄
 * @param [in] period PWM周期
 */
void bflb_pwm_v2_set_period(struct bflb_device_s *dev, uint16_t period);

bflb_pwm_v2_get_frequency 获取频率

/**bflb_pwm_v2.h
 * @brief 获取PWM频率.
 *
 * @param [in] dev 设备句柄
 * @return 频率
 */
float bflb_pwm_v2_get_frequency(struct bflb_device_s *dev);

bflb_pwm_v2_channel_init PWM 通道初始化

/**bflb_pwm_v2.h
 * @brief 配置通道
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 * @param [in] config 通道配置
 */
void bflb_pwm_v2_channel_init(struct bflb_device_s *dev, uint8_t ch, struct bflb_pwm_v2_channel_config_s *config);

bflb_pwm_v2_channel_set_threshold 设置 PWM 占空比

设置 PWM 占空比。

PWM 占空比=(high_threhold - low_threhold)/period周期

/**bflb_pwm_v2.h
 * @brief 
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 * @param [in] low_threhold 低阈值
 * @param [in] high_threhold 高阈值,需要大于 low_threhold,并且小于等于周期
 */
void bflb_pwm_v2_channel_set_threshold(struct bflb_device_s *dev, uint8_t ch, uint16_t low_threhold, uint16_t high_threhold);

bflb_pwm_v2_channel_positive_start PWM 正向通道使能输出

正向通道使能输出

/**bflb_pwm_v2.h
 * @brief PWM 正向通道使能输出
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 */
void bflb_pwm_v2_channel_positive_start(struct bflb_device_s *dev, uint8_t ch);

bflb_pwm_v2_channel_negative_start PWM 反向通道使能输出

PWM 反向通道使能输出

/**bflb_pwm_v2.h
 * @brief PWM 反向通道使能输出
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 */
void bflb_pwm_v2_channel_negative_start(struct bflb_device_s *dev, uint8_t ch);

bflb_pwm_v2_channel_positive_stop PWM 正向通道停止输出

PWM 正向通道停止输出

/**bflb_pwm_v2.h
 * @brief PWM 正向通道停止输出
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 */
void bflb_pwm_v2_channel_positive_stop(struct bflb_device_s *dev, uint8_t ch);

bflb_pwm_v2_channel_negative_stop PWM 反向通道停止输出

/**bflb_pwm_v2.h
 * @brief PWM 反向通道停止输出
 *
 * @param [in] dev 设备句柄
 * @param [in] ch 通道号
 */
void bflb_pwm_v2_channel_negative_stop(struct bflb_device_s *dev, uint8_t ch);

bflb_pwm_v2_int_enable PWM 中断使能和关闭。

PWM 中断使能和关闭。

/**bflb_pwm_v2.h
 * @brief PWM 中断使能和关闭
 *
 * @param [in] dev 设备句柄
 * @param [in] int_en 中断类型
 * @param [in] enable true 表示启用,否则禁用
 */
void bflb_pwm_v2_int_enable(struct bflb_device_s *dev, uint32_t int_en, bool enable);

int_en可以填入以下值,多个中断可以使用 | 连接

/** bflb_pwm_v2.h
  * @defgroup PWM_INTEN PWM 中断使能定义
  * @{
  */
#define PWM_INTEN_CH0_L  (1 << 0)
#define PWM_INTEN_CH0_H  (1 << 1)
#define PWM_INTEN_CH1_L  (1 << 2)
#define PWM_INTEN_CH1_H  (1 << 3)
#define PWM_INTEN_CH2_L  (1 << 4)
#define PWM_INTEN_CH2_H  (1 << 5)
#define PWM_INTEN_CH3_L  (1 << 6)
#define PWM_INTEN_CH3_H  (1 << 7)
#define PWM_INTEN_PERIOD (1 << 8)
#define PWM_INTEN_BRAKE  (1 << 9)
#define PWM_INTEN_REPT   (1 << 10)

bflb_pwm_v2_get_intstatus 获取 PWM 中断标志

获取 PWM 中断标志

/**bflb_pwm_v2.h
 * @brief 获取 PWM 中断标志
 *
 * @param [in] dev 设备句柄
 * @return 返回中断标志, use @ref PWM_INTSTS
 */
uint32_t bflb_pwm_v2_get_intstatus(struct bflb_device_s *dev);

返回值如下:

/** bflb_pwm_v2.h
    @defgroup PWM_INTSTS PWM 中断状态定义
    pwm interrupt status definition
  * @{
  */
#define PWM_INTSTS_CH0_L  (1 << 0)
#define PWM_INTSTS_CH0_H  (1 << 1)
#define PWM_INTSTS_CH1_L  (1 << 2)
#define PWM_INTSTS_CH1_H  (1 << 3)
#define PWM_INTSTS_CH2_L  (1 << 4)
#define PWM_INTSTS_CH2_H  (1 << 5)
#define PWM_INTSTS_CH3_L  (1 << 6)
#define PWM_INTSTS_CH3_H  (1 << 7)
#define PWM_INTSTS_PERIOD (1 << 8)
#define PWM_INTSTS_BRAKE  (1 << 9)
#define PWM_INTSTS_REPT   (1 << 10)

bflb_pwm_v2_int_clear 清除 PWM 中断标志

/**bflb_pwm_v2.h
 * @brief 清除 PWM 中断标志
 *
 * @param [in] dev 设备句柄
 * @param [in] int_clear 清除值, use @ref PWM_INTCLR
 */
void bflb_pwm_v2_int_clear(struct bflb_device_s *dev, uint32_t int_clear);

int_clear 可以填入以下参数:

/** bflb_pwm_v2.h
  @defgroup PWM_INTCLR PWM 中断清除定义
  pwm interrupt clear definition
  * @{
  */
#define PWM_INTCLR_CH0_L  (1 << 0)
#define PWM_INTCLR_CH0_H  (1 << 1)
#define PWM_INTCLR_CH1_L  (1 << 2)
#define PWM_INTCLR_CH1_H  (1 << 3)
#define PWM_INTCLR_CH2_L  (1 << 4)
#define PWM_INTCLR_CH2_H  (1 << 5)
#define PWM_INTCLR_CH3_L  (1 << 6)
#define PWM_INTCLR_CH3_H  (1 << 7)
#define PWM_INTCLR_PERIOD (1 << 8)
#define PWM_INTCLR_BRAKE  (1 << 9)
#define PWM_INTCLR_REPT   (1 << 10)

bflb_pwm_v2_feature_control PWM 其他特性相关控制,一般不常用

其他特性相关控制,一般不常用。

/**bflb_pwm_v2.h
 * @brief Control pwm feature.
 *
 * @param [in] dev 设备句柄
 * @param [in] cmd feature command, use @ref PWM_CMD
 * @param [in] arg user data
 * @return A negated errno value on failure.
 */
int bflb_pwm_v2_feature_control(struct bflb_device_s *dev, int cmd, size_t arg);

cmd 可以填入以下参数:

/** bflb_pwm_v2.h
  @defgroup PWM_CMD PWM 特征控制 CMD 定义
  pwm feature control cmd definition
  * @{
  */
#define PWM_CMD_SET_TRIG_ADC_SRC       (0x01)
#define PWM_CMD_SET_EXT_BRAKE_POLARITY (0x02)
#define PWM_CMD_SET_EXT_BRAKE_ENABLE   (0x03)
#define PWM_CMD_SET_SW_BRAKE_ENABLE    (0x04)
#define PWM_CMD_SET_STOP_ON_REPT       (0x05)
#define PWM_CMD_SET_REPT_COUNT         (0x06)

示例

#include "bflb_mtimer.h"        //mtimer定时器头文件
#include "bflb_pwm_v2.h"        //pwm_v2头文件
#include "bflb_clock.h"         //系统时钟头文件
#include "board.h"              //开发板头文件,包装的库
#include "bflb_gpio.h"          //gpio头文件


struct bflb_device_s *pwm;      //创建LHAL外设库结构体,名称为pwm
struct bflb_device_s *gpio;     //创建LHAL外设库结构体,名称为gpio


int main(void)
{
    int i;                      //临时变量i,作为改变占空比的变量
    board_init();               //板子初始化
    gpio = bflb_device_get_by_name("gpio");
    //选择IO15作为pwm输出,
    // PWM 复用 上拉 滤波 输出能力1
    bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

    pwm = bflb_device_get_by_name("pwm_v2_0");  //给外设接口赋名pwm_v2_0

    /* period = .XCLK / .clk_div / .period = 40MHz / 40 / 1000 = 1KHz */

    struct bflb_pwm_v2_config_s cfg = {
        .clk_source = BFLB_SYSTEM_XCLK,     // 时钟源40M
        .clk_div = 40,                      // 分频数
        .period = 1000,                     // 周期
    };//设置PWM的频率,选择时钟,分频,和周期。根据上面的公式算出最终的频率。

    /*初始化PWM输出*/
    bflb_pwm_v2_init(pwm, &cfg);
    bflb_pwm_v2_start(pwm);          //将设置好的频率开启pwm输出


    while (1) {
        //蓝灯呼吸亮灭  
        // 正向通道使能输出
        bflb_pwm_v2_channel_positive_start(pwm, PWM_CH3);   // 需要看数据手册确定通道
        for(i=150;i>0;i--)
        {
            /**bflb_pwm_v2.h
             * @param [in] dev 设备句柄
             * @param [in] ch 通道号
             * @param [in] low_threhold 低阈值
             * @param [in] high_threhold 高阈值,需要大于 low_threhold,并且小于等于周期
             * PWM 占空比=(high_threhold - low_threhold)/period周期
             * bflb_pwm_v2_channel_set_threshold
             */
            bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, i, 150); //改变占空比,变量i会不断变化

            bflb_mtimer_delay_ms(10);
        }
        for(i=1;i<150;i++)
        {
            bflb_pwm_v2_channel_set_threshold(pwm, PWM_CH3, i, 150);

            bflb_mtimer_delay_ms(10);
        }
        bflb_pwm_v2_channel_positive_stop(pwm, PWM_CH3);    
    }
}
回复

使用道具 举报

iiv | 2024-6-13 23:02:07 | 显示全部楼层
很棒
回复

使用道具 举报

WT_0213 | 2024-6-14 08:43:46 | 显示全部楼层
回复

使用道具 举报

爱笑 | 2024-6-14 08:47:28 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

1084504793 | 2024-6-14 08:54:33 | 显示全部楼层
回复

使用道具 举报

jkernet | 2024-6-14 09:36:25 | 显示全部楼层
民间文档
回复

使用道具 举报

爱笑 | 2024-6-14 10:01:08 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

a1286544151 | 2024-6-15 19:07:09 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-6-17 09:38:47 | 显示全部楼层
实力强大
选择去发光,而不是被照亮
回复

使用道具 举报

lazy | 2024-6-17 18:16:51 | 显示全部楼层
回复

使用道具 举报

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

本版积分规则