当前位置:首页 > 单片机 > 单片机
[导读]车轮位置的确定是在制作小车的过程中必不可少的部件,好在STM32中包含了硬件的编码器。但使用的过程中却存在诸多不方便。下面由我一一道来:1。编码器原理什么是正交?如果两个信号相位相差90度,则这两个信号称为正

车轮位置的确定是在制作小车的过程中必不可少的部件,好在STM32中包含了硬件的编码器。但使用的过程中却存在诸多不方便。下面由我一一道来:
1。编码器原理
什么是正交?如果两个信号相位相差90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、根据每个信号脉冲数量的多少及整个编码轮的周长就可以算出当前行走的距离、如果再加上定时器的话还可以计算出速度。
2。为什么要用编码器

从上图可以看出,由于TI,T2一前一后有个90度的相位差,所以当出现这个相位差时就表示轮子旋转了一个角度。但有人会问了:既然都是脉冲,为什么不用普通IO中断?实际上如果是轮子一直正常旋转当然没有问题。仔细观察上图,如果出现了毛刺呢?这就是需要我们在软件中编写算法进行改正。于是,我们就会想到如果有个硬件能够处理这种情况那不是挺好吗?
3. STM32编码器

还是刚才那张图,但这时候我们看到STM32的硬件编码器还是很智能的,当T1,T2脉冲是连续产生的时候计数器加一或减一一次,而当某个接口产生了毛刺或抖动,则计数器计数不变,也就是说该接口能够容许抖动。在STM32中,编码器使用的是定时器接口,通过数据手册可知,定时器1,2,3,4,5和8有编码器的功能,而其他没有。编码器输入信号TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。如果用的是定时器3,则对应的引脚是在PA6和PA7上。根据stmn32手册上编码器模式的说明,有6中组合计数方式,见下表。

由此可知,通过选择可以确定使用定时器的哪种方式来得到我们所要的结果。STM32编码器的使用也非常简单,其基本步骤和开发STM32其他部件的操作一致,都是打开时钟,配置接口,配置模式,如果要用中断则打开中断。具体可以参考以下代码(这里使用的是TIM4,引脚采用GPIOA 11和GPIOA12):
bool EncodeInit(u8 none1,u32 period)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDefEXTI_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//??TIM3??
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//??GPIOA??

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_10);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_10);



TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // No prescaling
TIM_TimeBaseStructure.TIM_Period = 1333;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM4, &TIM_ICInitStructure);

// Clear all pending interrupts
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

//Reset counter
TIM_SetCounter(TIM4,0);
TIM_Cmd(TIM4, ENABLE);

return 0;
}

4。编码器的中断
由于编码器是基于定时器的,所以编码器的中断实际上就是定时器的中断啦。也就是说定时器是每隔一定时间加一个数(或减一个数 ),当数到达预设值时就产生中断,而编码器是每一个有效脉冲就加一个数(或减一个数 ),当数到达预设值时就产生中断。若预设值为1000则编码器与定时器中断不同的是,当编码器反转时值到达999产生一次中断,而当编码器正转到达0时同样产生一次中断。在硬件上这两个中断是没法区分的,这也就造成了有种情况的误判。(后面再说)

5。STM32编码器没有考虑的情况
想象一下,如果编码器的预设值为1000,当某次我们使得编码器正转产生中断后,立即反转则又该怎么办呢?根据上面的说法,这时候会产生两次一样的中断。如果在算法上没有处理的话,极有可能认为是行走了两次正向。但实际上并没有。所以这个时候必须结合方向来判断行走的情况(判断方向使用的是DIR寄存器位)或者在产生中断后读一次count寄存器位(看看是999还是0,以此来判断当前的方向)。只有上一次为正且这一次同样为正,距离才是相加的。
具体中断处理函数代码如下:
void TIM4_IRQHandler(void)
{
temp=(TIM_GetCounter(TIM4)&0xffff);
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
if(temp==9999)
{
count--;
if(predir==0)//只有当前一次是负向走,这一次还是负向走才上传数据
{
upcount--;

}else{
predir=0;//表示往负向走
}
}else if(temp==0)
{
count++;
if(predir==1)//只有当前一次是正向走,这次又是正向走才上传数据
{
upcount++;
}else{
predir=1;//表示往正向走
}
}

}


TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}else{
#ifdef DEBUG
printf("ENCODE TIMER INTERRUP ERROR! n");
#endif
while(1)
{
;
}
}
6.最后一个问题
那么如果当前并没有到一个中断怎么办?难道这个时候就不能得到编码器的精确位置了吗?
其实只是个非常简单的算法:
u32 EncodeGetMileage(u8 none1,u8 none2)
{
u8 i=0;
temp=(TIM_GetCounter(TIM4)&0xffff);
if(count<0)
{
temp_mileage=(abs(count)-1)*1000 +(1000-temp);

}else{
temp_mileage=count*1000 +temp;
}
}

return temp_mileage; //返回编码器的脉冲个数,一个脉冲相当于125/1333 mm,这个返回值用于本次里程的计算,给总里程用
}
每次把中断的次数记录下来,然后再把距离上次中断共走了多少个脉冲,再把两者相加即可。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭