一般用于驱动电机,舵机,进行对呼吸灯的配置。
1、输出比较简介(OC)
输出比较可以通过比较CNT与CCR寄存器值的关系,对输出电平进行0,1,及翻转的操作,用于输出一定频率和占空比的PWM波形。
图中画的那两块,CNT自增,CCR是给定的一个值,当他们进行比较时会产生一个点评不断跳转的pwm波。
2.每个高级定时器和通用定时器都有4个输入输出比较通道
3.高级定时器的3个通道额外拥有死区生成和互补输出功能
PWM简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
具有惯性的系统才能使用PWM(像是LED小灯灭了不能立刻灭,电机转了不能直接灭)。
差不多就可以理解为它动了又停了但是这个时间间隔很小,太快了人没反应过来,这个重复很多次会产生一个波形,就差不多是我们的PWM波。
高电平比低电平多,就趋近于高电平。低电平比高电平多,就趋于下面的图形。
分辩率:是指PWM最小能设定到的高电平时间所占周期的比例,也即最小占空比,意思就是把一个周期的时间分成了多少份,如果是10份,那么占空比的精度就为10%。如果分成1000份,那么占空比的精度就为0.1%。譬如频率为600HZ的PWM,若最小能给到的时钟是60kHZ,则分辨率即为(1/60k)/(1/600)=1%。在同一个系统中,由于时钟不变,提高频率,则周期变小,分辨率会变大。
输出比较模式
冻结可理解位CNT和CCR无效,可用于你正在输出PWM波,突然想暂停一会,这时候输出就暂停了,高低电平也维持暂停时刻的状态不变。要是想暂停输入波形,并在暂停期间保持低电平和高电平,可用5,6强制为无效或有效电平。
有效电平就是高电平,无效电平就是低电平。CNT=CRR时匹配时电平翻转,可以输入一个频率可调,占空比始终为%50的PWM波形(高低电平始终相等)
要是想定时输入一个一次性的信号,可以考虑使用2,3的功能。
最后的 PWM模式一和模式二很重要,可以用于输出频率和占空比都可调的PWM波形,一般只使用向上计数
PWM参数计算
如图的占空比=30/(99+1)=%30
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。通用定时器也能同时产生多达 4 路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!这里我们仅利用 TIM3 的 CH2 产生一路 PWM 输出。如果要产生多路输出,大家可以根据我们的代码稍作修改即可。我们使用的是 TIM3 的通道 2,所以我们需要修改 TIM3_CCR2 以实现脉宽控制 DS0 的亮度。
1)开启 TIM3 时钟以及复用功能时钟,配置 PB5(这个是板子的DS0的串口)为复用输出。
要使用 TIM3,我们必须先开启 TIM3 的时钟,这点相信大家看了这么多代码,应该明白了。 这里我们还要配置 PB5 为复用输出,这是因为 TIM3_CH2 通道将重映射到 PB5 上,此时,PB5 属于复用功能输出。库函数使能 TIM3 时钟的方法是: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//使能定时器 3 时钟 这在前面一章已经提到过。库函数设置 AFIO 时钟的方法是: RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//复用时钟使能 这两行代码很容易组织,这里不做过多重复的讲解。设置 PB5 为复用功能输出的方法在前面的 几个实验都有类似的讲解,相信大家很明白,这里简单列出 GPIO 初始化的一行代码即可: GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
2)设置 TIM3_CH2 重映射到 PB5 上。
因为 TIM3_CH2 默认是接在 PA7 上的,所以我们需要设置 TIM3_REMAP 为部分重映射(通 过 AFIO_MAPR 配置),让 TIM3_CH2 重映射到 PB5 上面。在库函数函数里面设置重映射的函 数是: void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState),STM32 重映射只能重映射到特定的端口。第一个 入口参数可以理解为设置重映射的类型,比如 TIM3 部分重映射入口参数为 GPIO_PartialRemap_TIM3,这点可以顾名思义了。所以 TIM3 部分重映射的库函数实现方法是: GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
3)初始化 TIM3,设置 TIM3 的 ARR 和 PSC。
在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的 周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM 周 期在这里不宜设置的太小。这在库函数是通过 TIM_TimeBaseInit 函数实现的,在上一节定时器 中断章节我们已经有讲解,这里就不详细讲解,调用的格式为: TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的
4)设置 TIM3_CH2 的 PWM 模式,使能 TIM3 的 CH2 输出。 接下来,我们要设置 TIM3_CH2 为 PWM 模式(默认是冻结的),因为我们的 DS0 是低电 平亮,而我们希望当 CCR2 的值小的时候,DS0 就暗,CCR2 值大的时候,DS0 就亮,所以我 们要通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设 置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我 们使用的是通道 2,所以使用的函数是 TIM_OC2Init()。 void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 这种初始化格式大家学到这里应该也熟悉了,所以我们直接来看看结构体 TIM_OCInitTypeDef 的定义: typedef struct { uint16_t TIM_OCMode; uint16_t TIM_OutputState; uint16_t TIM_OutputNState; */ uint16_t TIM_Pulse; uint16_t TIM_OCPolarity; uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef; 这里我们讲解一下与我们要求相关的几个成员变量: 参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。 参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。 参数 TIM_OCPolarity 用来设置极性是高还是低。 其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是 高级定时器 TIM1 和 TIM8 才用到的。 要实现我们上面提到的场景,方法是: TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
5)使能 TIM3。 在完成以上设置了之后,我们需要使能 TIM3。使能 TIM3 的方法前面已经讲解过: TIM_Cmd(TIM3, ENABLE); //使能 TIM3
6)修改 TIM3_CCR2 来控制占空比。 最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定 的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。继而控制 DS0 的亮度。 在库函数中,修改 TIM3_CCR2 占空比的函数是: void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); 理所当然,对于其他通道,分别有一个函数名字,函数格式为 TIM_SetComparex(x=1,2,3,4)。
通过以上 6 个步骤,我们就可以控制 TIM3 的 CH2 输出 PWM 波了。
//TIM3 PWM 部分初始化
//PWM 输出初始化
//arr:自动重装值
psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//①使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
RCC_APB2Periph_AFIO, ENABLE);//①使能 GPIO 和 AFIO 复用功能时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//②重映射 TIM3_CH2->PB5
//设置该引脚为复用输出功能输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);//①初始化 GPIO
//初始化 TIM3
TIM_TimeBaseStructure.TIM_Period = arr;//设置在自动重装载周期值
TIM_TimeBaseStructure.TIM_Prescaler =psc;//设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM 向上计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//③初始化 TIMx
//初始化 TIM3 Channel2 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性高
TIM_OC2Init(TIM3,&TIM_OCInitStructure);//④初始化外设 TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能预装载寄存器
TIM_Cmd(TIM3, ENABLE);//⑤使能 TIM3
}
舵机
PWM信号输入到控制板,给控制板一个指定的目标角度,然后电位器检测输出轴的当前角度,如果大于目标角度,多几家就会反转。如果小于目标角度,电机就会正转,最终令输出轴固定在指定角度(输入一个PWM波形,输出轴固定在一个指定角度)
像是上方周期为20MS,那个频率等于周期的倒数即为50HZ,高电平宽度为0。5ms到2.5MS,这个就是占空比的范围,这个到旁边那个表格中去看。按比例来算。
控制原理:
定时器配置:将定时器设置为PWM模式,并设置输出比较通道的数量,以及每个通道的输出比较值(对应占空比)。同时设置定时器的频率,用来控制舵机的转速。
GPIO配置:将输出比较通道所对应的GPIO引脚配置为复用输出模式,以便输出PWM信号。
舵机控制:通过修改每个输出比较通道的比较值,可以控制舵机的角度。舵机的转动角度与输出PWM信号的占空比成正比,因此根据不同的舵机型号和要求,可以设置不同的PWM占空比来控制舵机的转动角度。
控制程序实现:在主程序中,设置舵机的初始位置和目标位置,并根据既定的算法逐渐调整每个比较通道的比较值,来实现舵机的平滑运动。可以同时控制多个舵机,通过不同的定时器和输出比较通道来实现。
原文链接:https://blog.csdn.net/Miraitowain/article/details/130466407
直流电机驱动
TB6612
靠电压差及逆行转,如果PWM十一个不断翻转的电平信号,电机就快速的反转,停止,反转,停止,如果PWM频率足够快,电机就可以连续稳定的反转了,速度取决于PWM的占空比。
L298N
注:当单片机与驱动不是同一电源时要供地。
控制方式
1.直接给高低电平
通过引脚的高低搭配,控制电机的正反转和停止,速度最大不可调。
2.PWM方式控制
通过快速的改变其中一个引脚的高低电平,使电机的开关不停的来回切换从而改变电机的转速。
3.改变电机A/B的使能
去掉A/B电机使能跳帽,另接到单片机引脚上,通过pwm迅速使能失能A/B电机的开关,来改变转速。
原文链接:https://blog.csdn.net/qq_64171874/article/details/127713410(这个有详细介绍)
如果只驱动一个电机,接线方面如下:
输出A的OUT1与OUT2 ——> 电机的两端
12V供电 ——> 7-12V电源
供电GND ——> GND (与单片机共地)
ENA ——> 单片机IO口 (可自己定义,需要具备PWM功能的IO口)
IN1、IN2 ——> 单片机IO口 (可自己定义)
如果要驱动两个电机,同理即可
原文链接:https://blog.csdn.net/m0_73629902/article/details/131524776