基于UC/COSII系统的STM32F103系列单片机外部中断按键的一种使用方法

基于UC/COSII系统的STM32F103系列单片机外部中断按键的一种使用方法

记录学习过程遇到的问题及解决方法,与大家一起分享:

外部中断按键大家都不陌生,在裸奔时只需配置几个寄存器就可以完成操作,初学单片机时都会将外部中断按键放到前几章学习中,那么当我们嵌入了UCOSII操作系统时,也需要外部按键中断来触发一个事件,比如按下按键打开蜂鸣器播放音乐,下面介绍一种在UCOSII操作系统下的使用方法:

参考如下代码:

  1. 初始化按键GPIO、中断。
  2. 写中断函数,按键触发进入中断函数,判断是按键按下,发送一个信号量给任务。
  3. 任务一直等待信号量,一旦有按键信号量,就会执行任务。处理按键按下需要处理的函数。
//按键端口初始化
void BSP_KeyInit(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = KEY_PIN; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//推挽输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz
    GPIO_Init(KEY_PORT, &GPIO_InitStructure);//根据设定参数初始化GPIOB.5
}

void BSP_KeyExtiInit(void)
{ 
  EXTI_InitTypeDef EXTI_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  // 按键端口初始化
  BSP_KeyInit();  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能复用功能时钟
 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);

  EXTI_InitStructure.EXTI_Line=EXTI_Line1;//外部中断线1
  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 = EXTI1_IRQn;//使能按键所在的外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级2 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;//子优先级0 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);   //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
//目的就是发送一个信号量给任务函数。
extern OS_EVENT*g_tKeyExtiSem;
void HDD_KeyIsr(void)
{   
    //发送信号量,并不会引起系统调度,中断服务函数一定要简洁
    OSSemPost(g_tKeyExtiSem);
    return;
}
//该函数放到库函数中断函数中
void EXTI1_IRQHandler(void)
{
    //进入处理函数 
    OSIntEnter();
    //判断按键是否按下,发送信号量给任务函数
    if (KEY_VALUE == 0)
    {   
        HDD_KeyIsr();
    }  
    EXTI_ClearITPendingBit(EXTI_Line1);  //清除LINE4上的中断标志位 
    OSIntExit();
    //在出中断的时候会引起系统调度,然后最高优先级的任务会先执行,保证了 系统的实时性 
} 
//任务函数如下
void USERAPP_KeyScanTask(void *pData)
{
    // OS_CPU_SR cpu_sr=0;
    (void)pData;
    g_tKeyExtiSem = OSSemCreate( 0 );  //定义处置为0的信号量
    while(1)
    {
        OSSemPend( g_tKeyExtiSem,0,&g_ucErr);//等待按键触发中断信号
        OSTimeDlyHMSM(0,0,0,1);
        if (KEY_VALUE == 0)
        {
          //要完成的代码区
        //也就是相当于不带操作系统中的中断处理函数内的内容。
        }
    }
}
在这前面需要定义两个全局变量,
//信号量及邮箱的定义
OS_EVENT *g_tKeyExtiSem;//按键中断信号量
//错误类型全局变量
INT8U g_ucErr;

可以添加更为复杂的长按、短按、多按键的按键队列等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值