赞
踩
输出比较可以通过比较CNT(计数器)与CCR(捕获/比较)寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。
每个高级定时器和通用定时器都拥有4个输出比较通道
高级定时器的前3个通道额外拥有死区生成和互补输出的功能(用于驱动三相无刷电机)
通用定时器:均有4个通道
(PWM调光,通过高频点亮熄灭,点亮熄灭来实现对灯光强弱的控制,只要闪的够快就发现不了是正常的还是没有的)
原因:LED熄灭时,由于人眼的余辉和视觉暂留现象,LED不会立刻熄灭,过一小段才会熄灭,电机也是因为惯性过一会才会停下来
极性选择:就是选择要不要把高低电平反转一下
占空比和CCR值有关
对于普通的推挽输出:引脚的控制权来自于输出数据寄存器,来进行输出控制
而想要定时器来控制引脚就需要使用复用开漏推挽输出。(定时器属于片上外设)
如果要重定义某个端口:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//给AFIO使能
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE); //重映射 把CH1的PA0换到PA15
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable ,ENABLE);//关闭PA15的调试端口的功能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//给TIM2使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//给GPIO使能 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //由于定时器属于片上外设,所以采用复用推挽输出, GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; //根据引脚表的出CH_1所在引脚时PA0 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStruct); TIM_InternalClockConfig(TIM2); //选择内部时钟 给时基单元提供时钟 //时基单元 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //每一个时钟后面都会加一个滤波器, //作用就是为是信号更加稳定,使用的采样的方式, //在输入的脉冲中采样,按照n/f,因此采样系数越大,延迟越大 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数方式,递增 TIM_TimeBaseInitStruct.TIM_Period = 100-1; //ARR =100 TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1; // psc = 720 //预分频器,72MHZ进行7200分频 , //72000/7200 = 10KHZ 1ms = 1KHZ //10KHZ下记10000个数 10000/10000HZ = 1S // f = 1/t TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器(高级定时器才有) TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct); //配置比较输出模块 TIM_OCInitTypeDef TIM_OCInitStruct; TIM_OCStructInit(&TIM_OCInitStruct);//给结构体赋初始值 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式 //TIM_OCInitStruct.TIM_OCNIdleState = ; //带N的都是高级定时器才用的 //TIM_OCInitStruct.TIM_OCNPolarity = ; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //输出比较极性 //TIM_OCInitStruct.TIM_OutputNState = ; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; //使能输出状态 TIM_OCInitStruct.TIM_Pulse = 50;//CCR的值 TIM_OC1Init(TIM2,&TIM_OCInitStruct); //运行控制,所有的模块配置完毕,启动时基单元 TIM_Cmd(TIM2,ENABLE); //如果要使用高级定时器,就需要把TIM2改为TIM1,那么结构原来用不到的成员。就需要用到,这些成员又没有赋值, //这个时候就会出现奇怪的问题,如果把初始化函数放在的程序第一行没有问题,初始化函数前面出现了其他的代码,那么4路PWM就会有3路不能输出。这竟然和初始化函数在那一行有关。 //原因是,没有给结构体配置完整,也没有给结构体赋初始值。所以要用到structInit()函数,给结构体赋初始值。
舵机是一种根据输入PWM信号占空比来控制输出角度的装置
输入PWM(可当作一种输出协议)信号要求:周期为20ms,高电平宽度为0.5ms~2.5ms
void Servo_Init(void)
{
PWM_Init();
}
void Servo_SetAngle(float Angle)
{
//0 500
//180 2500 度数
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
PWM驱动舵机
1.RCC使能GPIO
2.选择时钟,给定时器单元使能
3.配置时基单元(也就是计数模块)
4.配置输出比较模块
5.启动时基单元
6.逻辑函数
选用的是通用定时器TIM2,
由于直流电机上的PWMA连接的是PA2口,根据引脚定义表。PA2对应的时钟通道是TIM2_CH3.
所以在选择输出比较通道时,选择初始化3通道。TIM_OC3Init(TIM2,&TIM_OCInitStruct);
void Motor_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出模式,高低电平均可以亮 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //方向控制角 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStruct); PWM_Init(); } void Motor_SetSpeed(uint8_t speed) { if(speed >= 0) { GPIO_SetBits(GPIOA,GPIO_Pin_4); //给端口4给高 5给低 正转 GPIO_ResetBits(GPIOA,GPIO_Pin_5); PWM_SetCompare3(speed); //给PWM设置CCR的值 捕获比较值,根据不同CCR的值,得到PWM波也不同,输出的速度自然不同 } else { GPIO_ResetBits(GPIOA,GPIO_Pin_4); //给端口4给低 5给高 反转 GPIO_SetBits(GPIOA,GPIO_Pin_5); PWM_SetCompare3(-speed); } }
//配置输出比较单元
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);
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
//配置强制输出模式
//如果暂停输出波形并且强制输出高/低电平,强制设置高电平,和设置100%占空比是一样的
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);
//用来单独设置输出比较的极性,带N的就是高级定时器,互补通道的配置,OC4没有互补通道,所以没有OC4N的函数。 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); //用来单独修改输出使能函数 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); //单独修改选择输出比较模式 void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode); //用来单独修改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);
//这个函数仅再高级定时器使用!!!!!!,在使用高级定时器输出PWM时,需要调用这个函数使能主输出,否则PWM将不再正常输出
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。