基本定时器功能的应用以及功能函数
STM32F103C8T6共有TIM1,TIM2,TIM3,TIM4四个定时器,其中TIM1是高级定时器,其余均为通用定时器,现在介绍定时器的时钟来源以及基本操作
时钟来源,定时器的时钟总线处在APB1上,APB1上的时钟经过分频后的时钟提供给APB1上的低速外设,而APB1上的定时器外设则是在分频后经过*2得到。
基本操作,定时器可以对APB1上的供给时钟进行分频后供给给计数器,并设置重装载值,计数器在计数到重装载值之后会清零。注意,要对PSC和ARR进行-1操作后才能设置到想要的值。
相关函数与一般操作
MYTIM.h
void Start_Count(TIM_HandleTypeDef htim);//开始计数
void Stop_Count(TIM_HandleTypeDef htim);//停止计数
uint16_t Get_Count(TIM_HandleTypeDef htim);//获取当前计数值
void Set_PWM_PSC(TIM_HandleTypeDef htim, uint16_t New_PSC);//设置分频值
void Set_PWM_ARR(TIM_HandleTypeDef htim, uint16_t New_ARR);//设置重装载值
void Set_Count(TIM_HandleTypeDef htim, uint16_t Count);//设置当前计数器
void Start_Count(TIM_HandleTypeDef htim)
{
HAL_TIM_Base_Start(&htim);
}
void Stop_Count(TIM_HandleTypeDef htim)
{
HAL_TIM_Base_Stop(&htim);
}
uint16_t Get_Count(TIM_HandleTypeDef htim)
{
return htim.Instance->CNT;
}
void Set_PWM_PSC(TIM_HandleTypeDef htim, uint16_t New_PSC)//注:16位寄存器
{
//__HAL_TIM_SET_PRESCALER(&htim3,,New_PSC);
__HAL_TIM_DISABLE(&htim);
htim.Instance->CNT=0;//首先将定时器失能并清空计数值
htim.Instance->PSC=New_PSC-1;
__HAL_TIM_ENABLE(&htim);
}
void Set_PWM_ARR(TIM_HandleTypeDef htim, uint16_t New_ARR)//注:16位寄存器
{
//__HAL_TIM_SET_PRESCALER(&htim3,,New_PSC);
__HAL_TIM_DISABLE(&htim);
htim.Instance->CNT=0;//首先将定时器失能并清空计数值
htim.Instance->ARR=New_ARR-1;
__HAL_TIM_ENABLE(&htim);
}
void Set_Count(TIM_HandleTypeDef htim, uint16_t Count)
{
__HAL_TIM_SET_COUNTER(&htim,Count);
}
一般操作:
- 首先在cubemx中开启定时器,选中使用内部时钟源;
- 开启定时器;
- 设置定时器分频和重装载值;
定时器产生PWM波(输出比较)
基本操作,通过定时器开启定时器通道输出,设置输出比较值CRR,通过cubemx中的设置可以确定当定时器的计数值小于比较值时输出高电平,大于时输出低电平,以此达到输出PWM波的效果。
有关函数
void Set_PWM_PSC(TIM_HandleTypeDef htim, uint16_t New_PSC);
void Set_PWM_ARR(TIM_HandleTypeDef htim, uint16_t New_ARR);
void Set_Count(TIM_HandleTypeDef htim, uint16_t Count);
void Start_PWM(TIM_HandleTypeDef htim, uint32_t Channel);
void Set_Compare(TIM_HandleTypeDef htim,uint32_t Channel,uint16_t compare);
部分函数与定时器基本操作重复,这里要着重指出几个公式,以便更好的配置PWM波
1.频率:Fre=72M/(PSC+1)/(ARR+1),注意寄存器中的值比实际值少1,因此就是总频率直接除以分频值和重装载值
2.占空比,占空比指的是高电平占整个周期的时间比例,定时器中的计数值也比真实值小1(由于计数值是从0开始而不是从1开始),Duty=(count1+1)/(count2+1)其中count1是在第一个下降沿时的计数器计数值,count2是在一个周期结束时计数器的计数值。
void Set_PWM_PSC(TIM_HandleTypeDef htim, uint16_t New_PSC)//注:16位寄存器
{
//__HAL_TIM_SET_PRESCALER(&htim3,,New_PSC);
__HAL_TIM_DISABLE(&htim);
htim.Instance->CNT=0;//首先将定时器失能并清空计数值
htim.Instance->PSC=New_PSC-1;
__HAL_TIM_ENABLE(&htim);
}
void Set_PWM_ARR(TIM_HandleTypeDef htim, uint16_t New_ARR)//注:16位寄存器
{
//__HAL_TIM_SET_PRESCALER(&htim3,,New_PSC);
__HAL_TIM_DISABLE(&htim);
htim.Instance->CNT=0;//首先将定时器失能并清空计数值
htim.Instance->ARR=New_ARR-1;
__HAL_TIM_ENABLE(&htim);
}
void Set_Count(TIM_HandleTypeDef htim, uint16_t Count)
{
__HAL_TIM_SET_COUNTER(&htim,Count);
}
void Start_PWM(TIM_HandleTypeDef htim, uint32_t Channel)
{
HAL_TIM_PWM_Start(&htim,Channel);
}
void Set_Compare(TIM_HandleTypeDef htim,uint32_t Channel,uint16_t compare)
{
__HAL_TIM_SET_COMPARE(&htim,Channel,compare);
}
使用时要注意一定要先调用PWM开启函数
定时器输入捕获和从模式选择
定时器的输入捕获模式:定时器可以配置某个通道为输入捕获模式,并输入某个通道产生的PWM波,在上升沿或下降沿进行捕获,需要注意的是,定时器的四个通道都具有输入捕获寄存器,当出现满足条件的上升沿或者下降沿时,定时器将此时计数器的数值储存进入寄存器中。
定时器的输入通道间接模式,定时器的通道一和通道二,通道三和通道四分别在内部连接,因此完全可以将定时器通道1定义为上升沿捕获,定时器通道2定义为下降沿捕获,这样就可以捕获整个PWM周期,从而对PWM的占空比进行计算。
定时器的间接触发,定时器的通道1和通道2可以作为从触发源,当定时器达到重装载值时触发模式,如将定时器计数值清零等。结合这个特点和间接通道模式,可以实现定时器频率和占空比的自动测量。
输入捕获操作函数:
void Start_Tim_Inputcapture(TIM_HandleTypeDef htim,uint32_t Channel)
{
HAL_TIM_IC_Start(&htim,Channel);
//这只是开启输入捕获,如果要开启中断,则加IT
}
{
uint16_t Get_Cap_Count(TIM_HandleTypeDef htim,uint32_t Channel)
{
return HAL_TIM_ReadCapturedValue(&htim,Channel);
}
uint16_t Get_Fre(void)
{
uint16_t Fre;
uint16_t count;
Start_Tim_Inputcapture(htim1,TIM_CHANNEL_1);
//清零
Start_Count(htim1);
count=Get_Cap_Count(htim1,TIM_CHANNEL_1);
Fre=1000000/(count+1);
return Fre;
}
uint16_t Get_Duty(void)
{
float CCR1;
float CCR2;
Start_Tim_Inputcapture(htim1, TIM_CHANNEL_2);
Start_Tim_Inputcapture(htim1, TIM_CHANNEL_1);
CCR1=Get_Cap_Count(htim1,TIM_CHANNEL_1);
CCR2=Get_Cap_Count(htim1,TIM_CHANNEL_2);
OLED_Printf(16,0,8,"CCR1:%f",CCR1);
OLED_Printf(32,0,8,"CCR2:%f",CCR2);
return (CCR2+1)/(CCR1+1)*100;
}
编码器模式
有关函数:
//开启定时器1的编码模式
void Encoder_Start(void)
{
HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
}