CubeMX初配置PWM&驱动MG995舵机
CubeMX初配置PWM&驱动MG995舵机
最近在重学STM32,发现大二上整的像s一样
参考博客
[Bonjour STM32] No.6-定时器简单理解与使用 - Emoe-Studio
STM32CubeMX学习笔记1——PWM配置_夏沫不学习的博客-CSDN博客_cubemx配置pwm
PWM
个人理解:PWM就是方波,具体使用的时候改变这玩意的占空比就行。
配置PWM
要知道 CNT
(计数器当前值), ARR
(自动重装载值), CCRx
(捕获/比较寄存器值)
当 CNT
小于 CCRx
时,通道输出高电平;
当 CNT
等于或大于 CCRx
时,通道输出低电平;
因为目前使用 STM32F103C8T6
,首先设置使用外部时钟,再设置时钟为72Mhz
直接输入 72 就行,CubeMX 会自动配置
然后贴一段参考博客里的:
确定时钟源频率后,我们就可以设置PSC和ARR了。按照之前的要求,我们想让定时器的溢出频率为5Hz,则240MHz/5Hz=48M分频。我们知道,一个模值(“容量”)为48M的定时器即可完成此分频,可是我们的CNT寄存器只有16位,也就是说模值最大设置为65535,远远不够呀。这就是预分频器PSC存在的意义了,“时钟源太快了,CNT没有足够的容量来实现较长周期的定时,所以需要预分频器把时钟降慢一些”。所以说,我们把48M拆成2400*20000就可以了。注意实际填入PSC和ARR都有一个“-1”,这是因为定时器是从0开始计数的,由0计到239正好是240次。总结一个定时器频率公式,就是这样:
$$f_{TIM}=\frac{f_{CLK}}{(PSC+1)\times(ARR+1)}$$
改变占空比只需要改变对应计时器的 CCRx 就行
$$Duty_x=\frac{CCRx}{ARR}$$
因为 MG995 电机需要一个20ms的时基脉冲,所以需要频率50Hz,为我们设置 PSC=7200-1
ARR=200-1
72000000/7200/200=50
所以计数器每次 +1
的时间为 20ms/ARR=20ms/200=0.1ms
在CubeMX配置如下
设置 TIM3 定时器 ,只用一个通道就行,设置为 PWM模式,默认是 GPIOA16 管脚

先点个灯
历时108个秒,我做出了苹果手机没有的功能,呼吸灯
呼吸灯的呼吸,就是灯的强弱状态,改变 PWM 的占空比便可调整
具体配置和前面差不多,这里设置为 ARR=500
改变 CRRx 的两种方式
//ld1_duty 为我们设置的CCRx具体数值
//方法一,直接操作
TIM3 -> CCR1 = ld1_duty;
//方法二,使用库函数
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,ld1_duty);
主要代码为
int main(void)
{
// 省略一堆初始化函数
// 记录变强还是变弱
uint8_t ld1_dir = 0;
// 相当于CNT
uint16_t ld1_duty = 0;
// 初始化,启动 TIM3 通道1的 PWM 模式
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //PA6
while (1)
{
// 变强状态
if(ld1_dir == 1) {
ld1_duty += 20;
}
// 变弱状态
if(ld1_dir == 0) {
ld1_duty -= 20;
}
// 由强变弱
if(ld1_duty >= 500) {
ld1_dir = 1;
}
// 由弱变强
if(ld1_duty == 0) {
ld1_dir = 0;
}
// 使用库函数改变 TIM3 通道1 PWM 的占空比
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,ld1_duty);
//延时
HAL_Delay(50);
}
}
大概效果
驱动MG995舵机
这玩意具体参数可以去参考的博客去看
控制原理
舵机的控制一般需要一个20ms的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度舵机为例,那么对应的控制关系是这样的:
0.5ms————–0度;
1.0ms————45度;
1.5ms————90度;
2.0ms———–135度;
2.5ms———–180度;
既然前面已经配置好时钟了,可以直接写代码了
调上面的角度转换成对应高电平部分
// 对应角度 0 45 90 135 180
uint8_t deg[5] = {5,10,15,20,25};
启动 TIM3 通道1的 PWM 模式
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //PA6
所以主函数为
int main(void)
{
// 省了略各种初始化函数
uint8_t deg[5] = {5,10,15,20,25};
// 初始化,启动 TIM3 通道1的 PWM 模式
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //PA6
while (1)
{
// 先正转,再反转
for(int i = 1; i < 5; ++i) {
// 更新CCR1值,直接用寄存器操作
TIM3 -> CCR1 = deg[i];
// 延时,等舵机转过去
HAL_Delay(1000);
}
for(int i = 3; i >= 0; --i) {
TIM3 -> CCR1 = deg[i];
HAL_Delay(1000);
}
}
}
转动效果
对了如果发现不转记得检查一下供电,最好插上电源线再测试。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!