嵌入式开发学习之--抢答器
admin
2024-03-27 02:45:41
0次

本篇以一个简单的抢答器来学习外部中断。

文章目录

  • 前言
  • 一、项目概况
    • 1.1项目需求
    • 1.2 项目来源
    • 1.3开发环境
    • 1.4项目意义
  • 二、开发步骤
    • 2.1涉及硬件电路
    • 2.2项目代码
      • 2.2.1中断配置
  • 总结


前言

前一篇大致了解了什么是中断,中断需要配置的参数,再结合之前的按键输入,这一篇实战一下。


提示:以下是本篇文章正文内容,下面案例可供参考

一、项目概况

1.1项目需求

  1. 两个按键,按下后蜂鸣器都会响;
  2. 1号按键按下,led红灯长亮;2号按键按下,led蓝灯长亮;
  3. 任意一个按键按下后,另一个按键按下将没有任何反应;也就是说led只会有一种颜色。

1.2 项目来源

作者脑洞;

1.3开发环境

软件:keil5;
硬件:野火挑战者开发板。

1.4项目意义

可以用在很多娱乐活动中,也可以增加家庭娱乐气氛,也可以用来维持讨论时的纪律,工作的人应该都知道讨论问题尤其是要负责任的问题时,有多么吵。

二、开发步骤

2.1涉及硬件电路

电路图请参考之前按键检测试验,这里不放了。

2.2项目代码

2.2.1中断配置

代码如下(示例):

exti.h

#ifndef __EXTI_H
#define	__EXTI_H#include "stm32f4xx.h"#define KEY1_INT_GPIO_PORT                GPIOA
#define KEY1_INT_GPIO_CLK                 RCC_AHB1Periph_GPIOA
#define KEY1_INT_GPIO_PIN                 GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE          EXTI_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE           EXTI_PinSource0
#define KEY1_INT_EXTI_LINE                EXTI_Line0
#define KEY1_INT_EXTI_IRQ                 EXTI0_IRQn#define KEY1_IRQHandler                   EXTI0_IRQHandler#define KEY2_INT_GPIO_PORT                GPIOC
#define KEY2_INT_GPIO_CLK                 RCC_AHB1Periph_GPIOC
#define KEY2_INT_GPIO_PIN                 GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE          EXTI_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE           EXTI_PinSource13
#define KEY2_INT_EXTI_LINE                EXTI_Line13
#define KEY2_INT_EXTI_IRQ                 EXTI15_10_IRQn#define KEY2_IRQHandler                   EXTI15_10_IRQHandler/*******************************************************/void EXTI_Key_Config(void);#endif /* __EXTI_H */

exti.c

#include "exti.h"static void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;NVIC_Init(&NVIC_InitStructure);
}void EXTI_Key_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure;RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);NVIC_Configuration();GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;	    		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;  GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);      SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);
}

简单说一下,NVIC_Configuration(void)函数中定义了中断优先级以及初始化; EXTI_Key_Config(void)函数则是在按键输入的基础上又加了中断的一些配置,比如上升沿还是下降沿触发,触发的引脚是什么,宏定义中,注意外部中断用的是哪个,则后面的中断函数也需要用哪一个。

app.c

#include "app.h"enum Respond respond;//³õʼ»¯app
void app_init(void)
{respond=NOBODY;}uint8_t user_rank(void)
{if(respond==NOBODY){respond=FIRST;return FIRST;}else{return NOBODY;}
}

app.h

#ifndef __APP_H
#define __APP_H#include "stm32f4xx.h"
#define NONE 0
#define GAIN 1enum Respond{NOBODY =0,FIRST=1
};extern enum Respond respond;void app_init(void);
uint8_t user_rank(void);#endif

app.c中做了一个user_rank函数,利用类似互斥锁的理论,来锁定哪一个先触发。

stm32f4xx.c


void KEY1_IRQHandler(void)
{if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {if(user_rank()==FIRST){LED_RED;}EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     }  
}void KEY2_IRQHandler(void)
{if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {if(user_rank()==FIRST){LED_BLUE;}EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     }  
}	

将中断函数放在stm32f4xx.c中,无论哪一个触发一次后,另一个按键将不会生效了。

#include "stm32f4xx.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "exti.h"
#include "app.h"void bsp_init(void)
{BEEP_GPIO_Config();
//	Key_GPIO_Config();LED_GPIO_Config();EXTI_Key_Config();
}uint8_t key1_inspect()
{if(KEY1_READ==KEY_ON){return KEY_ON;}else if(KEY1_READ==KEY_OFF){return KEY_OFF;}
}uint8_t key2_inspect()
{if(KEY2_READ==KEY_ON){return KEY_ON;}else if(KEY2_READ==KEY_OFF){return KEY_OFF;}
}int main(void)
{uint8_t led_status;led_status=OFF;bsp_init();app_init();while(1){if(key1_inspect()==KEY_ON){BEEP_ON;			while(key1_inspect()==KEY_ON){}BEEP_OFF;	}			if(key2_inspect()==KEY_ON){BEEP_ON;			while(key1_inspect()==KEY_ON){}BEEP_OFF;	}			}		
}

main.c主要是按键按下后蜂鸣器的处理。

总结

1.利用中断能节省资源,提高效率;
2.能实现任务并行。
3.在写上层逻辑中,要注意的是当多中断同时调用某一变量或者某一函数,最好加互斥锁,否则可能数据会出错。

相关内容

热门资讯

两只大牛股,紧急发声:不属实!... 5天3板超声电子:“超声电子高频板通过英伟达认证”情况不属实,目前无产品供货给英伟达9月13日晚间,...
科创板创新药企BD授权交易总额... 2026年半年度财报季已收官,在创新药企业以业绩扭亏和BD兑现吸引市场目光的同时,以CXO为代表的上...
蔚来李斌1-8月交付增近58%... 9月9日消息,上海蔚来汽车有限公司副总裁品牌与传播资深专家马麟在微博透露,9月8日下午,蔚来创始人、...
京东物流部署过万前置仓应对手机... IT之家 9 月 13 日消息,据京东物流黑板报,9 月,多个品牌旗舰手机集中上新。针对消费者希望尽...
特朗普让泽连斯基勿袭击俄柴油燃... 9月13日,当地时间9月13日,美国总统特朗普要求乌克兰总统泽连斯基停止袭击俄罗斯柴油燃料设施,称相...
下周,年内最便宜新股启动打新 ... 2026.09.13本文字数:1467,阅读时长大约2分钟作者 |第一财经 安卓封图 |AI生成下周...
北京:激活地理信息要素赋能城市... 9月13日,从北京市规划和自然资源委员会获悉,《北京市测绘地理信息条例》已由北京市第十六届人民代表大...
接下来该如何逃顶?建议看看这篇... 最近这段时间,很多朋友的心里其实都是悬着的。行情走到这个位置,大家见面聊得最多的就是,接下来到底该怎...
武汉:到2035年武汉区域科技... 9月13日,武汉市委十四届十三次全会召开,审议通过了《关于打造具有全球竞争力的开放创新生态 高水平建...
卡塔尔股市收盘上涨0.25% 9月13日,卡塔尔证券交易所主要股指今日收盘上涨0.25%,报9848.95点,上涨24.46点。全...