时序图
程序思路
把A端或B端充当时钟信号,可以上升沿或下降沿触发都ok利用触发后判断另一端是低电平还是高电平来判断顺时针还是逆时针中断尽量只处理标志位不然可能使程序不按照预设的进行
程序
#define EC11_ PAin(4)//按下
#define EC11B PAin(6)//用B高低电平判断旋转方向
#define EC11A PAin(5)//用A充当时钟信号
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //外部中断,需要使能AFIO时钟
//引脚初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;//PA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
//GPIOA.5 中断线以及中断初始化配置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler ( void )
{
if ( EC11A == 0 )
{
delay_ms ( 10 );
if ( EC11A == 0 && EC11B == 0 ) //逆时针
{
}
else if ( EC11A == 0 && EC11B == 1 ) //顺时针
{
}
//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
}
}
EXTI_ClearITPendingBit ( EXTI_Line5 ); //清除LINE5上的中断标志位
}
======================================================================================================================================================================================================================================================================================================================================================================================================================================================
程序强化:
误判①
误判②-①
展开细节发现具有3ms毛刺非常严重,因为没有在AB端加电容滤波的缘故吧,使用104p电容消除毛刺,加了电容后中断可以不适用1ms延时进行消抖,还有一个坑是写Flash会禁止进入外部中断的,要是每次检测完后就写一次Flash,然后快速连续地旋转旋钮会导致检测丢失导致误判。
,
误判②-②
展开细节发现毛刺抖动后1点多ms再来个下降沿造成的
unsigned char A_Trigger_Rising = 0;
unsigned char A_Trigger_Falling = 0;
unsigned char A_Trigger_Rising_Date = 0x88;//无数据为0x88
unsigned char B_Trigger_Falling_Date = 0x88;//无数据为0x88
unsigned char EC11Date = 0X00;//无数据为0x88
//中断服务函数
void EXTI9_5_IRQHandler ( void )
{
EC11Date = 0X00;
delay_ms ( 1 ); //*************延时重要必须延时*******************
if(EC11_A == 1)
{
A_Trigger_Rising = 1;
if(EC11_B)
A_Trigger_Rising_Date = 0XFF;
else
A_Trigger_Rising_Date = 0X00;
}
if(EC11_A == 0)
{
A_Trigger_Falling = 1;
if(EC11_B)
B_Trigger_Falling_Date = 0XFF;
else
B_Trigger_Falling_Date = 0X00;
}
if(A_Trigger_Rising && A_Trigger_Falling)
{
A_Trigger_Rising = 0;
A_Trigger_Falling = 0;
if(A_Trigger_Rising_Date == B_Trigger_Falling_Date)
{
;
}
else
{
if(A_Trigger_Rising_Date == 0XFF && B_Trigger_Falling_Date == 0X00)
{
EC11Date = 0XF0;
}
else if(A_Trigger_Rising_Date == 0X00 && B_Trigger_Falling_Date == 0XFF)
{
EC11Date = 0X0F;
}
}
A_Trigger_Rising_Date = 0x88;
B_Trigger_Falling_Date = 0x88;
}
//程序逻辑处理
if ( EC11Date == 0XF0 ){;}//累加
if ( EC11Date == 0X0F ){;}//累减
}
防止扭动过快人手不自觉倒退一格,程序在上一个程序基础增加检测标志位
unsigned char A_Trigger_Rising = 0;
unsigned char A_Trigger_Falling = 0;
unsigned char A_Trigger_Rising_Date = 0x88;//无数据为0x88
unsigned char B_Trigger_Falling_Date = 0x88;//无数据为0x88
unsigned char EC11Date = 0X00;//无数据为0x88
//中断服务函数
void EXTI9_5_IRQHandler ( void )
{
EC11Date = 0X00;
delay_ms ( 1 ); //*************延时重要必须延时*******************
if(EC11_A == 1)
{
A_Trigger_Rising = 1;
if(EC11_B)
A_Trigger_Rising_Date = 0XFF;
else
A_Trigger_Rising_Date = 0X00;
}
if(EC11_A == 0)
{
A_Trigger_Falling = 1;
if(EC11_B)
B_Trigger_Falling_Date = 0XFF;
else
B_Trigger_Falling_Date = 0X00;
}
if(A_Trigger_Rising && A_Trigger_Falling)
{
A_Trigger_Rising = 0;
A_Trigger_Falling = 0;
if(A_Trigger_Rising_Date == B_Trigger_Falling_Date)
{
;
}
else
{
if(A_Trigger_Rising_Date == 0XFF && B_Trigger_Falling_Date == 0X00)
{
EC11Date = 0XF0;
}
else if(A_Trigger_Rising_Date == 0X00 && B_Trigger_Falling_Date == 0XFF)
{
EC11Date = 0X0F;
}
}
A_Trigger_Rising_Date = 0x88;
B_Trigger_Falling_Date = 0x88;
}
//程序逻辑处理
if ( EC11Date == 0XF0 )
{//累加
if ( KeySubCnt1 == KeySubCnt2 )
{//程序内容...
KeyAddCnt1++;
}
}
if ( EC11Date == 0X0F )
{//累减
if ( KeyAddCnt1 == KeyAddCnt2 )
{//程序内容...
KeySubCnt1++;
}
}
}
//某某定时器中断 我这里是250ms中断一次
unsigned int KeyAddCnt1 = 0, KeySubCnt1 = 0;
unsigned int KeyAddCnt2 = 0, KeySubCnt2 = 0;
u8 kkk = 0;
void TIM2_IRQHandler ( void ) //TIM3中断
{
if ( TIM_GetITStatus ( TIM2, TIM_IT_Update ) != RESET ) //检查指定的TIM中断发生否:TIM 中断源
{
TIM_ClearITPendingBit ( TIM2, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
if ( ++kkk >= 1 )
{
//250ms
if ( KeyAddCnt1 != KeyAddCnt2 )
{
KeyAddCnt2 = KeyAddCnt1;
}
if ( KeySubCnt1 != KeySubCnt2 )
{
KeySubCnt2 = KeySubCnt1;
}
kkk = 0;
}
}
======================================================================================================================================================================================================================================================================================================================================================================================================================================================
误判转动无反应问题
unsigned char A_Trigger_Rising = 0;
unsigned char A_Trigger_Falling = 0;
unsigned char A_Trigger_Rising_Date = 0x88;//无数据为0x88
unsigned char B_Trigger_Falling_Date = 0x88;//无数据为0x88
unsigned char EC11Date = 0X00;//无数据为0x88
//中断服务函数
void EXTI9_5_IRQHandler ( void )
{
EC11Date = 0X00;
delay_ms ( 1 ); //*************延时重要必须延时*******************
if(EC11_A == 1)
{
A_Trigger_Rising = 1;
if(EC11_B)
A_Trigger_Rising_Date = 0XFF;
else
A_Trigger_Rising_Date = 0X00;
}
if(EC11_A == 0)
{
A_Trigger_Falling = 1;
if(EC11_B)
B_Trigger_Falling_Date = 0XFF;
else
B_Trigger_Falling_Date = 0X00;
}
if(A_Trigger_Rising && A_Trigger_Falling)
{
A_Trigger_Rising = 0;
A_Trigger_Falling = 0;
if(A_Trigger_Rising_Date == B_Trigger_Falling_Date)
{
if(A_Trigger_Rising_Date == 0X00)
{
EC11Date = 0XF0;
}
else if(A_Trigger_Rising_Date == 0XFF)
{
EC11Date = 0X0F;
}
}
else
{
if(A_Trigger_Rising_Date == 0XFF && B_Trigger_Falling_Date == 0X00)
{
EC11Date = 0XF0;
}
else if(A_Trigger_Rising_Date == 0X00 && B_Trigger_Falling_Date == 0XFF)
{
EC11Date = 0X0F;
}
}
A_Trigger_Rising_Date = 0x88;
B_Trigger_Falling_Date = 0x88;
}
//程序逻辑处理
if ( EC11Date == 0XF0 )
{//累加
if ( KeySubCnt1 == KeySubCnt2 )
{//程序内容...
KeyAddCnt1++;
}
}
if ( EC11Date == 0X0F )
{//累减
if ( KeyAddCnt1 == KeyAddCnt2 )
{//程序内容...
KeySubCnt1++;
}
}
}
//某某定时器中断 我这里是250ms中断一次
unsigned int KeyAddCnt1 = 0, KeySubCnt1 = 0;
unsigned int KeyAddCnt2 = 0, KeySubCnt2 = 0;
u8 kkk = 0;
void TIM2_IRQHandler ( void ) //TIM3中断
{
if ( TIM_GetITStatus ( TIM2, TIM_IT_Update ) != RESET ) //检查指定的TIM中断发生否:TIM 中断源
{
TIM_ClearITPendingBit ( TIM2, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
if ( ++kkk >= 1 )
{
//250ms
if ( KeyAddCnt1 != KeyAddCnt2 )
{
KeyAddCnt2 = KeyAddCnt1;
}
if ( KeySubCnt1 != KeySubCnt2 )
{
KeySubCnt2 = KeySubCnt1;
}
kkk = 0;
}
}