stm32编码器模式


选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的
SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1TI2边沿计数,则
SMS=011

TI1FP1TI2FP2
TI1TI2在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则TI1FP1=TI1
TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号
的跳变顺序,计数器向上或向下计数,同时硬件对
TIMx_CR1寄存器的DIR位进行相应的设置。
不管计数器是依靠
TI1计数、依靠TI2计数或者同时依靠TI1TI2计数,在任一输入端(TI1或者
TI2)的跳变都会重新计算DIR位。
编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在
0
TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0ARR计数,或是ARR0
)。所以在开始计数之前必须配置TIMx_ARR;同样,捕获器、比较器、预分频器、重复计数
器、触发输出特性等仍工作如常。编码器模式和外部时钟模式
2不兼容,因此不能同时操作。
在这个模式下,计数器依照增量编码器的速度和方向被自动的修改,因此计数器的内容始终指
示着编码器的位置。计数方向与相连的传感器旋转的方向对应。下表列出了所有可能的组合,
假设
TI1TI2不同时变换
73 计数方向与编码器信号的关系
226/754

相对信号的电平
(TI1FP1对应TI2,
TI2FP2
对应TI1)
TI1FP1信号 TI2FP2信号 有效边沿
上升 下降 上升 下降
向下计数 向上计数 不计数 不计数 仅在TI1计数
向上计数 向下计数 不计数 不计数
不计数 不计数 向上计数 向下计数 仅在TI2计数
不计数 不计数 向下计数 向上计数
向下计数 向上计数 向上计数 向下计数 TI1TI2上计数
向上计数 向下计数 向下计数 向上计数

一个外部的增量编码器可以直接与 MCU 连接而不需要外部接口逻辑。但是,一般会使用比较器
将编码器的差动输出转换到数字信号,这大大增加了抗噪声干扰能力。编码器输出的第三个信
号表示机械零点,可以把它连接到一个外部中断输入并触发一个计数器复位。
下图是一个计数器操作的实例,显示了计数信号的产生和方向控制。它还显示了当选择了双边
沿时,输入抖动是如何被抑制的;抖动可能会在传感器的位置靠近一个转换点时产生。在这个
例子中,我们假定配置如下:
CC1S=’01’ (TIMx_CCMR1 寄存器, IC1FP1 映射到 TI1)
CC2S=’01’ (TIMx_CCMR2 寄存器, IC2FP2 映射到 TI2)
CC1P=’0’ (TIMx_CCER 寄存器, IC1FP1 不反相, IC1FP1=TI1)
CC2P=’0’ (TIMx_CCER 寄存器, IC2FP2 不反相, IC2FP2=TI2)
SMS=’011’ (TIMx_SMCR 寄存器,所有的输入均在上升沿和下降沿有效 ).
CEN=’1’ (TIMx_CR1 寄存器,计数器使能 )
91 编码器模式下的计数器操作实例


下图为当
IC1FP1极性反相时计数器的操作实例(CC1P=’1’,其他配置与上例相同)
92 IC1FP1反相的编码器接口模式实例


当定时器配置成编码器接口模式时,提供传感器当前位置的信息。使用第二个配置在捕获模式
的定时器,可以测量两个编码器事件的间隔,获得动态的信息
(速度,加速度,减速度)。指示机
械零点的编码器输出可被用做此目的。根据两个事件间的间隔,可以按照固定的时间读出计数
器。如果可能的话,你可以把计数器的值锁存到第三个输入捕获寄存器
(捕获信号必须是周期的
并且可以由另一个定时器产生
);也可以通过一个由实时时钟产生的DMA请求来读取它的值。

eg:

编码器A相接PB6,B相接PB7


#define ENCODENU 65536

void time4IOInit()

{
GPIO_InitTypeDef        GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //①使能 GPIOB 时钟

GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6 | GPIO_Pin_7; //PB6 7 设置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 

GPIO_Init(GPIOB, &GPIO_InitStructure); 
}


void time4CountInit()
{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   //使能 TIM4 时钟
TIM4->ARR = ENCODENU-1;                                                                    //设定计数器重装值(因为没有使用更新中断所以将计数器设最大值,保证1s延时不会溢出)   
TIM4->PSC  = 0;                                                                                          //预分频器
TIM4->CR1 &=~(3<<8);                                                                              // 选择时钟分频:不分频
TIM4->CR1 &=~(3<<5);                                                                              //边沿对齐(根据dir位向上或者向下计数)
        //定时器4配置成编码器模式,双边沿触发
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);
TIM_SetCounter(TIM4, 0);                                                                       //计数器清零
}

void encoderConfig()
{
        time4IOInit();
time4CountInit();
TIM_Cmd(TIM4, ENABLE);  //计数器使能,开始工作

}

void main () 
{
int dir=0;
u16 nu=0;
encoderConfig();
for (;;) 
       {


dir=(TIM4->CR1 & 0x0010)>4;                                                     //取方向标志位
if(dir > 0){                                                                                         //向下计数
 nu = (ENCODENU-TIM_GetCounter(TIM4))/4;                  //除以4是因为一对脉冲计数器计数4次
         FG_Print("down ; TIM_GetCounter=%d  \r\n",nu*60/1000);//(*60是因为延时1s转换成一分钟,/1000是因为编码器转一圈是1000个脉冲)
}else{                                                                                              //向上计数
  nu = TIM_GetCounter(TIM4)/4;                              
          FG_Print("up ; TIM_GetCounter=%d  \r\n",nu*60/1000);
}


TIM_SetCounter(TIM4, 0);
osDelay(1000);
}
}

猜你喜欢

转载自blog.csdn.net/jf_xu/article/details/79814616