OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11373|回复: 6

关于外部中断

[复制链接]

10

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2012-6-13
在线时间
0 小时
发表于 2012-7-15 16:23:24 | 显示全部楼层 |阅读模式
背景:KEY1和KEY0分别控制一个LED灯,WA_UP控制两个灯全灭
外部中断会出现这样的问题:key1和key0按下时,我指的是一直按下,有的时候会出现灯一直闪烁的情况,有的时候灯会保持长亮或者灭掉非常稳定
没有找到具体规律。如果按下后中断清零,不应该出现一直按下,有的时候会出现灯一直闪烁的情况。寻求原因,谢谢
#include <stm32f10x_lib.h>
#include <sys.h>
#include <usart.h>
#include <delay.h>
    void EXTI15_10_IRQHandler(void)
            {       
                    if((GPIOA->IDR&0x8000)==0)         //PA15,有键KEY1按下
                                { 
                                    delay_ms(30);
                                    if((GPIOA->IDR&0x8000)==0)
                                            {   
                                                PAout(8)=~PAout(8);          //PA8输出为0     ,led点亮
                                                EXTI->R=1<<15;//      写入1清除
                                            }   
                                }
                    if((GPIOA->IDR&0x2000)==0)         //PA13,有键KEY0按下
                           
                                {   
                                    delay_ms(30);
                                    if((GPIOA->IDR&0x2000)==0)
                                            { 
                                            PDout(2)=~PDout(2);       //PD2输出为0     ,led点亮
                                            EXTI->R=1<<13;//      写入1清除
                                            }
                                }     
                             
                   
            }
    void EXTI0_IRQHandler(void)   
        {
                    if((GPIOA->IDR&0x0001)==1)            //PA0为输入,按下键WA_UP接高电平
                    {
                        delay_ms(30);
                          if((GPIOA->IDR&0x0001)==1) 
                                    {
                                   
                                     GPIOD->ODR|=0x00000004;         //PD2输出高,关闭LED
                                     GPIOA->ODR|=0x00000100;         //PA8输出高,关闭LED
                                     EXTI->R=1<<0;//      写入1清除
                                    }
                    }
        }
main()
{  Stm32_Clock_Init(9);//系统时钟设置
    delay_init(72);//延时初始化
    JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD
    RCC->APB2ENR|=1<<2;//使能PORTA时钟
    RCC->APB2ENR|=1<<5;//使能PORTD时钟
    RCC->APB2ENR|=0x0001;//使能辅助功能IO时钟
    GPIOA->CRH&=0xFF0FFFFF;
    GPIOA->CRH|=0X00800000;//设定PA13为输入
    GPIOA->ODR&=0x0000DFFF;
    GPIOA->ODR|=0x00002000;    //设定为输入上拉

    GPIOA->CRH&=0x0FFFFFFF;
    GPIOA->CRH|=0X80000000;//设定PA15为输入
    GPIOA->ODR&=0x00007FFF;
    GPIOA->ODR|=0x00008000;    //设定为输入上拉
    AFIO->EXTICR[3]&=0x0FFF;//选择PA13,PA15为外部中断输入源
       AFIO->EXTICR[3]&=0xFF0F;//选择PA13,PA15为外部中断输入源

    GPIOA->CRL&=0xFFFFFFF0;
    GPIOA->CRL|=0X00000008;//设定PA0为输入
    GPIOA->ODR&=0x0000FFFE;
    GPIOA->ODR|=0x00000000;    //设定输入下拉
    AFIO->EXTICR[0]&=0xFFF0;//选择PA0为外部中断输入源
    EXTI->IMR=0XA001;//使能线15,线13,线0中断输入
    EXTI->EMR=0X0000; //屏蔽线15,线13,线0事件请求
    EXTI->FTSR=0XA000;//使能线15,线13上的下降沿触发
    EXTI->RTSR=0x0001;//使能线0上的上升沿触发

    GPIOA->CRH&=0xFFFFFFF0;
    GPIOA->CRH|=0X00000003;//设定PA8为输出,连接LED
    GPIOA->ODR&=0x0000FEFF;
    GPIOA->ODR|=0x00000100;    //设定输出高

    GPIOD->CRL&=0xFFFFF0FF;
    GPIOD->CRL|=0X00000300;//设定PD2为输出,连接LED
    GPIOD->ODR&=0x0000FFFB;
    GPIOD->ODR|=0x00000004;    //设定输出高
    MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2
    MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2
  while(1)
  {           
    delay_ms(10);   
    }   
}                                          


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-15 19:04:17 | 显示全部楼层
可能是按下抖动造成的.
按不太稳,导致不停的按下松开,按下松开,就出现流水灯了...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

10

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2012-6-13
在线时间
0 小时
 楼主| 发表于 2012-7-15 22:00:38 | 显示全部楼层
我敢肯定这个不是由于按键不稳造成的,因为这个我反复试过,但是具体什么原因我也找不出。
对应着触摸屏程序,我的本意是想按一下屏幕,产生外部中断,标志adjust_flag加1,现在用JTAG调试发现,每按一下adjust_flag回一直往上加,一直加到4变成0为止
//开启pen上的外部中断
void pen_int(u8 x)
{
if(x==1)
{
EXTI->IMR=1<<1;//使能line1上的中断请求
EXTI->EMR=0<<1;//屏蔽line1上的事件请求
EXTI->FTSR=1<<1;//允许下降沿触发
}
else EXTI->IMR=0<<1;//关闭line1上的中断请求
}
//产生中断
u16 adjust_flag=0;
void EXTI1_IRQHandler()

if(key_flag==1)
{
EXTI->R=1<<1;  //清除LINE1上的中断标志位
pen_int(0);
adjust_flag++;
if(adjust_flag==4)
adjust_flag=0;
}                
touch_sc=1;//触摸屏被按下 
EXTI->R=1<<1;  //清除LINE1上的中断标志位
}
回复 支持 反对

使用道具 举报

9

主题

45

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2012-7-10
在线时间
0 小时
发表于 2012-7-15 22:17:40 | 显示全部楼层
       这两天我正好也在写外部中断,用的也是按键点亮LED小灯,你小灯的触发用的是中断方式,那在中断函数中,直接处理点亮灯岂不是更好?为什么在中断里面还要查询一下呢?
                    if((GPIOA->IDR&0x8000)==0)         //PA15,有键KEY1按下
                                {  
                                    delay_ms(30);
                                    if((GPIOA->IDR&0x8000)==0) 
                                            {    
                                                Aout(8)=~PAout(8);          //PA8输出为0     ,led点亮
                                                EXTI->R=1<<15;//      写入1清除
                                            }    
                                }
                    if((GPIOA->IDR&0x2000)==0)         //PA13,有键KEY0按下
                            
                                {    
                                    delay_ms(30);
                                    if((GPIOA->IDR&0x2000)==0)
                                            {  
                                            Dout(2)=~PDout(2);       //PD2输出为0     ,led点亮
                                            EXTI->R=1<<13;//      写入1清除
                                            }
                                }    

        按键触发还进行消抖是为什么?这样处理会不会就出现你的现象,你把消抖处理去掉,试试程序?
千人千般苦,苦苦不相同!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-15 23:09:33 | 显示全部楼层
回复【3楼】zhengchao20105:
---------------------------------
把你的清除中断标记放到最外层试试.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

10

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2012-6-13
在线时间
0 小时
 楼主| 发表于 2012-7-15 23:11:14 | 显示全部楼层
回复【4楼】爱学习的小妞:
---------------------------------
之所以一直按键会出现灯闪烁的状况是因为if((GPIOA->IDR&0x8000)==0)         //PA15,有键KEY1按下
                                { 
                                    delay_ms(30);
                                    if((GPIOA->IDR&0x8000)==0) 
我给灯的状态转换时间改成了30ms,这样如果一直按键,会发现闪烁,改成10ms后闪烁小时

进入中断后再给出10ms的消抖时间是必要的,放置按键初期就马上进入外部中断
回复 支持 反对

使用道具 举报

10

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2012-6-13
在线时间
0 小时
 楼主| 发表于 2012-7-15 23:20:52 | 显示全部楼层
如果我把程序改成现在这样,软件仿真的结果如图片所示,发现如果按键一直按下,他并没有执行一次就完事,而是一直在执行
把EXTI->R=1<<15; EXTI->R=1<<13;拿到外面就会正常,为什么会这样,在里面的时候也已经清除中断了呀
void EXTI15_10_IRQHandler(void)
            {       
            if((GPIOA->IDR&0x2000)==0)
                    {delay_ms(10);       
                    if((GPIOA->IDR&0x2000)==0) //PA13,有键KEY0按下
                        { 
                        PDout(2)=~PDout(2);       //PD2输出为0     ,led点亮
                        delay_ms(100);
                         EXTI->R=1<<15;//      写入1清除
                        }
                    }
                if((GPIOA->IDR&0x8000)==0)
                {  delay_ms(10);
                    if((GPIOA->IDR&0x8000)==0)         //PA15,有键KEY1按下
                               
                        {   
                            PAout(8)=~PAout(8);          //PA8输出为0     ,led点亮   
                            EXTI->R=1<<13;//      写入1清除
                        }
                }
               
                                        
            }




回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-22 12:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表