目录
2.2.1、输出比较通道函数(即一、1.1函数),需要初始化那个通道就调用那个通道。
PWM配置流程图
1、与pwm相关的函数介绍
1.1、输出比较函数配置
1.1.1、以下四个函数是配置图1中的四个比较单元
参数1:选择定时器
参数2:结构体
TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
TIM_OC2nit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
1.1.2、输出结构体赋默认值
TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct)
补充:在使用高级定时器时需要调用以下函数,否则PWM无法开启工作
TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)
1.2、单独修改参数的相关函数
1.2.1、单独设置极性相关函数
TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
其中OCXN中的N代表高级定时器的互补通道配置。
1.2.2、单独修改输出使能参数函数
TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx)
TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN)
1.2.3、单独修改输出比较模式函数
TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode)
1.2.4、单独更改CCR寄存器的值(需掌握)
TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)
TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3)
TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4)
1.3、小功能函数配置(暂时仅需了解)
1.3.1、配置强制输出模式
//在运行中停止输出波形并强制输出高/低电平
TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
1.3.2、配置CCR寄存器的预装功能(即影子寄存器)
TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
1.3.3、配置快速使能
TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
1.3.4、外部事件是清除REF信号
TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
二、代码配置
2.1、输出PWM的GPIO口配置
具体配置参数详见GPIO口的配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//选择推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
其中对于 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP 为什么选择推挽输出,原因如下:
对于普通的开漏/推挽输出,其引脚控制权来自于输出数据寄存器;如果需要使用定时器控制引脚,需要复用开漏/推挽输出模式,此时输出数据寄存器被断开,输出控制权将移交给片上外设。
部分代码展示
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //开启时钟,TIM2是APB1总线的外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟,选择GPIOkou
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//选择推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
2..2、初始化输出比较单元
2.2.1、输出比较通道函数(即一、1.1函数),需要初始化那个通道就调用那个通道。
参数1:选择定时器
参数2:结构体
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
2.2.2、定义结构体变量以及结构体信息
//定义结构体变量
TIM_OCInitTypeDef TIM_OCInitStructure;
//选择输出模式
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
图2
图2中分别对应着冻结模式、相等时置有效电平、相等时置无效电平(即低电平)、相等时电平翻转、PW1/PW2模式。
2.2.3、 输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
上图对应着有效电平是高电平,REF有效时,输出高电平;低极性,REF电平取反,
//输出状态,使能or失能
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
//设置CCR寄存器的值。
TIM_OCInitStructure.TIM_Pulse=50;
例如要产生一个频率为1KHZ,占空比为50%,分辨率为1%的PWM波形,可以用下图计算公式得出CCR的值为50。
相对应下图配置也需改变
2.2.4、结构体赋初值
如不赋初值,则可能导致后续程序出现不必要的错误,因此为了防止出现此状况,需赋初值避免出现错误,赋初值后可以引用函数对结构体信息单独赋值。
参数:结构体变量
TIM_OCStructInit(&TIM_OCInitStructure);
部分代码展示
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//整个结构体附初始值,避免出现错误
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //输出比较极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出状态,使能or失能
TIM_OCInitStructure.TIM_Pulse=0; //设置CCR寄存器的值
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
2.2.5、单独更改CCR的值
以便实现呼吸灯的效果。详见一中的2.4
PWM_SetCompare(uint16_t Compare);
用法:
void PWM_SetCompare(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);
}
3、主程序代码
uint8_t i;
int main(void)
{
OLED_Init(); //OLED初始化
PWM_Init();
while(1)
{
for(i=0;i<=100l;i++)
{
PWM_SetCompare(i);
Delay_ms(10);
}
for(i=0;i<=100l;i++)
{
PWM_SetCompare(100-i);
Delay_ms(10);
}
}
三、舵机的使用
由第一张图可以知道周期为20ms,则由公式 Freq=CK_PSC/(PSC+1)/(ARR+1)有:
Freq=72MHZ/72/20k=50Hz,其中(PSC+1)=72;(ARR+1)=20K;这两个值可以自己调整;
则由Duty=CCR/(ARR+1)有,CCR是500时,占空比为0.5ms,CCR为2500时,占空比为2.5ms.
由此可以知道以下参数应为
对于如何控制CCR的值,我们使用一个函数去控制CCR的值,
TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)