买了个Arduino的旋转编码器模块,合作STM32定时器的编码器形式完成了旋转视点以及圈数的计数。这种旋转编码器我能想到的实践运用场景暂时只要实体音量旋钮,鼠标的滚轮等,所以只完成了计数。阅览Arduino关于该编码器的介绍,该编码器还能够完成旋转的速度、加速度的核算。应该算是算法层级的吧,还没做到实践运用,暂时不深究,本篇仅仅对旋转编码器的原理以及STM32编码器接口形式的装备运用办法做个简介。
正文
编码器分类:
按作业原理:光电式、磁电式和触点电刷式;
按码盘的刻孔办法:增量式和肯定式两类;
这是从网上看到一个简介,只触摸过Arduino的编码器,其他暂未运用过。
Arduino的编码器归于增量式。它一共有5根线。别离为“CLK”、“DT”、“SW”、“+”、“GND”。
“+”、“GND”:勿用多说,VCC与GND,接至板子的VCC与GND即可。
“SW”:Arduino介绍说,当旋钮旋转完一圈时,该脚会放出一个电平跳变信号,相当于旋转编码器常说的“Z”信号,实践上我买的这个仅仅一个开关,即旋钮部分能够按下去(类似于汽车上的音量调理按钮),该接口会产生一个下降沿。然后由MCU去做相关处理。
“CLK”、“DT”:在该模块上显现的丝印名称为这两个,不明白为什么是这个丝印,应该实践对应于编码器常用的“A”、“B”信号吧,这两个信号的产生办法如下:
正旋:如上图当旋钮开端正向旋转时,“A”从低电平变为高电平,“B”坚持不变;当旋钮旋转到预订方位时,“A”保持为高电平,“B”然后跟着从低电平跳变到高电平。也就是说,正旋时,“A”总是先与“B”开端电平改变。
反旋:与正旋相反,“B”总是先与“A”开端电平改变。
所以在此处,丝印将该两个接线印成“CLK”、“DT”就让我有点困惑。也未找到相关材料,先暂时放放,下次有实践运用,就知道为什么了。
依据如上正旋反旋规则,就现已能够依据编码器输出的信息判别出编码器的旋转方向以及核算出其旋转视点了,详细做法如下:
将“CLk”、“DT”别离衔接至MCU的恣意具有外部中止的IO口,处理办法为:
将该两个IO口装备为双边缘外部中止。
当其间某个IO口检测到上升沿或许下降沿时,在中止函数内检测另一个IO口的电平状况。以正旋为例,正旋时,“A”先上升沿引起中止,得到的“A”、“B”的电平状况为“10”,紧接着,“B”上升沿,检测到“A”、“B”电平状况为“11”。
若一向正转,则“A”、“B”的电平状况为“10 – 11 – 01 – 00 – 10 – …”。
若一向回转,则“A”、“B”的电平状况为“01 – 11 – 10 – 00 – 01 – …”
以此,即可判别出该编码器的旋转方向,一起在“A”、“B”一起跳变完成后,即可依据编码器的旋转方向对编码器的旋转计数进行增减。
以上为运用外部中止办法处理旋转编码器的输出信息,当然,本篇要用到STM32定时器的接口形式,所以也就不会用以上的办法进行判别。那么定时器的接口形式是怎么对旋转编码器进行计数的呢?
其实原理相同,将旋转编码器的“CLK(A)”、“DT(B)”脚接入到TIMx的通道,将对应通道引脚装备为编码器接口形式,使能计数,然后STM32的值就会在硬件上依照上述规对计数器的值进行加减。
本试验接到的是STM32F103的“PB6(TIM4_CH1)”、“PB7(TIM4_CH2)”,详细装备如下:
装备IO口:
// GPIO// 使能对应的GPIO口时钟RCC_APB2PeriphClockCmd(Enc_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = Enc_CLK_GPIO_PIN | Enc_DAT_GPIO_PIN | Enc_SW_GPIO_PIN;// 该编码器模块现已做了外部上拉处理,配制成浮空输入即可GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Enc_GPIO_PORT, GPIO_InitStructure);
装备定时器根本单元:
// TIM4// PB6 ch1 A,PB7 ch2 // TIMxCLK = 36MHZRCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_DeInit(TIM4);
TIM_TimeBaseStructInit(TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
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_Falling, TIM_ICPolarity_Falling);
TIM_ICStructInit(TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;TIM_ICInit(TIM2, TIM_ICInitStructure);
铲除相关中止,以及铲除对应的计数器,并发动定时器:
// Clear all pending interruptsTIM_ClearFlag(TIM4, TIM_FLAG_Update);// 其实中止能够不必开,由于硬件自行对计数器进行加减。TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//Reset counterTIM4->CNT = 0;
TIM_Cmd(TIM4, ENABLE); //发动TIM4定时器
如若开了中止,中止处理函数为:
void TIM4_IRQHandler(void){
if(TIM4->SR0x0001)//溢出中止{
LED_Toggle(1);
}
TIM4->SR=~(10);//铲除中止标志位 }
主函数读取相应计数器值,并将其打印至串口:
int main(void) {// 读取计数器信息Enc0Pos = TIM_GetCounter(TIM4);// 取模2的原因是,两个引脚接到同一个定时器,每旋转一次会计数两次Enc0Pos /= 2;if(Enc0Pos != Enc_PinDATLast
{
Enc_PinDATLast = Enc0Pos; printf(Position = %d\n\r, Enc0Pos);
}
}
参阅文献:
Reading Rotary Encoders Contents.
Get Native 32Bit resolution for your encoder on STM32F4.
STM32定时器—正交编码器形式详解.
至此,记载结束
- STM32单片机中文官网
- STM32单片机官方开发工具
- STM32单片机参阅规划