历史上的今天
今天是:2025年08月14日(星期四)
2019年08月14日 | 基于stm32单片机的Grayhill编码器/开关软件设计
2019-08-14 来源:eefocus
1、初识编码器,像示波器的旋转按钮,可左旋右旋,还可以按下,我们使用的是Grayhill编码器,如下图所示:

从图中可以看出,该编码器一共有6个IO,从1-6分别为GND,GND,C,B,A,VCC,。
其中VCC和GND接3.3V和GND,A、B对应旋转时电平的跳变IO,C对应按下时电平的跳变IO。
(1) 硬件电路设计上,为了方便代码编写与理解,最好把编码器的A、B接到单片机相邻的GPIO中,即使用同一个中断处理函数,比如本设计A、B分别接到PB12和PB11。C接任一个GPIO,当成中断使用。
(2) 顺时针和逆时针旋转编码器时,慢慢旋转一个单位(手指头会有明显旋转到位的感觉),用万用表测量A、B对应的IO电平,并记录下来。旋转一圈为止。如下表是我使用的编码器,在顺、逆时针旋转一圈时所记录下的IO电平(旋4次即满一圈):
(实际使用中,旋转了24小格才满一圈,这里只记录方法,不记录确切的值,需要自己测量)
2、A、B对应的IO初始化成中断双边沿触发方式,如下所示:
void KeyA_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTI_PB1 Clock */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12); //配置PB12管脚为外部中断线路用
EXTI_InitStructure.EXTI_Line = EXTI_Line12; //配置为外部中断线2
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //配置为中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //输入线路下降沿为中断请求
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC_Group:先占优先级2位,从优先级2位
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //配置为外部中断2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_Init(&NVIC_InitStructure);
}
void KeyB_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTI_PB1 Clock */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); //配置PB11管脚为外部中断线路用
EXTI_InitStructure.EXTI_Line = EXTI_Line11; //配置为外部中断线11
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //配置为中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //输入线路下降沿为中断请求
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC_Group:先占优先级2位,从优先级2位
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //配置为外部中断2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_Init(&NVIC_InitStructure);
}
3、根据表1设计的中断处理函数如下所示,使用TurningDir变量来标识检测到的旋转方向,TurnLeft表示逆时针(对应数值可以理解为减),TurnRight表示顺时针(对应数值可以理解为加):
typedef enum {TurnNone=0,TurnRight , TurnLeft}TurnDir ;
TurnDir TurningDir=TurnNone;//default turning dir = none
void EXTI15_10_IRQHandler(void)
{
u8 KeyAValue=0;
u8 KeyBValue=0;
//key left & right
if (EXTI_GetITStatus(EXTI_Line12) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line12);
KeyAValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12);
KeyBValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
// printf("AB=%d,%drn",KeyAValue,KeyBValue);
if(KeyAValue==1)
{
if(KeyBValue==0)
{
TurningDir=TurnLeft;
}
else
{
TurningDir=TurnRight;
}
}
else if(KeyAValue==0)
{
if(KeyBValue==1)
{
TurningDir=TurnLeft;
}
else
{
TurningDir=TurnRight;
}
}
}
if (EXTI_GetITStatus(EXTI_Line11) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line11);
KeyAValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12);
KeyBValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
if(KeyBValue==1)
{
if(KeyAValue==0)
{
TurningDir=TurnRight;
}
else
{
TurningDir=TurnLeft;
}
}
else if(KeyBValue==0)
{
if(KeyAValue==1)
{
TurningDir=TurnRight;
}
else
{
TurningDir=TurnLeft;
}
}
}
}
编码器旋钮的按下功能,即C,可以把它当成一个普通的按键,软件设置成上拉输入,按下时为低电平,弹起时为高,同样也使用中断操作,这里就不再描述。
至此,编码器软件设计完成。经过实测,能完美检测左旋右旋。
史海拾趣
|
--8位10进制频率计 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ftctrl3 is port(clkk:in std_logic; cnt_en:out std_log ...… 查看全部问答> |
|
最近在看6410的串口驱动,看得一头雾水,希望各位大侠传授点经验,这个方面应该怎么看,一般要看到什么程度? 有关mdd层和pdd层的驱动程序怎么处理?还是只要看BSP中的seriar的程序?… 查看全部问答> |
|
在一个小系统中调试发现,如果在时钟初始化中里把AFIO打开,那么USART2就进入不了接收中断,关闭AFIO后,USART2接 ...… 查看全部问答> |
|
什么是伺服控制系统,衡量伺服控制系统性能的主要指标系统精度、稳定性、响应特性、工作频率四大方面,特别在频带宽度和精度方面。频带宽度简称带宽,由系统频率响应特性来规定,反映伺服系统的跟踪的快速性。带宽越大,快速性越好。伺服系统 ...… 查看全部问答> |
|
这不是一个单纯的 为论坛提出BUG什么的帖子。 这只是一个实践,一个关于测试的实践。 我很久没打开个人空间了,无意打开,发现了这个新功能。 叫 碎碎念一下 是个小问答。挺有爱的,我就试试咯 结果至今尚未成功过一次。 于是我想到,给这个小 ...… 查看全部问答> |
|
在我的开发板上,eeprom使用的是i2c1接口,内核版本是linux3.2,问题如下 : [ 1.496795] omap_i2c omap_i2c.2: Arbitration lost [ 2.513793] omap_i2c omap_i2c.2: timeout waiting for bus ready root@am335x-evm:~# i2cdetect -r 2 WARNING! ...… 查看全部问答> |




