定时器的三个女朋友
框图
PWM输出
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=(100-1);
//最后PWM输出频率为10KHZ
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= (72-1);
//1MHZ 也就是一微秒CNT加一
/* Set the Autoreload value */
TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
/* Set the Prescaler value */
TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
/* Set the Capture Compare1 Register value */
TIMx->CCR1 = Compare1;
}
CNT寄存器加一的时间由PSC分频寄存器决定,其重装载由ARR寄存器决定。
CCR1控制器着PWM的输出占空比,但它的取值受限于ARR寄存器的值,不能大于ARR寄存器的值,也可以说ARR寄存器的取值就是一个周期。
PWM的输出频率可根据实际情况进行设置,比如PWM输出控制电机,咱们就可以把PWM输出频率设置为10KHZ,这里的周期是100us。
输入捕获
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=(65535-1)
//最多计910微秒 最低1khz;
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= (1-1);
//72MHZ 也就是1/72MHZ秒加一 0.01388微秒CNT加一
输入捕获的频率要比待测频率要小,预分频尽可能小,这样处理数据精准,但进行中断捕获时注意中断函数处理,因为处理频率较高的信号会一直进中断。
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
/* Get the Capture 1 Register value */
return TIMx->CCR1;
}
这里输入捕获的值也是CCR1寄存器的值,捕获的值不大于ARR寄存器的值。
编码器模式(正交解码)
#define ENCODER_RESOLUTION 11 /*编码器一圈的物理脉冲数*/
#define ENCODER_MULTIPLE 4 /*编码器倍频,通过定时器的编码器模式设置,也就是正交解码,4个小上升沿才算一个大上升沿*/
#define MOTOR_REDUCTION_RATIO 34 /*电机的减速比*/
/*电机转一圈总的脉冲数(定时器能读到的脉冲数) = 编码器物理脉冲数*编码器倍频*电机减速比 */
#define TOTAL_RESOLUTION ( ENCODER_RESOLUTION*ENCODER_MULTIPLE*MOTOR_REDUCTION_RATIO )
//这里的脉冲数与硬件相关,
TIM_TimeBaseStructure.TIM_Period=(65535-1)
//这里表示脉冲最大个数,这里可以设置为最大,也可以设置为TOTAL_RESOLUTION(1496) ,也就是CNT计数到1496进入中断,表示一圈。
TIM_TimeBaseStructure.TIM_Prescaler= (1-1);
//72MHZ 也就是1/72MHZ秒加一 0.01388微秒CNT加一
// 读取定时器计数值
static int read_encoder(void)
{
int encoderNum = 0;
encoderNum = (int)((int16_t)(TIM4->CNT)); /*CNT为uint32, 转为int16*/
TIM_SetCounter(TIM4, CNT_INIT);/*CNT设初值*/
return encoderNum;
}
//计算电机转速(被另一个定时器100ms调用1次)
void calc_motor_rotate_speed()
{
int encoderNum = 0;
float rotateSpeed = 0;
/*读取编码器的值,正负代表旋转方向*/
encoderNum = read_encoder();
/* 转速(1秒钟转多少圈)=单位时间内的计数值/总分辨率*时间系数 */
rotateSpeed = (float)encoderNum/TOTAL_RESOLUTION*10;
//rotateSpeed = (float)(encoderNum*10)/TOTAL_RESOLUTION;
printf("encoder: %d\t speed:%.2f rps\r\n",encoderNum,rotateSpeed);
}
//计算电机转速(被另一个定时器1s调用1次)
void calc_motor_rotate_speed()
{
int encoderNum = 0;
float rotateSpeed = 0;
/*读取编码器的值,正负代表旋转方向*/
encoderNum = read_encoder();
/* 转速(1秒钟转多少圈)=单位时间内的计数值/总分辨率*时间系数 */
rotateSpeed = (float)encoderNum/TOTAL_RESOLUTION;
printf("encoder: %d\t speed:%.2f rps\r\n",encoderNum,rotateSpeed);
}