TIM输出比较【OC】
TIM输出比较【OC】
通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作
PWM:等效模拟参量
参数
频率 = 1 / TS
占空比 = TON / TS
分辨率 = 占空比变化精细程度
基本结构
红线:CCR
黄线:ARR
蓝线:CNT
斜率:PSC
参数计算
频率 Freq = CK_PSC / (PSC + 1) / (ARR + 1)
占空比 Duty = CCR / (ARR + 1)
分辨率 Reso = 1 / (ARR + 1)
eg.
(ARR+1)=100
若CCR=50 占空比为50% 高电平和低电平的时间始终相等
CCR↑ 占空比变大
CCR↓ 占空比变小
输出比较通道
通用计时器
高级计时器
输出比较模式
l298n电机驱动
(1)控制1个电机3条线:TIM1个 I/O2个
(2)控制电机正反转:(IN1=IN3 IN2=IN4)
代码部分
【配置输出通道】
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);
//仅高级定时器使用
//在高级定时器输出PWM时需要调用使能
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
//更改占空比:修改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);
【初始化TIM】
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
/*GPIO初始化*/
//注意引脚定义!!通用计时器只有4个口有TIM
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//将PA1引脚初始化为复用推挽输出
//受外设控制的引脚,均需要配置为复用模式
/*配置时钟源*/
TIM_InternalClockConfig(TIM2);
//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
//定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
//重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//配置TIM2的时基单元
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//结构体初始化,赋初始值
//最好执行此函数,给结构体所有成员都赋一个默认值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//输出比较模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //初始的CCR值
TIM_OC2Init(TIM2, &TIM_OCInitStructure);//配置TIM2的输出比较通道2
/*TIM使能*/
TIM_Cmd(TIM2, ENABLE);//使能TIM2,定时器开始运行
PWM内要封装一个函数处理CCR修改
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2, Compare);//设置CCR2的值
}
【控制电机用GPIO】
void Motor_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
//注意要有2个引脚!
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//将PA4和PA5引脚初始化为推挽输出
PWM_Init();//初始化直流电机的底层PWM
}
【更改速度:修改CCR】
void Motor_SetSpeed(int8_t Speed)
{
if (Speed >= 0)//如果设置正转的速度值
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);//PA4置高电平
GPIO_ResetBits(GPIOA, GPIO_Pin_5);//PA5置低电平,设置方向为正转
PWM_SetCompare3(Speed); //PWM设置为速度值
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4); //PA4置低电平
GPIO_SetBits(GPIOA, GPIO_Pin_5); //PA5置高电平,设置方向为反转
PWM_SetCompare3(-Speed);//PWM只能给正数
}
}