[ BLE4.0 ] 伦茨ST17H66开发-PWM产生50HZ方波-驱动SG90舵机

目录

一、前言

二、设备选型

三、功能实现

3.1 PWM分析

3.2 查阅技术手册

3.3 实现代码

3.3.1 摘抄例程

3.3.2 分析参数

3.3.3 可用代码

四、实现效果


一、前言

        实现精确控制是许多物联网和自动化项目的核心需求,掌握PWM(脉冲宽度调制)技术尤为重要,在许多精细化控制的场景中,往往都是通过PWM实现的。

        那么本文选择了一个示例,想要通过PWM驱动SG90舵机,SG90舵机广泛应用于机器人、无人机、云台及自动化设备等领域,其控制依赖于精确的PWM信号。

二、设备选型

        本文选用的开发板芯片为ST17H66,本文中驱动的舵机为SG90(产生驱动PWM信号即可)180°,那么其驱动信号为50HZ的PWM信号,高电平占比分别为2.5%、7.5%、12.5%时,分别可以驱动舵机旋转-90°、0°、90°。

三、功能实现

3.1 PWM分析

        50HZ的驱动信号,说明其周期为20ms,我们以让其保持0°来说(本文中的角度并非实际角度,只代表与其他角度的相对角度,用来表明舵机的三个位置),那么我们需要产生1.5ms的高电平和18.5ms的低电平,然后持续该波形。

3.2 查阅技术手册

        为了探究ST17H66的PWM的实现方法,需要查阅技术手册,我们打开认识SDK文件。

        开发手册:【免费】伦茨ST17H66开发资源包_st17h66资源-CSDN文库

        具体我记得这个文件应该是唯一一个提到PWM功能实现的函数。

3.3 实现代码

3.3.1 摘抄例程

        首先,摘抄出文档中给出的代码。

hal_pwrmgr_register(MOD_USR8, NULL, NULL);// 开机初始化注册睡眠功耗控制变
量,睡眠会关闭pwm模块
hal_pwrmgr_lock(MOD_USR8);// 开启pwm之前需要设备不能进入睡眠,否则pwm失效
hal_pwm_init(PWM_CH0, PWM_CLK_DIV_4, PWM_CNT_UP, PWM_POLARITY_FALLING);
hal_pwm_open_channel(PWM_CH0, USR_IO_BUZZER);
hal_pwm_set_count_val(PWM_CH0, (((16000000/(1<<PWM_CLK_DIV_4))/(freq))*(duty)/100),\((16000000/(1<<PWM_CLK_DIV_4))/(freq)));
hal_pwm_start();

3.3.2 分析参数

        看到程序之后是不一头雾水?下面我们一起来分析程序。

hal_pwm_init(PWM_CH0, PWM_CLK_DIV_4, PWM_CNT_UP, PWM_POLARITY_FALLING);

        首先看hal_pwm_init函数,第一个参数很明显是PWM通道,此处我们可以不改变,使用CH0即可。

        剩下的三个参数分别为分频系数、计数模式、极性模式。其中分频系数和计数模式想必大家都比较了解,第三个极性我们选择PWM_POLARITY_FALLING,这将使PWM波的第二个阶段是低电平

        我们分频系数取决于我们系统的是时钟频率,在main.c中,本工程的时钟频率为16MHZ,因此我选择了16作为分频系数,这样可以得到1MHZ的频率,即每个时钟周期为1us。这样也方便产生20ms的周期波形。

        计数模式选择上升计数。

hal_pwm_open_channel(PWM_CH0, USR_IO_BUZZER);

        然后我们来看hal_pwm_open_channel函数,两个参数,根据函数名可以推断这是打开通道的函数,那么第一个参数就是通道,我们写前面初始化的通道,第二个参数,例程中没有提到,但是经过我的试验,这是IO口,所以写IO口即可,这里我选择P34。

hal_pwm_set_count_val(PWM_CH0, (((16000000/(1<<PWM_CLK_DIV_4))/(freq))*(duty)/100),\((16000000/(1<<PWM_CLK_DIV_4))/(freq)));

        最后再来看hal_pwm_set_count_val函数,看到这么多的运算是不是感觉很难,其实不然,我们不要看他的参数写的多多,我们去找到这个函数的定义。

/**************************************************************************************
    @fn          hal_pwm_set_count_val

    @brief       This function process for change pwm count value

    input parameters

    @param       PWMN_e pwmN                     : pwm channel
                uint16_t cmpVal                 : the compare value of PWM channel
                uint16_t cntTopVal              : the counter top value of PWM channel

    output parameters

    @param       None.

    @return      None.
 **************************************************************************************/
void hal_pwm_set_count_val(PWMN_e pwmN, uint16_t cmpVal, uint16_t cntTopVal)
{
    if(cmpVal > cntTopVal)
        return;

    PWM_NO_LOAD_CH(pwmN);
    PWM_SET_CMP_VAL(pwmN, cmpVal);
    PWM_SET_TOP_VAL(pwmN, cntTopVal);
    PWM_LOAD_CH(pwmN);
}

        一切豁然开朗,不过就是我们常说的比较值重装载值而已。之前我们通过分频,已经知道其产生的1us的周期,那么我们20ms一个周期就可以写重装载值为20*1000us。比较值1.5ms我们可以写1.5*1000us。

3.3.3 可用代码

        我们将代码按需修改后如下:

hal_pwrmgr_register(MOD_USR8, NULL, NULL);
hal_pwrmgr_lock(MOD_USR8);// 开启pwm之前需要设备不能进入睡眠,否则pwm失效
hal_pwm_init(PWM_CH0, PWM_CLK_DIV_16, PWM_CNT_UP, PWM_POLARITY_FALLING);//16分频 上升模式 低电平
hal_pwm_open_channel(PWM_CH0, P34);
hal_pwm_set_count_val(PWM_CH0,1500,20000);//1us--20ms
hal_pwm_start();

        我们将其代码,放到我们的任务初始化函数中,关闭睡眠模式,工程引入pwm.c文件,使用时导入pwm.h文件。

四、实现效果

        烧写程序后,本文代码经我使用示波器查看后,波形正确。(忘记拍照了哈哈)

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西西菜鸟

打赏支持获得问题解答机会

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值