【注意,标注“*”的部分属于了解即可,无需过多关注】
一:库函数
1.配置输出比较模块
(1)输出比较单元控制
在硬件电路中,输出比较控制器一共有4个,对应的有4个输出比较 单元
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
(2)给输出比较结构体赋默认值
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
(3)用来单独更改输出比较单元控制器中结构体的函数
a.单独更改CCR寄存器值的函数
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
b.修改输出使能函数*
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);
c.选择输出比较模式*
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);
d.单独设置输出比较的极性*
带有“N”的就是高级定时器里互补通道的配置,其中OC4没有互补通道,结构体初始化的地方也可以设置极性
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
(4)配置强制输出模式*
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
(5)配置CCR寄存器的预装功能,即是影子寄存器*
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
(6)配置快速使能,在功能手册的单脉冲模式有介绍*
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
(7)外部事件时清除REF信号*
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
(8)仅高级计时器使用,使能主输出。否则PWM不能正常输出*
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
二、书写PWM初始化函数
步骤:
1.RCC开启时钟,将TIM外设和GPIO外设全部打开
2.配置时基单元,包括之前的时钟源选择
3.配置输出比较单元,包括CCR的值,输出比较模式,极性选择,输出使能
4.配置GPIO,将PWM对应的GPIO口初始化为复用推挽输出的配置
5.运行控制,启动计数器,输出PWM
因为该图中不经过NVIC部分,即无需写输出控制以及NVIC相关的函数,复制之前的工程即可获得1.2.5.的代码,无需再次书写
3.输出比较单元的书写
(1)使用PA0的口,根据引脚对应表显示,使用的正是一号通路
TIM_OC1Init()
参数2是一个结构体,但是该结构体中的许多成员都是高级定时器才有的,但是如果不进行配置会导致结构体成员为空,会出现一定的错误。所以在此之前要给结构体的所有成员赋予初始值,使用TIM_OCStructInit()函数,该函数就是用来给结构体赋初始值的
通用定时器需要使用的结构体成员有:
TIM_OCMode,输出比较模式
TIM_OCMode_Timing 冻结模式
TIM_OCMode_Active 相等时置有效电平
TIM_OCMode_Inactive 相等时置无效电平
TIM_OCMode_Toggle 相等时电平反转
TIM_OCMode_PWM1 PWM模式1
TIM_OCMode_PWM2 PWM模式2
该处使用的是TIM_OCMode_PWM1
(2)TIM_OCPolarity 输出比较极性
TIM_OCPolarity_High 高极性,即极性不翻转,REF波直接输出;有效电平为低电平
TIM_OCPolarity_Low 低极性,REF极性取反,有效电平为低电平
此处选用TIM_OCPolarity_High
(3)TIM_OutputState 输出状态,输出使能
TIM_OutputState_Disable
TIM_OutputState_Enable
(4)TIM_Pulse 脉冲,用来设置CCR寄存器
取值范围是 0x0000 and 0xFFFF
4.配置GPIO口
根据引脚定义表,可知TIM2_CH1与PA0口对应上,即需要初始化PA0号口
需要使用复用推挽输出,输出控制寄存器的控制断开,转而接上片上外设
6.针对ARR,PSC,CCR的数据选择
这三个数据分别来自于时基单元与输出比较单元的结构体,若是想要获得一个1000Hz,50%占空比,1%分辨率的状态,根据公式
• PWM 频率: Freq = CK_PSC (72M )/ (PSC + 1) / (ARR + 1)
• PWM 占空比: Duty = CCR / (ARR + 1)
• PWM 分辨率: Reso = 1 / (ARR + 1)
计算值分别为100,720,50
三、PWM控制呼吸灯主程序
需要利用TIM_SetCompare1()函数设置一个新的函数PWM_TIMSetCompare1(),以便于能够在主函数中随时调用更改CCR寄存器内部值,实现呼吸灯
while (1)
{
for (i = 1;i<=100;i++)
{
PWM_TIMSetCompare1(i);
Delay_ms(10);
}
for (i = 1;i<=100;i++)
{
PWM_TIMSetCompare1(100-i);
Delay_ms(10);
}
}
此外,如果想要使用重映射,就需要加入一下代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 开启AFIO的时钟,重映射必须先开启AFIO的时钟
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); 将TIM2的引脚部分重映射,具体的映射方案需查看参考手册
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); 将JTAG引脚失能,作为普通GPIO引脚使用
并且将端口PA0改为PA15(根据引脚对定义表)
四、PWM控制舵机
1.如果同时使用2个及以上捕获/比较寄存器时,由于他们共用一个CNT计数器,所以他们的PWM频率是相同的,相位也是同步的。
2.舵机对频率的要求是固定的20ms,50Hz,高电平时间为0.5ms-2.5ms,对应的占空比为2.5%-12.5%。其中,ARR设置为20000,PSC=72即可,ARR的20k对应20ms,则输入的CCR0.5k对应0.5ms等等