打印
[菜农助学交流]

M0助学板学习第四帖:外部中断回调实验(库函数)

[复制链接]
3674|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mcsgy|  楼主 | 2011-9-25 23:53 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 mcsgy 于 2011-9-25 23:55 编辑

(一)硬件电路:
                   很简单就是两个按键连接到MCU的中断,KEY1连接GPB15也就是INT1,KEY2连接GPB14也就是INT0。如下图:
                              
(二)中断初始化:
                   这里要调用函数
void DrvGPIO_EnableEINT0(E_DRVGPIO_INT_TYPE TriggerType, E_DRVGPIO_INT_MODE Mode, GPIO_EINT0_CALLBACK pfEINT0Callback)
{
    volatile uint32_t u32Reg;
    if ((TriggerType == E_IO_BOTH_EDGE) && (Mode == E_MODE_LEVEL))
        return ;
    u32Reg = (uint32_t)&GPIOA->IEN + (E_GPB*PORT_OFFSET);
    if (TriggerType == E_IO_RISING)
    {
        outpw(u32Reg, inpw(u32Reg) | (1UL<<(14+16)));  
    }
    else if (TriggerType == E_IO_FALLING)
    {
        outpw(u32Reg, inpw(u32Reg) | (1UL<<(14)));  
     }
    else if (TriggerType == E_IO_BOTH_EDGE)
    {  
        outpw(u32Reg, inpw(u32Reg) | (1UL<<(14))|(1UL<<(14+16)));  
     }      
     /* Configure to be level trigger or edge trigger */
    u32Reg = (uint32_t)&GPIOA->IMD + (E_GPB*PORT_OFFSET);
    if (Mode == E_MODE_EDGE)
          outpw(u32Reg, inpw(u32Reg) & ~(1<<14));
    else if(Mode == E_MODE_LEVEL)
          outpw(u32Reg, inpw(u32Reg) | (1<<14));
    _pfEINT0Callback = pfEINT0Callback;
    NVIC_EnableIRQ(EINT0_IRQn);
}
                    
其中,第一个参数是选择边沿触发方式(上升沿,下降沿),第二个参数是选择触发方式(边沿触发,电平触发),第三个参数是中断回调函数的地址,从DrvGPIO.c开头的函数声明
                   static void (*_pfEINT0Callback)(void);
                   static void (*_pfEINT1Callback)(void);
                   可以看到,定义了指向函数的指针变量,可以用来存储回调函数的地址。  

                 中断响应函数:


void EINT0_IRQHandler(void)
{
         /* EINT0 = GPB14. Clear the interrupt */
         GPIOB->ISRC = 1UL << 14;
         if ( _pfEINT0Callback )
         _pfEINT0Callback();
}
(三)main()函数:

/////////////////////////////////////////////////
//工程:中断实验
//日期:2011年9月25日
////////////////////////////////////////////////
#include <stdio.h>
#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"
void pfEINT0Callback(void);
void pfEINT1Callback(void);
int main(void)
{
UNLOCKREG();
DrvSYS_Open(48000000);       //将时钟设定为48MHz

//GPIO端口配置 可以是GPA, GPB , GPC , GPD , GPE
//GPIO端口bit 可以是 0~15.
//GPIO端口模式 可设定为IO_INPUT , IO_OUTPUT ,IO_OPENDRAIN  或者IO_QUASI

DrvGPIO_Open(E_GPB, 10, E_IO_OUTPUT);         //  设置GPB10端口为输出模式
DrvGPIO_ClrBit(E_GPB, 10);            //  清GPB10端口  蜂鸣器不叫唤
//---------------------------------------------------------   
DrvGPIO_Open(E_GPA, 2, E_IO_OUTPUT);         //  设置GPA2端口为输出模式
DrvGPIO_Open(E_GPA, 3, E_IO_OUTPUT);         //  设置GPA3端口为输出模式
DrvGPIO_Open(E_GPA, 4, E_IO_OUTPUT);         //  设置GPA4端口为输出模式
DrvGPIO_Open(E_GPA, 5, E_IO_OUTPUT);         //  设置GPA5端口为输出模式
// DrvGPIO_Open(E_GPB,14,E_IO_INPUT);         
// DrvGPIO_Open(E_GPB,14,E_IO_INPUT);
DrvGPIO_EnableEINT0(E_IO_FALLING,E_MODE_EDGE,&pfEINT0Callback);    //初始化INT0中断方式
DrvGPIO_EnableEINT1(E_IO_FALLING,E_MODE_EDGE,&pfEINT1Callback);    //初始化INT1中断方式
// 经过测试,以上Open注释掉程序也能用
while(1);
}
void pfEINT0Callback(void)
{
DrvSYS_Delayms(10);
if(0==DrvGPIO_GetBit(E_GPB,14))
{
  DrvGPIO_ClrBit(E_GPA,2);    //点亮LED1
  DrvGPIO_SetBit(E_GPB,10);    //打开蜂鸣器
  DrvSYS_Delayms(200);     //延时200ms
  DrvGPIO_SetBit(E_GPA,2);    //关灯
  DrvGPIO_ClrBit(E_GPB,10);    //关蜂鸣器
}

}
static void pfEINT1Callback(void)
{
DrvSYS_Delayms(10);
if(0==DrvGPIO_GetBit(E_GPB,15))
{
  DrvGPIO_ClrBit(E_GPA,3);
  DrvGPIO_SetBit(E_GPB,10);
  DrvSYS_Delayms(200);
  DrvGPIO_SetBit(E_GPA,3);
  DrvGPIO_ClrBit(E_GPB,10);
}
}
(四)工程包: 中断实验.rar (198 KB)

相关帖子

沙发
afxstar| | 2012-3-9 10:32 | 只看该作者
感谢楼主,正在研究中断,帖子内容正是我想找的:victory: :victory: :victory: :victory:

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:从零开始

6

主题

230

帖子

1

粉丝