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,可以把它当成一个普通的按键,软件设置成上拉输入,按下时为低电平,弹起时为高,同样也使用中断操作,这里就不再描述。
至此,编码器软件设计完成。经过实测,能完美检测左旋右旋。
上一篇:MDK5+CH340驱动安装
下一篇:STM32学习记录之cubemx配置IIC+逻辑分析仪的学习
推荐阅读最新更新时间:2024-11-17 13:07
设计资源 培训 开发板 精华推荐
- 使用 ROHM Semiconductor 的 BA30BC0WT 的参考设计
- LTC2908IDDB-B1、3.3V、2.5V、1.8V、1.2V四路电源监视器的典型应用电路
- 使用 Analog Devices 的 AD9154BCPZ 的参考设计
- LM358ADR2G 函数发生器运算放大器的典型应用
- 用于高稳定性稳压器的 Sg137A 1.5 安培负可调稳压器的典型应用
- LT3710EFE LT3781EG LTC1698EGN 演示板,双路输出隔离电源,36V 至 72V 输入,3.3Vout @ 10A,1.8/2.5Vout @ 10A
- MAXREFDES27#:IO-LINK接近检测光传感器
- 51爱心灯
- 基于 L6902D 的 STEVAL-ISA155V1、1A 恒流 DC/DC 转换器评估板
- LT1172IN8、-10 至 -26/1.25A LCD 对比度电源的典型应用