嵌入式开发学习之--抢答器

简介: 嵌入式开发学习之--抢答器

嵌入式开发学习之--抢答器


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

文章目录

前言

一、项目概况

1.1项目需求

1.2 项目来源

1.3开发环境

1.4项目意义

二、开发步骤

2.1涉及硬件电路

2.2项目代码

2.2.1中断配置

总结

前言

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

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

一、项目概况

1.1项目需求

两个按键,按下后蜂鸣器都会响;

1号按键按下,led红灯长亮;2号按键按下,led蓝灯长亮;

任意一个按键按下后,另一个按键按下将没有任何反应;也就是说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.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、在写上层逻辑中,要注意的是当多中断同时调用某一变量或者某一函数,最好加互斥锁,否则可能数据会出错。

相关文章
|
开发工具 数据安全/隐私保护 git
git 命令拉取提交代码时都需要输入账号密码
git 命令拉取提交代码时都需要输入账号密码
725 0
git 命令拉取提交代码时都需要输入账号密码
|
6月前
|
数据安全/隐私保护
基于双PI控制的永磁同步电机变频调速系统simulink建模与仿真
本课题针对基于双PI控制的永磁同步电机(PMSM)变频调速系统,进行Simulink建模与仿真。系统采用MATLAB2022a实现,包含完整核心程序与无水印仿真结果。双PI控制器分别对速度和电流闭环控制,结合dq坐标变换及SVPWM技术,确保电机高效运行与精确调速。内容涵盖系统原理、数学模型与控制策略,适合学习与研究使用。
|
11月前
|
消息中间件 存储 Java
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
200 3
|
8月前
|
Java 测试技术 应用服务中间件
Spring Boot 配置文件总结
Spring Boot 提供全局配置文件 `application.properties` 和 `application.yml`,用于修改自动配置的默认值。前者使用键值对配置,后者使用缩进和冒号。不同环境(开发、测试、生产)可切换配置文件,通过 `spring.profiles.active` 指定。例如,开发环境端口为4790,测试环境为4791,生产环境为4792。配置示例展示了属性、List、Map定义及引用方法。
209 14
|
10月前
|
Java 测试技术 开发者
Spring Boot 的优点详解
Spring Boot 的优点详解
716 6
|
10月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤。通过这些工具,可以显著提升编码效率和代码质量。
1883 4
|
11月前
|
传感器 人工智能 自动驾驶
未来出行:无人驾驶汽车的技术革新与挑战
本文深入探讨了无人驾驶汽车背后的技术原理,包括感知、定位、决策和执行四个核心系统。同时,文章分析了当前自动驾驶技术的发展现状,并指出了技术标准不统一、基础设施不完善和法律法规滞后等主要挑战。最后,展望了无人驾驶汽车未来的发展趋势,强调了跨学科合作和政策支持的重要性。
478 4
|
10月前
|
监控 Java 微服务
微服务调用失败时常用处理手段
【10月更文挑战第27天】在微服务架构中,服务调用面临诸多不确定性,如服务提供者的硬件故障、网络问题等。因此,需要采取超时、重试、双发和熔断等策略来确保服务的稳定性和可靠性。超时机制避免长时间等待,重试机制应对偶发错误,双发机制提高成功率,熔断机制防止故障扩散。这些策略共同作用,保障了系统的高可用性。
|
存储 关系型数据库 MySQL
MySQL 多表查询详解
MySQL 是一个强大的关系型数据库管理系统,多表查询是数据库操作中的重要部分之一。多表查询允许您从多个表中检索和操作数据,以满足复杂的数据需求。本文将介绍 MySQL 多表查询的基本概念、语法和示例,以及一些常见的多表查询场景。
1033 0
|
NoSQL Java 关系型数据库
软件开发常用之若依修改之添加数据库,添加redis,利用RDM连接宝塔
软件开发常用之若依修改之添加数据库,添加redis,利用RDM连接宝塔