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);
}
}