TIM输出比较【OC】

TIM输出比较【OC】

通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作

PWM:等效模拟参量

image
image

参数

频率 = 1 / TS
占空比 = TON / TS
分辨率 = 占空比变化精细程度

基本结构

image

红线:CCR
黄线:ARR
蓝线:CNT
斜率:PSC

image

参数计算

频率 Freq = CK_PSC / (PSC + 1) / (ARR + 1)
占空比 Duty = CCR / (ARR + 1)
分辨率 Reso = 1 / (ARR + 1)

eg.

(ARR+1)=100
若CCR=50 占空比为50% 高电平和低电平的时间始终相等
CCR↑ 占空比变大
CCR↓ 占空比变小

输出比较通道

通用计时器

image

高级计时器

image

输出比较模式

image

l298n电机驱动

image
(1)控制1个电机3条线:TIM1个 I/O2个
(2)控制电机正反转:(IN1=IN3 IN2=IN4)
image

代码部分

【配置输出通道】
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只能给正数
	}
}
posted @ 2024-11-11 07:47  White_ink  阅读(6)  评论(0编辑  收藏  举报