TIM定时器相关
TIM定时器编码器接口模式CC1P极性问题
背景
使用TIM2/TIM3的编码器接口模式对平衡小车的左右电机上的AB相霍尔编码器采样,以实现读取点击转动速度、方向信息的功能。
减速电机的编码器是由一个霍尔传感器+铁氧体磁环组成的装置。霍尔传感器是根据霍尔效应制作的一个磁场检测开关。当有磁场接近时(磁场强度达到一定值后)霍尔传感器的信号线就变为高电平;如果此时把磁场移开,信号线又变为低电平。
当轴旋转时,固定在轴上面的磁环随之旋转,霍尔传感器附近产生了变化的磁场,这样 在霍尔传感器的信号引脚就可以输出高低电平的脉冲信号。
AB相编码器测量电机的速度和旋转位置,输出两路90°相位正交的脉冲,可测量出电机的转动方向和速度。
问题
由于两组霍尔编码器对称,因此会出现左右点击相同转向时,读取TIM的计数值一个为正,一个为负
对应代码如下
void Dri_TIM2_3_Init(void) {
RCC->APB1ENR |= (RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN);
RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN);
// AFIO重映射
AFIO->MAPR |= AFIO_MAPR_TIM2_REMAP_FULLREMAP;
AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP_PARTIALREMAP;
// 关闭JTAG 010
AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0;
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_1;
AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2;
// ===========GPIO输入 mode=00 cnf=01
GPIOA->CRH &= ~GPIO_CRH_MODE15;
GPIOA->CRH &= ~GPIO_CRH_CNF15_1;
GPIOA->CRH |= GPIO_CRH_CNF15_0;
GPIOB->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_MODE4 | GPIO_CRL_MODE5);
GPIOB->CRL &= ~(GPIO_CRL_CNF3_1 | GPIO_CRL_CNF4_1 | GPIO_CRL_CNF5_1);
GPIOB->CRL |= (GPIO_CRL_CNF3_0 | GPIO_CRL_CNF4_0 | GPIO_CRL_CNF5_0);
// ===========定时器基本配置
// 定时器溢出频率 72M / 7200 = 10kHz
TIM2->PSC = 1 - 1;
TIM2->ARR = 0xFFFF - 1;
TIM3->PSC = 1 - 1;
TIM3->ARR = 0xFFFF - 1;
// ===========编码器模式配置
TIM2->CCMR1 |= (TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0);
TIM2->CCMR1 &= ~(TIM_CCMR1_CC1S_1 | TIM_CCMR1_CC2S_1);
TIM2->CCER &= ~TIM_CCER_CC1P; // 输入信号不反转,TI1FP1=TI1
TIM2->CCER &= ~TIM_CCER_CC2P; // 输入信号不反转,TI2FP2=TI2
TIM2->SMCR |= TIM_SMCR_SMS_0;
TIM2->SMCR |= TIM_SMCR_SMS_1;
TIM2->SMCR &= ~TIM_SMCR_SMS_2;
TIM3->CCMR1 |= (TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0);
TIM3->CCMR1 &= ~(TIM_CCMR1_CC1S_1 | TIM_CCMR1_CC2S_1);
TIM3->CCER |= TIM_CCER_CC1P;
TIM3->CCER &= ~TIM_CCER_CC2P;
TIM3->SMCR |= TIM_SMCR_SMS_0;
TIM3->SMCR |= TIM_SMCR_SMS_1;
TIM3->SMCR &= ~TIM_SMCR_SMS_2;
// 使能计数器
TIM2->CR1 |= TIM_CR1_CEN;
TIM3->CR1 |= TIM_CR1_CEN;
}
void Int_HallEncoder_Init(void) { Dri_TIM2_3_Init(); }
/**
* @brief 获取霍尔编码器对应的计数值(霍尔编码器对接TIM编码器接口模式)
* 正数表示正转(前进)、负数表示反转(后退)
*
* @param hallSensor
* @return int16_t
*/
int16_t Int_HallEncoder_ReadCounter(HallSensor hallSensor) {
int16_t value = 0;
switch (hallSensor) {
case HALL_LEFT:
value = (int16_t)TIM2->CNT;
TIM2->CNT = 0;
break;
case HALL_RIGHT:
value = (int16_t)TIM3->CNT;
TIM3->CNT = 0;
break;
}
return value;
}
STM32 TIM编码器接口模式分析
以如下配置为例,给出计数值的示例图
极性反转
可以理解为将TI1的输入信号进行极性反转(相当于加了非门)作为TI1FP1