前言(可绕开):
今天大年初二,还是来温习下PWM输出的知识,献此教程给有所有初学者。
PWM输出,可以用来做很多事情,呼吸灯,蜂鸣器,当然了最主要的还是 电机和舵机 控制了,主要通过的方式,就是改变占空比,当然就就可以模拟电压了! 学好这个,你就迈进了控制机器的门!!!
这里我用的开发板时正点原子的MiniSTM32,芯片型号为STM32F103RCT6. This is easy, so you can do that very easily!
[objc] view plain copy
我们在这里进行通俗的讲解,详细的内容,可以在以后再去看STM32手册。
接下来,还是一块一块代码进行分析,将其中的重点进行说明:
void pwm_Config(u16 period, u16 psc){
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
这里我们定义函数, 这里不用使用AFIO模式,我们使用TIM1, PA8-通道1 ,PA11-通道4。 stm32f103的TIM的定时器一共有8个
其中可以输出和捕获的PWM的只有TIM1,TIM8高级定时器 , TIM2~TIM5普通定时器。 且能做到互补输出的只有高级定时器。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_Mode,这里必须采用复用推挽输出GPIO_Mode_AF_PP,不是复用推挽就需要打开AFIO复用模式,是在引脚复用时候需要打开!
TIM_TimeBaseStructure.TIM_Period = period-1;
TIM_TimeBaseStructure.TIM_Prescaler = psc-1;
TIM_TimeBaseStructure.TIM_ClockDivision= 0 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
关键的地方到了! 一行一行来!
Peroid就是周期,PWM通俗讲是有规律的高低电平,比如低电平400,高电平600,那么总的周期就是1000,我们需要改变的占空比就是 低电平/周期 或者高电平/周期。 至于为什么要 -1 ,因为计数从0~9。
Prescaler就是预分频,我们用的 TIM1 是72MHz的,有些控制是要求频率限制的,我们计算时PWM频率是这样的:假如我们需要1KHz的频率,1000的周期,那么我们需要输入的参数为 周期:1000, 预分频:72, 你会发现 频率*周期*预分频 就是72MHz。 接下来有个通俗的讲解,分频后TIM频率就是 1000KHz ,就是每秒振动1000K下,振动1000下一个周期,其中一个周期振动400下为低电平,振动600下为高电平,换算成时间就是 高电平:400/1000K 就是0.4ms 低电平: 600/1000K 就是0.6ms 一个周期为1ms 。
为了配置上面的参数,就是后面的语句了:
TIM_ClockDivision为时钟分割,一般的我们都为0,TIM_CounterMode 这个计数模式影响到后面PWM模式,一般的我们采用向上计数模式TIM_CounterMode_Up
TIM_OCMode这里是非常讲究的:
PWM模式1- 在向上计数时,一旦TIMx_CNT
则为有效电平(OC1REF=1)。
PWM模式2- 在向上计数时,一旦TIMx_CNT
平。
我们这里采用的是PWM模式2, TIMx_CCR1 为设置比较值,什么是有效电平呢?就是TIM_OCPolarity_High这个表达的意思就是高电平为有效值,TIM_SetCompare1(TIM1,400);设置比较值得时候,意思为1000-400 =600 , 就是占空比为0.4,0.4个周期为低电平,0.6个周期为高电平。
TIM_OutputState设置输出使能。
TIM_Pulse这里设置一开始默认的比较值。
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_OC4Init(TIM1,&TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);
这里我们使用TIM1 得通道1 和通道4 ,初始他们的结构体,然后最重要的的是,还要初始化重复装载,让周期重复进行。
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_CtrlPWMOutputs(TIM1,ENABLE);
TIM_Cmd(TIM1,ENABLE);
}
这里初始化 TM1得预装载,使能PWM输出,使能TIM1,这些都是常见得必须配置。
到这里整个初始化函数,就配置结束了,我们改变它得占空比,就可以通过
TIM_SetCompare1(TIM1,400); //通道1的比较值
TIM_SetCompare4(TIM1,400); //通道4的比较值
是不是很简单啊!说实话,如果你是单片机创建者,考虑这些参数配置,其实都是很有必要的。