I.MX6U 裸机开发15.IRQ中断——GPIO中断处理

server/2024/11/23 22:13:35/

I.MX6U 裸机开发15.IRQ中断——GPIO中断处理

  • 一、向GPIO驱动添加中断处理函数
    • 1. GPIO 相关寄存器
      • (1)GPIOx_ICRn 按键GPIO设置中断模式
      • (2)使能GPIO对应的中断
      • (3)GPIOx_EDGE_SEL
      • (4)GPIO_ISR寄存器
    • 2. GIC 设置
      • (1)使能相应的中断ID
      • (2)中断优先级设置
      • (3)注册GPIO1_IO18的中断处理函数
  • 二、GPIO 中断代码
    • 1. 在 bsp_gpio.h 里定义中断触发类型枚举
    • 2. 修改配置结构体
    • 3. 使能、禁用GPIO中断及清除标志位
    • 4. 触发方式
  • 三、按键中断驱动
    • 1. bsp_esti.h
    • 2. bsp_esti.c
    • 3. main.c

一、向GPIO驱动添加中断处理函数

1. GPIO 相关寄存器

(1)GPIOx_ICRn 按键GPIO设置中断模式

在这里插入图片描述

在《IMX6ULL参考手册》中可以看到,GPIOx_ICR1GPIOx_ICR2 是用于配置 GPIO 引脚中断触发模式的寄存器。每个寄存器控制 16 个 GPIO 引脚的中断配置。

  • GPIOx_ICR1:控制 GPIO 引脚 0 到 15 的中断配置。
  • GPIOx_ICR2:控制 GPIO 引脚 16 到 31 的中断配置。

每个引脚的中断配置占用 2 位,可以配置为以下几种模式:

  • 00:低电平触发
  • 01:高电平触发
  • 10:上升沿触发
  • 11:下降沿触发

具体配置方法如下:

// 配置 GPIO 引脚 0 为下降沿触发
GPIOx->ICR1 &= ~(3 << (0 * 2)); // 清除原有配置
GPIOx->ICR1 |= (2 << (0 * 2));  // 设置为下降沿触发// 配置 GPIO 引脚 16 为上升沿触发
GPIOx->ICR2 &= ~(3 << ((16 - 16) * 2)); // 清除原有配置
GPIOx->ICR2 |= (3 << ((16 - 16) * 2));  // 设置为上升沿触发

通过设置 GPIOx_ICR1GPIOx_ICR2 寄存器,可以灵活配置每个 GPIO 引脚的中断触发模式。

开发板按下时,UART1_CTS端口接地,所以设置为下降沿触发 。

(2)使能GPIO对应的中断

GPIO_MIR 寄存器用于配置 GPIO 引脚的中断屏蔽。每个 GPIO 引脚对应 GPIO_MIR 寄存器中的一位,通过设置或清除这些位,可以使能或屏蔽相应引脚的中断。

设置示例:

// 屏蔽 GPIO 引脚 0 的中断
GPIOx->MIR |= (1 << 0);// 使能 GPIO 引脚 0 的中断
GPIOx->MIR &= ~(1 << 0);// 屏蔽 GPIO 引脚 16 的中断
GPIOx->MIR |= (1 << 16);// 使能 GPIO 引脚 16 的中断
GPIOx->MIR &= ~(1 << 16);

(3)GPIOx_EDGE_SEL

GPIOx_EDGE_SEL 寄存器用于配置 GPIO 引脚的边沿选择。它允许选择 GPIO 引脚是对上升沿、下降沿还是双边沿(上升沿和下降沿)触发中断。

(4)GPIO_ISR寄存器

处理完中断后,通过 GPIO_ISR 寄存器清除中断标志位,写1清零。

2. GIC 设置

(1)使能相应的中断ID

开发板使用的按键是接在 GPIO1_IO18引脚,在 《IMX6ULL参考手册》P185:
在这里插入图片描述
可以看到GPIO1_IO18对应的中断ID是67+32=99。
d MCIMX6X6Y2.h 里有定义:

GPIO1_Combined_16_31_IRQn = 99

(2)中断优先级设置

(3)注册GPIO1_IO18的中断处理函数

二、GPIO 中断代码

1. 在 bsp_gpio.h 里定义中断触发类型枚举

/*** @brief 中断触发类型枚举*/typedef enum _gpio_interrupt_mode{kGPIO_NoIntmode = 0U, // 无中断kGPIO_IntLowLevel = 1U, // 低电平触发kGPIO_IntHighLevel = 2U, // 高电平触发kGPIO_IntRisingEdge = 3U, // 上升沿触发kGPIO_IntFallingEdge = 4U, // 下降沿触发kGPIO_IntRisingOrFallingEdge = 5U, // 上升沿或下降沿触发} gpio_interrupt_mode_t;

2. 修改配置结构体

/*** @brief GPIO 配置结构体*/
typedef struct _gpio_pin_config
{gpio_pin_direction_t direction; // 输入输出uint8_t outputLogic;            // 输出电平gpio_interrupt_mode_t interruptMode; // 中断触发类型
} gpio_pin_config_t;

3. 使能、禁用GPIO中断及清除标志位

/**
* @brief 使能GPIO中断
*/
void gpio_enableint(GPIO_Type *base, int pin)
{base->IMR |= 1 << pin;
}/**
* @brief 禁止GPIO中断
*/
void gpio_disableint(GPIO_Type *base, int pin)
{base->IMR &= ~(1 << pin);
}/**
* @brief 清除中断标志位
*/
void gpio_clearintflags(GPIO_Type *base, int pin)
{base->ISR |= 1 << pin;
}

4. 触发方式


/**
* @brief GPIO中断初始化
*/
void gpio_interrupt_init(GPIO_Type *base, unsigned int pin, gpio_interrupt_mode_t mode) {volatile uint32_t *icr;uint32_t icrShift;icrShift = pin;// 清0防止 gpio_icr 寄存器设置无效base->EDGE_SEL &= ~(1 << pin);if (pin < 16) {icr = &(base->ICR1);} else {icr = &(base->ICR2);icrShift -= 16;}switch (mode) {case kGPIO_IntLowLevel:  // 低电平触发*icr &= ~(3 << (icrShift * 2));  // 每个IO占用2位,即0b11,移动次数为icrShift * 2break;case kGPIO_IntHighLevel: // 高电平触发*icr = (*icr & ~(3 << (icrShift * 2))) | (1 << (icrShift * 2));break;case kGPIO_IntRisingEdge: // 上升沿触发*icr = (*icr & ~(3 << (icrShift * 2))) | (2 << (icrShift * 2));break;case kGPIO_IntFallingEdge: // 下降沿触发*icr = (*icr & ~(3 << (icrShift * 2))) | (3 << (icrShift * 2));break;case kGPIO_IntRisingOrFallingEdge: // 上升沿或下降沿触发base->EDGE_SEL |= 1 << pin;break;}}

三、按键中断驱动

1. bsp_esti.h

//
// Created by Xundh on 2024/11/19.
//#ifndef LEARN_I_MX6U_BSP_ESTI_H
#define LEARN_I_MX6U_BSP_ESTI_H/**
* @brief  初始化外部中断, GPIO1_IO18
*/
void exti_init(void);/**
* @brief GPIO1_IO18 中断服务函数
*/
void gpio1_io18_irqhandler(unsigned int gicciar, void *param);
#endif //LEARN_I_MX6U_BSP_ESTI_H

2. bsp_esti.c

//
// Created by Xundh on 2024/11/19.
//
#include "bsp_exti.h"
#include "bsp_clk.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
#include "bsp_int.h"
#include "led.h"
#include "imx6u.h"/**
* @brief  初始化外部中断, GPIO1_IO18
*/
void exti_init(void) {gpio_pin_config_t key_config;// 1. 设置复用为GPIO1_IO18IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);// 2. 设置电气属性IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF0B0);// 3. 设置方向为输入key_config.direction = kGPIO_DigitalInput;// 4. 设置中断触发类型为下降沿触发key_config.interruptMode = kGPIO_IntFallingEdge;// 5. 初始化GPIOgpio_init(GPIO1, 18, &key_config);// 6. 使能GPIO1_IO18中断GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);// 7. 中断服务函数注册sys_irq_handle_register(GPIO1_Combined_16_31_IRQn, (system_irq_handler_t)gpio1_io18_irqhandler, NULL);// 8. GPIO 使能gpio_enableint(GPIO1, 18);
}/**
* @brief GPIO1_IO18 中断服务函数
*/
void gpio1_io18_irqhandler(unsigned int gicciar, void *param) {static unsigned char state = 0;// 临时使用定时,生产环境不能这样用delay(10);if (gpio_pinread(GPIO1, 18) == 0) {state = !state;led_switch(LED0, state);}// 清除中断标志位gpio_clearintflags(GPIO1, 18);}

上面程序编译后,查看反汇编文件:

在这里插入图片描述

可以看到 0x87800000 放的并不是中断向量表,修改 start.S,将bss段定义移到清除BSS段前面。

3. main.c

#include "inc/main.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "bsp_int.h"
#include "bsp_exti.h"int main(void)
{bsp_int_init();  /* 初始化中断 */imx6u_clkinit();    /* 初始化系统时钟 */clk_enable();   /* 使能外设时钟 */led_init();     /* 初始化LED */beep_init();    /* 初始化蜂鸣器 */exti_init();    /* 初始化外部中断 */while(1) {
//        led_on();
//        delay(1000);
//        led_off();
//        delay(1000);}return 0;
}

本代码实现按key0, LED0切换亮灭显示。


http://www.ppmy.cn/server/144367.html

相关文章

4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)

LinkedList 概述 LinkedList<T> 通过节点&#xff08;Node&#xff09;来存储数据&#xff0c;每个节点包含数据和指向下一个节点的引用 LinkedList<T> 存储的元素是可重复的 LinkedList<T> 支持泛型&#xff0c;可以指定存储的元素的类型 LinkedList<…

ETCD调优

ETCD是一种高可用的分布式键值存储&#xff0c;广泛用于Kubernetes和其他云原生应用。为了确保ETCD在生产环境中的性能和稳定性&#xff0c;以下是一些调优建议&#xff1a; 1. 硬件和网络 节点配置&#xff1a;使用较高配置的硬件&#xff0c;尤其是CPU和内存&#xff0c;以…

Sobey融媒体 硬编码漏洞复现

0x01 产品描述: ‌ Sobey融媒体‌是成都索贝数码科技股份有限公司(简称索贝)提供的一系列融媒体解决方案,旨在帮助媒体机构实现新闻内容的快速采集、高效生产、首发首推、安全可控和灵活迭代。这些解决方案主要应用于广播、电视和新媒体各渠道,提供轻量化、移动化…

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…

【AI系统】GPU 架构回顾(从2010年-2017年)

GPU 架构回顾 1999 年&#xff0c;英伟达发明了 GPU&#xff08;graphics processing unit&#xff09;&#xff0c;本文将介绍英伟达 GPU 从 Fermi 到 Blackwell 共 9 代架构&#xff0c;时间跨度从 2010 年至 2024 年&#xff0c;具体包括费米&#xff08;Feimi&#xff09;…

OpenAI 助力数据分析中的模式识别与趋势预测

数据分析师的日常工作中&#xff0c;发现数据中的隐藏模式和预测未来趋势是非常重要的一环。借助 OpenAI 的强大语言模型&#xff08;如 GPT-4&#xff09;&#xff0c;我们可以轻松完成这些任务&#xff0c;无需深厚的编程基础&#xff0c;也能快速上手。 在本文中&#xff0…

[JavaWeb]微头条项目

完整笔记和项目代码&#xff1a; https://pan.baidu.com/s/1PZBO0mfpwDPic4Ezsk8orA?pwdwwp5 提取码: wwp5 JavaWeb-微头条项目开发 1 项目简介 1.1 业务介绍 微头条新闻发布和浏览平台,主要包含业务如下 用户功能 注册功能登录功能 头条新闻 新闻的分页浏览通过标题关键字搜…

使用 PyTorch 实现并训练 VGGNet 用于 MNIST 分类

本文将展示如何使用 PyTorch 实现一个经典的 VGGNet 网络&#xff0c;并在 MNIST 数据集上进行训练和测试。我们将从模型构建开始&#xff0c;涵盖数据预处理、模型训练、评估、保存与加载模型&#xff0c;以及可视化预测结果等全过程。 1. VGGNet 模型的实现 首先&#xff0c;…