普冉(PUYA)单片机开发笔记(12): 获取外部中断

2023-12-17 17:44

本文主要是介绍普冉(PUYA)单片机开发笔记(12): 获取外部中断,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

将单片机的 GPIO 引脚作为外部按键的输入端是单片机较为常用的方式,例如把这颗 MCU 部署在一块控制面板的触点底板,使用者按压按钮(按键)对产品进行控制。本着学以致用的原则,使用 PY32F003 对外部中断如何处理是一项必须完成的学习内容了。今天我们就来操练一把。

参考厂家的例程,使用 PA12 作为外部中断的输入管脚,掌握一下 PY32F003 对外部中断处理的代码。PA12 设置为突变检测,当 PA12 上产生高低电平的变化时,翻转一次板载 LED 可以验证 MCU 是否正确捕捉了外部中断。

在我的这一个系列的实验,Keil 的文件组织都是沿用下来的,请参见我的任意一期《开发笔记》,这里就不罗嗦了,直接上代码。

实现代码

1. 在 main.h 中加一个预定义,然后定义和外部中断相关的函数原型

代码片段如下。

#define TIM_PWM_TEST    0
#define ADC_SAMPLE_TEST 0
#define FLASH_WR_TEST   0
#define I2C_COMM_TEST   0
#define I2C_SLAVE       0
#define EXTI_TEST       1...
...#if(EXTI_TEST)
void EXTI_Config(void);
void EXTI_Demo(void);
#endif...
...

文件新定义了预编译开关: EXTI_TEST,其它的开关全部设置为 0(关掉其它功能,免得产生冲突)。然后声明了 Config 和 Demo 两个函数。

2. app_exti.c 中实现相关函数

这一次我们将获取外部中断的相关函数都写到 app_exti.c 这一个文件中,包括 main.h 中预定义的 EXTI_Config() 函数,HAL_EXTI_MspInit() 函数和 EXTI4_15_IRQHandler() 函数,酱紫就不需要再“麻烦” 去修改 py32_f0xx_hal_msp.c 文件了。

完整代码如下。

/********************************************************************************* @file    app_exti.c* @brief   External Interrupt test functions.******************************************************************************* @copyright** Copyright (c) 2023 CuteModem Intelligence.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/#include "main.h"#if(EXTI_TEST)
/** ----------------------------------------------------------------------------
* @name   : void EXTI_Config(void)
* @brief  : EXTI 初始化, 配置引脚 PA12 为下降沿中断
* @param  : 
* @retval : void
* @remark : 
*** ----------------------------------------------------------------------------
*/
void EXTI_Config(void)
{GPIO_InitTypeDef  GPIO_InitStruct;__HAL_RCC_GPIOA_CLK_ENABLE();                  // 使能GPIOA时钟GPIO_InitStruct.Mode  = GPIO_MODE_IT_FALLING;  // 下降沿中断GPIO_InitStruct.Pull  = GPIO_PULLUP;           // 上拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;  // 速度为高速GPIO_InitStruct.Pin   = GPIO_PIN_12;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);             // 使能EXTI中断HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);     // 配置中断优先级
}/** ----------------------------------------------------------------------------
* @name   : void EXTI4_15_IRQHandler(void)
* @brief  : EXTI 初始化, 配置事件引脚 PA12
* @param  : 每产生一次下降沿, LED翻转一次
* @retval : void
* @remark : 
*** ----------------------------------------------------------------------------
*/
void EXTI4_15_IRQHandler(void)
{BSP_LED_Toggle(LED3);HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);//处理EXTI中断请求
}/** ----------------------------------------------------------------------------
* @name   : void EXTI_Demo(void);
* @brief  : 由 main() 调用的外部中断实验程序
* @param  : 
* @retval : void
* @remark : 
*** ----------------------------------------------------------------------------
*/
void EXTI_Demo(void)
{EXTI_Config();
}#endif
  • 使用 EXTI_Config() 函数分配 PA12 为外部中断源,内部上拉,下降沿中断,GPIO 高速。
  • 使用 EXTI4_15 中断,设置成 0 组最高优先级。
  • 在 EXT4_15中断服务程序中,翻转板载 LED 一次,然后调用 HAL_GPIO_EXTI_IRQHandler(GPIO_Pinx) 函数清除这个 GPIO 的中断标志,以便下一次捕获。
  • 定义了一个非常简单的 Demo 函数。

3. 修改一下 py32_f0xx_hal_it.c

已经在 app_exti.c 中实现了 EXTI_15_IRQ4_Handler,所以在 py32_f0xx_hal_it.c 中把那个函数关掉。

请注意这里不能重复定义其为 __weak 类型,这么做不会导致编译错误,但程序运行时会卡死。

/********************************************************************************* @file    py32f0xx_it.c* @author  MCU Application Team* @Version V1.0.0* @Date    2020-10-19* @brief   Interrupt Service Routines.*******************************************************************************/...
...#if(!EXTI_TEST)
void EXTI4_15_IRQHandler(void)
{
}
#endif...
...

4. 在 main() 函数中调用

/********************************************************************************* @file    main.c* @brief   Main program entry.******************************************************************************...
...********************************************************************************/#include "main.h"
#include <stdio.h>/**
* -------------------------------------------------------------------------
* @file   : int main(void)
* @brief  : main函数
* @param  : 无
* @retval : 无限循环,无返回值
* @remark : 
* -------------------------------------------------------------------------
*/
int main(void)
{HAL_Init();             // systick初始化SystemClock_Config();   // 配置系统时钟if(USART_Config() != HAL_OK) Error_Handler();         printf("\r\n\r\n\r\n""[SYS_INIT] Debug port initilaized.\r\n");printf("\r\n+---------------------------------------+""\r\n|        PY32F003 MCU is ready.         |""\r\n+---------------------------------------+""\r\n         10 digits sent to you!          ""\r\n+---------------------------------------+""\r\n");HAL_Delay(0);if (DBG_UART_Start() != HAL_OK) Error_Handler();HAL_Delay(0);#if(EXTI_TEST)EXTI_Config();
#endifwhile (1){ 
#if(!EXTI_TEST)BSP_LED_Toggle(LED3);HAL_Delay(500);
#endif}
}

程序很短,如果不考虑打印的话,只需要 HAL_Init(); SystemClock_Config(); 和 EXTI_Config(); 三个函数。主循环用 #if(!EXTI_TEST)关掉了,实际上是空的。

实验结果

编译烧录后,使用一根杜邦线连接 PA12 引脚,杜邦线的另一头接上 GND,反复插拔,观察板载 LED 的明灭。可以发现板载 LED 随着杜邦线的插拔一明一灭,说明实验是成功了的。

总结

  • 使用 PY32F003 的外部中断功能的配置很简单。
  • 如果使用 GPIO 的高速模式,对捕获外部中断有好处,但要避免插拔抖动造成的多次触发。实测使用 GPIO_SPEED_FREQ_VERY_HIGH 时,一次接触会产生 LED 的多次明灭;使用 GPIO_SPEED_FREQ_MEDIUM 时,好像又有点丢失的感觉。在实用设计中,在使用 HIGH 或者 VERY_HIGH 的同时,应该加一套时间常数较为合适的 RC 低通电路用于防抖。

本实验只是完成了一个管脚作为外部中断源的捕获,如果有多个的话,想来可能大同小异吧,毕竟芯片的 NVIC 构架是相同的。

谬误之处,欢迎在评论区讨论指正。

这篇关于普冉(PUYA)单片机开发笔记(12): 获取外部中断的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/505264

相关文章

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介