嵌入式系统中使用STM32计时器编码器接口模式的方法详解

文章目录

  • 前言
  • 一、编码器接口模式介绍
  • 二、固件库编程
  • 1. 定时器输入通道GPIO配置
  • 2. 定时器配置
  • 3. 注意事项
  • 三、硬件连接
  • 四、实验
  • 总结

  • 前言

    使用STM32调试电机或传感器时经常会使用到计数器的编码器接口模式,本文主要记录该模式的固件库配置方法,并给出使用该模式获取光栅测距值的实例。

    硬件:
    STM32F103C8T6
    光栅测距传感器


    一、编码器接口模式介绍

    编码器接口模式为STM32计时器的一种特殊使用模式,该模式下可对编码器输出的脉冲信号进行输入捕获,检测脉冲信号的上升沿和下降沿并进行计数,通过计数值获得增量式编码器当前指示的角度或位移。
    编码器输出的脉冲信号通常有A+/A-、B+/B-、Z+/Z-三组差分信号,其中A和B信号的跳变次数为传感器增量值A与B信号的相位差表征编码器数值上升或下降(位移的正反向,电机的正反转等)Z信号在每个编码周期产生一次脉冲,通常表示编码器计数圈数或电机机械零点
    编码器输出信号可通过RS422通信线进行传输(注意和422通信协议区分)。

    STM32的编码器接口模式专门为处理编码器的输出信号设计,将传感器输出的信号A和信号B分别连接到计时器输入捕获通道1和通道2,通过检测A、B信号的电平跳变进行计数,并通过判断电平跳变时另一信号的电平状态自动确定向上计数或向下计数(与相位判断结果相同),计数方向与编码器信号的关系如下图:

    上表中通道TI1和TI2分别与传编码器输出信号A、B连接,其可配置为仅在TI1跳变时计数仅在TI2跳变时计数在TI1和TI2跳变时均计数。下图展示了选择双边沿计数时的计数情况:

    二、固件库编程

    使用STM32F103C8T6进行程序开发,使用通用定时器2。

    1. 定时器输入通道GPIO配置

    static void General_Timner_GPIO_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	RCC_APB2PeriphClockCmd(TIMER2_CH2_GPIO_RCC|TIMER2_CH1_GPIO_RCC, ENABLE);
    	
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;						// 推挽复用
    	GPIO_InitStructure.GPIO_Pin = TIMER2_CH2_GPIO_PIN;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(TIMER2_CH2_GPIO_PORT, &GPIO_InitStructure);
    	
    	GPIO_InitStructure.GPIO_Pin = TIMER2_CH1_GPIO_PIN;
    	GPIO_Init(TIMER2_CH1_GPIO_PORT, &GPIO_InitStructure);
    }
    

    2. 定时器配置

    static void General_Timner_Mode_Config(void)
    {
    	RCC_APB1PeriphClockCmd(TIMER2_RCC, ENABLE); /* 开启TIM2时钟 72MHz*/
    
    	// TIM2时基配置------------------------------------------------------------------------
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    	TIM_TimeBaseInitStructure.TIM_Period = COUNTER_PERIOD;				// 计数周期,ARR自动重装载寄存器 65535
    	TIM_TimeBaseInitStructure.TIM_Prescaler = COUNTER_PSC;				// 预分频器,对时钟源信号分频得到计数频率
    	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数
    	TIM_TimeBaseInit(TIMER, &TIM_TimeBaseInitStructure);
    		
    	// TIM2输入通道配置--------------------------------------------------------------------
    	// TIM2_ch1
    	TIM_ICInitTypeDef  TIM_ICInitStructure;
    	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    	TIM_ICInitStructure.TIM_ICFilter = 5;								// 输入捕获滤波器
    	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;				// 1分频
    	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;		//通道直接连接
    	TIM_ICInit(TIMER, &TIM_ICInitStructure);
    	
    	// TIM1_ch2
    	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    	TIM_ICInit(TIMER, &TIM_ICInitStructure);
    	
    	// 编码器模式配置	双边沿计数	电平不反相
    	TIM_EncoderInterfaceConfig(TIMER, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
    	
    	// 使能计数器
    	TIM_Cmd(TIMER, ENABLE);
    }
    

    3. 注意事项

    计数周期配置为65535,计数重装载寄存器为16位,因此最大计数值为65535,本例中该计数值已满足使用要求(测距范围较小),因此没有做溢出处理。计数初始值为0,由于计数值可能递减(光栅反向运动),递减后计数值向下溢出,可将计数值转化为16位有符号整数,此时大于32767的数据被视为负数(最高位为1),正负号可直接表示运动方向。例如在计数值为0时产生反向脉冲,此时计数值向下溢出,为0xFFFF,为-1的补码。

    初始化时基时应配置计数器为向上计数(此时时基为编码器输出的信号),否则计数方向出错。

    配置输入捕获滤波器时,参照用户手册的描述:

    图中CK_INT为定时器时钟,为总线时钟经分频后的时钟,此处为72MHz。DTS为定时器时钟再次分频后得到的数字滤波器时钟,由于此处分频系数为1,所以DTS也为72MHz。
    当配置为5时,采样频率为72/2=36MHz,采样次数为8,当8次采样均为有效电平时才视为一次有效跳变,因此频率高于36/8=4.5MHz(有效电平持续时间低于1/4.5M=0.22us)的杂波将被滤除。查询光栅尺用户手册,其最小脉冲间隔为0.2微秒,即为5MHz,从而杂波被有效滤除。(滤波器错误配置将导致计数误差显著增加)

    三、硬件连接

    所使用开发板为自制STM32F103最小系统板,其片上所有IO引脚已将引出。本实验采用定时器2的输入通道1、输入通道2的默认GPIO引脚,PA0、PA1。
    光栅编码器采用RS422接口,输出A+/A-、B+/B-、Z+/Z-,3路差分信号,其中Z信号用于标记绝对零点和记录圈数,本实验只用到A、B两路差分信号。
    将A+端口与单片机PA0连接、B+端口与单片机PA1连接,A-和B-均与单片机GND相连。
    (线路连接之前先用示波器查看A、B端口是否正确输出脉冲信号)

    四、实验

    光栅编码器由检测头和光栅尺组成,检测头与光栅尺相对移动时,编码器产生脉冲信号,分辨率为1um。
    光栅传感器:

    通过串口调试助手将计数器数值打印到电脑,并与光栅传感器自带上位机获取的数据进行实时对比,二者数据完全相同,证明了STM32读取编码器脉冲信号的有效性。
    对比图(左侧为光栅自带上位机数据,右侧为STM32计数值):


    另可使用vofa软件进行波形可视化。


    总结

    STM32的编码器接口模式配置简单、有效,准确度较高,后续可以对该数据进一步处理,与光栅传感器自带上位机相比,数据处理更加灵活、高效!

    物联沃分享整理
    物联沃-IOTWORD物联网 » 嵌入式系统中使用STM32计时器编码器接口模式的方法详解

    发表评论