STM32开发问题记录(踩坑集锦)


TIM定时器相关

TIM定时器编码器接口模式CC1P极性问题

背景

使用TIM2/TIM3的编码器接口模式对平衡小车的左右电机上的AB相霍尔编码器采样,以实现读取点击转动速度、方向信息的功能。

image-20241226221641860

image-20241226221751893

image-20241226221925610

image-20241227090001295

减速电机的编码器是由一个霍尔传感器+铁氧体磁环组成的装置。霍尔传感器是根据霍尔效应制作的一个磁场检测开关。当有磁场接近时(磁场强度达到一定值后)霍尔传感器的信号线就变为高电平;如果此时把磁场移开,信号线又变为低电平。

当轴旋转时,固定在轴上面的磁环随之旋转,霍尔传感器附近产生了变化的磁场,这样 在霍尔传感器的信号引脚就可以输出高低电平的脉冲信号。

image-20241227090006898

AB相编码器测量电机的速度和旋转位置,输出两路90°相位正交的脉冲,可测量出电机的转动方向和速度。

问题

由于两组霍尔编码器对称,因此会出现左右点击相同转向时,读取TIM的计数值一个为正,一个为负

image-20241226222445286

对应代码如下

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编码器接口模式分析

image-20241226224211446

以如下配置为例,给出计数值的示例图

image-20241226225328465

image-20241226224506609

极性反转

可以理解为将TI1的输入信号进行极性反转(相当于加了非门)作为TI1FP1

image-20241226224644600

image-20241226225928689

image-20241226225126915

image-20241226225227238

DMA相关

DMA中断太频繁导致程序无法执行

image-20241229215335401


文章作者: 安文
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 安文 !
  目录