【嵌入式Linux】i.MX6ULL GPIO 中断管理与配置函数

news2024/11/17 22:31:28

文章目录

  • GPIO 中断管理与配置函数
    • 1 GPIO中断服务号
    • 2 GPIO中断相关的寄存器配置
    • 3 具体代码分析
      • 3.1 数据结构和类型定义
      • 3.2 `gpio_int_enable`
      • 3.3 `gpio_int_disable`
      • 3.4 `gpio_int_flagClear`
      • 3.5 `gpio_int_init`
      • 3.6 `gpio_init`
    • 4 完整代码

  • 本文章结合了正点原子的 i.mx6u嵌入式Linux开发指南和笔者的理解。
  • 前面我们进行了总的外部中断处理函数(system_irqhandler)的初始化,在这个函数中同个中断号,选择跳转到了不同的中断服务函数
  • 下面我们就来写一个具体的中断服务函数,本文将具体编写GPIO 中断管理与配置函数

GPIO 中断管理与配置函数

以按键开关为例进行编写。

1 GPIO中断服务号

查看原理图,可知按键开关接入了 GPIO1_PIN18。

  • IMX6ULL参考手册P185
    在这里插入图片描述
    可以看到中断服务号是67,加上前面32个CPU接口的私有中断,真正的中断号应该是67+32=99。

  • 查看MCIMX6Y2.hIRQn_Type,可以证实这一点

GPIO1_Combined_0_15_IRQn     = 98,               /**< Combined interrupt indication for GPIO1 signals 0 - 15. */
GPIO1_Combined_16_31_IRQn    = 99,               /**< Combined interrupt indication for GPIO1 signals 16 - 31. */

2 GPIO中断相关的寄存器配置

  • IMX6ULL参考手册P1360
    在这里插入图片描述
  • 以下是这些寄存器的详细解释:
    • GPIOx_ICR1 (GPIO Interrupt Configuration Register 1):配置的是pin0-pin15,该寄存器用于配置 GPIO 中断的触发方式,包括上升沿、下降沿、低电平或高电平触发。
    • GPIOx_ICR2 (GPIO Interrupt Configuration Register 2):同上,只不过配置的是pin16-pin31
    • GPIOx_IMR (GPIO Interrupt Mask Register):该寄存器用于屏蔽或启用 GPIO 中断。 通过设置该寄存器中的相应位,可以屏蔽或启用每个 GPIO 引脚的中断。
    • GPIOx_ISR (GPIO Interrupt Status Register):该寄存器用于指示 GPIO 中断状态。 当一个 GPIO 引脚发生中断时,该寄存器中的相应位会被置位。
    • GPIOx_EDGE_SEL (GPIO Edge Select Register):该寄存器用于选择 GPIO 中断的触发方式为边沿(上升沿和下降沿都会触发),且一旦设置边沿检测有效,将会屏蔽ICR寄存器的设置

3 具体代码分析

3.1 数据结构和类型定义

  • gpio_interrupt_mode_t
    此枚举定义了GPIO中断的可能触发模式:

    • kGPIO_Nointmode: 无中断模式。
    • kGPIO_IntLowLevel: 低电平触发。
    • kGPIO_IntHighLevel: 高电平触发。
    • kGPIO_IntRisingEdge: 上升沿触发。
    • kGPIO_IntFallingEdge: 下降沿触发。
    • kGPIO_IntRisingFallingEdge: 上升沿和下降沿都触发。
      在这里插入图片描述
      在这里插入图片描述
  • gpio_pin_direction_t
    此枚举定义了GPIO引脚可能的方向:

    • kGPIO_DigitalInput: 数字输入。
    • kGPIO_DigitalOutput: 数字输出。
  • gpio_pin_config_t
    此结构体用于配置GPIO引脚:

    • direction: 引脚方向(输入或输出)。
    • outputLogic: 当方向为输出时的默认电平。
    • interruptMode: 中断模式。

3.2 gpio_int_enable

void gpio_int_enable(GPIO_Type *base, unsigned int pin)
{
    base->IMR |= (1U << pin);
}

使能指定GPIO组的特定引脚的中断功能。
在这里插入图片描述

3.3 gpio_int_disable

void gpio_int_disable(GPIO_Type *base, unsigned int pin)
{
    base->IMR &= ~(1U << pin);
}

禁用指定GPIO组的特定引脚的中断功能。

3.4 gpio_int_flagClear

void gpio_int_flagClear(GPIO_type *base, unsigned int pin)
{
    base->ISR |= (1U << pin);
}

清除指定GPIO组的特定引脚的中断标志位,注意是通过写1清除。
在这里插入图片描述

3.5 gpio_int_init

void gpio_int_init(GPIO_Type *base, int pin, gpio_interrupt_mode_t pin_int_mode)
{
    volatile uint32_t *icr;//GPIO高16位和低16位使用的ICR寄存器不同,需要判断一下
    uint32_t icrShift;
    icrShift = pin;
    base->EDGE_SEL &= ~(1<<pin);//先把双边沿触发模式关了

    if(pin < 16){
        icr = &(base->ICR1);
    }
    else{
        icr = &(base->ICR2);
        icrShift -= 16;
    }

    switch(pin_int_mode){
        case kGPIO_IntLowLevel:
            *icr &= ~(3 << (2*icrShift));
            break;
        case kGPIO_IntHighLevel:
            *icr &= (3 << (2*icrShift));
            *icr |= (1 << (2*icrShift));
            break;
        case kGPIO_IntRisingEdge:
            *icr &= ~(3 << (2*icrShift));
            *icr |= (2 << (2*icrShift));
            break;
        case kGPIO_IntFallingEdge:
            *icr &= ~(3 << (2*icrShift));
            *icr |= (3 << (2*icrShift));
            break;
        case kGPIO_IntRisingFallingEdge:
            base->EDGE_SEL |= (1<<pin);
            break;
    }
}

配置特定GPIO引脚的中断触发模式。此函数处理边缘和电平触发的配置,并根据引脚号选择正确的寄存器和位偏移。

3.6 gpio_init

void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
{
     if(config->direction == kGPIO_DigitalInput){
         base->GDIR &= ~(1 << pin);
     }
     else{
         base->GDIR |= (1 << pin);
         gpio_pin_write(base, pin, config->direction);
     }

     gpio_int_init(base, pin, config->interruptMode);
}

使用提供的配置(方向,输出逻辑,中断模式)初始化指定的GPIO引脚。此函数首先设置引脚方向,然后根据配置设置默认输出逻辑,并调用gpio_int_init来配置中断功能。

4 完整代码

  • bsp_gpio.c
#include "bsp_gpio.h"

/**
  * @brief 使用给定配置初始化GPIO引脚。
  *
  * @param base GPIO组。
  * @param pin 要配置的引脚号。
  * @param config 指向GPIO引脚配置结构的指针。
  *
  * @return 无。
  */
 void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
 {
     if(config->direction == kGPIO_DigitalInput){
         base->GDIR &= ~(1 << pin);
     }
     else{
         base->GDIR |= (1 << pin);
         gpio_pin_write(base, pin, config->direction);
     }

     gpio_int_init(base, pin, config->interruptMode);
 }


 /**
  * @brief 读取指定GPIO的电平值。
  *
  * @param base 要读取的GPIO组。
  * @param pin 要读取的引脚号。
  *
  * @return GPIO的电平值。
  */
 int gpio_pin_read(GPIO_Type *base, int pin)
 {
    return (((base->DR)>>pin)&0x1);
 }


 /**
  * @brief 指定 GPIO 输出高或者低电平。
  *
  * @param base GPIO组。
  * @param pin  要输出的引脚号。
  * @param value 要输出的电平,1输出高电平,0输出低电平。
  *
  * @return 无。
  */
void gpio_pin_write(GPIO_Type *base, int pin, int value)
{
    if(value == 0u){
        base->DR &= ~(1U << pin);
    }
    else{
        base->DR |= (1U << pin);
    }
}

 /**
  * @brief 使能指定 GPIO 中断。
  *
  * @param base GPIO组。
  * @param pin  要输出的引脚号。
  *
  * @return 无。
  */
void gpio_int_enable(GPIO_Type *base, unsigned int pin)
{
    base->IMR |= (1U << pin);
}


 /**
  * @brief 失能指定 GPIO 中断。
  *
  * @param base GPIO组。
  * @param pin  要输出的引脚号。
  *
  * @return 无。
  */
void gpio_int_disable(GPIO_Type *base, unsigned int pin)
{
    base->IMR &= ~(1U << pin);
}

 /**
  * @brief 清除指定 GPIO 中断标志位。
  *
  * @param base GPIO组。
  * @param pin  要输出的引脚号。
  *
  * @return 无。
  */
void gpio_int_flagClear(GPIO_Type *base, unsigned int pin)
{
    base->ISR |= (1U << pin);
}


 /**
  * @brief GPIO中断初始化函数。
  *
  * @param base GPIO组。
  * @param pin  要输出的引脚号。
  * @param pin_int_mode  要设置的触发类型。
  *
  * @return 无。
  */
void gpio_int_init(GPIO_Type *base, int pin, gpio_interrupt_mode_t pin_int_mode)
{
    volatile uint32_t *icr;//GPIO高16位和低16位使用的ICR寄存器不同,需要判断一下
    uint32_t icrShift;
    icrShift = pin;
    base->EDGE_SEL &= ~(1<<pin);//先把双边沿触发模式关了

    if(pin < 16){
        icr = &(base->ICR1);
    }
    else{
        icr = &(base->ICR2);
        icrShift -= 16;
    }

    switch(pin_int_mode){
        case kGPIO_IntLowLevel:
            *icr &= ~(3 << (2*icrShift));
            break;
        case kGPIO_IntHighLevel:
            *icr &= (3 << (2*icrShift));
            *icr |= (1 << (2*icrShift));
            break;
        case kGPIO_IntRisingEdge:
            *icr &= ~(3 << (2*icrShift));
            *icr |= (2 << (2*icrShift));
            break;
        case kGPIO_IntFallingEdge:
            *icr &= ~(3 << (2*icrShift));
            *icr |= (3 << (2*icrShift));
            break;
        case kGPIO_IntRisingFallingEdge:
            base->EDGE_SEL |= (1<<pin);
            break;
    }
}


  • bsp_gpio.h
typedef enum _gpio_interrupt_mode{
    kGPIO_Nointmode = 0U,
    kGPIO_IntLowLevel = 1U, 			/* 低电平触发	*/
    kGPIO_IntHighLevel = 2U, 			/* 高电平触发 */
    kGPIO_IntRisingEdge = 3U, 			/* 上升沿触发	*/
    kGPIO_IntFallingEdge = 4U, 			/* 下降沿触发 */
    kGPIO_IntRisingFallingEdge = 5U, 	/* 上升沿和下降沿都触发 */
}gpio_interrupt_mode_t;


typedef enum _gpio_pin_direction{
    kGPIO_DigitalInput = 0U,
    kGPIO_DigitalOutput = 1U,
} gpio_pin_direction_t;


/**
 * @brief 方向,默认电平
 */
typedef struct _gpio_pin_config{
    //方向
    gpio_pin_direction_t direction;
    //方向为输出时,默认输出电平
    uint8_t outputLogic;
    //中断模式
    gpio_interrupt_mode_t interruptMode;
} gpio_pin_config_t;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

49、基于归一化感知器的输入向量分类(matlab)

1、基于归一化感知器的输入向量分类的原理及流程 归一化感知器是一种分类算法&#xff0c;其原理基于感知器算法&#xff0c;但是在输入向量上进行了归一化处理&#xff0c;以提高算法的性能和稳定性。 流程如下&#xff1a; 输入向量归一化&#xff1a;对每个输入向量进行归…

ChatGPT只是开胃菜,AIGC风口真的来了!

去年OpenAI发布的ChatGPT在全球疯狂刷屏成为一款现象级产品&#xff0c;并成功出圈受到IT、新闻媒体、学术研究、教育等领域的广泛好评和应用。甚至有一位美国学生用ChatGPT 写论文拿下全班最高分&#xff0c;受到了全球媒体的热议。 比尔盖茨曾在今年“Reddit AMA大会”表示&…

Mamba 模型

建议观看讲解视频&#xff1a;AI大讲堂&#xff1a;革了Transformer的小命&#xff1f;专业拆解【Mamba模型】_哔哩哔哩_bilibili 1. 论文基本信息 2. 创新点 选择性 SSM&#xff0c;和扩展 Mamba 架构&#xff0c;是具有关键属性的完全循环模型&#xff0c;这使得它们适合作…

武汉星起航:跨境电商直播带货热,推动中国出口销售新飞跃

随着数字化时代的到来&#xff0c;跨境电商领域正经历着前所未有的变革。中国商务部最近发布的数据显示&#xff0c;2023年中国跨境电商进出口总额达到2.38万亿元&#xff0c;同比增长15.6%&#xff0c;其中出口更是高达1.83万亿元&#xff0c;同比增长19.6%。这一亮眼成绩的背…

电脑开不了机怎么办?无响应就试试这3个方法,快速解决黑屏

当电脑突然变得沉默寡言&#xff0c;没有任何响应&#xff0c;屏幕只剩下一片漆黑时&#xff0c;不仅会打断我们的计划&#xff0c;还可能让我们感到无助和焦虑。电脑开不了机怎么办呢&#xff1f;如果你正面临这样的困境&#xff0c;别担心&#xff0c;本文将引导你通过三个简…

一文讲解:如何理解数字化?数字化的三大本质!

在当今时代&#xff0c;一些企业对数字化概念与本质进行了专门的诠释&#xff0c;部分认为数字化是基于大数据、云计算、物联网、5G等数字技术来实现企业的管理创新&#xff0c;且这一进程的前提是建立在信息化基础之上。然而&#xff0c;也有一些专家持有不同观点&#xff0c;…

基于weixin小程序新生报到系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;班级信息管理&#xff0c;师资力量管理&#xff0c;宿舍信息管理&#xff0c;宿舍安排管理&#xff0c;签到信息管理&#xff0c;论坛管理 小程序功能包括&#xff1a;系统首页&a…

用IP申请SSL证书需要注意什么?

用IP地址申请SSL证书需要选择支持IP地址验证的证书&#xff0c;验证所有权&#xff0c;正确安装和配置证书等。在互联网中&#xff0c;确保数据传输的安全性是至关重要的&#xff0c;使用SSL证书能够对数据进行加密处理&#xff0c;防止信息被窃取或篡改。使用IP地址申请SSL证书…

使用 Vanna 生成准确的 SQL 查询:工作原理和性能分析

Vanna工作原理 从本质上讲,Vanna 是一个 Python 包,它使用检索增强功能来帮助您使用 LLM 为数据库生成准确的 SQL 查询。 Vanna 的工作分为两个简单的步骤 - 在您的数据上训练 RAG“模型”,然后提出问题,这些问题将返回可设置为在您的数据库上自动运行的 SQL 查询。 vn.t…

如何安装Linux-centOS虚拟机

一、创建虚拟机 二、安装虚拟机 开启虚拟机&#xff0c;将光标移入虚拟机中&#xff0c;点击键盘上的上下键&#xff0c;移动到第一行&#xff0c;按下enter键&#xff0c;如图&#xff1a; 等待进入到如下图&#xff0c;选择中文 设置root密码

计算机毕业设计Thinkphp/Laravel校园体育器材管理系统

校园体育器材管理系统在流畅性&#xff0c;续航能力&#xff0c;等方方面面都有着很大的优势。这就意味着校园体育器材管理系统的设计可以比其他系统更为出色的能力&#xff0c;可以更高效的完成最新的体育器材、器材借用、器材归还、器材损坏、采购入库、器材报废、维修记录等…

项目实施方案(实际项目原件doc参考)

软件实施方案 二、 项目介绍 三、 项目实施 四、 项目实施计划 五、 人员培训 六、 项目验收 七、 售后服务 八、 项目保障措施 软件开发全套资料获取&#xff1a;&#xff08;本文末个人名片也可直接获取&#xff09; 软件产品&#xff0c;特别是行业解决方案软件产品不同于一…

制造业采购堡垒机的四大必要性看这里!

制造业包括的行业广泛&#xff0c;与大家的生活息息相关&#xff0c;例如食品制造业、汽车制造业、纺织业、服装制造业等等。但大家对于制造业不是很了解&#xff0c;不知道制造业也是需要采购堡垒机的&#xff0c;今天我们就来聊聊制造业采购堡垒机的必要性。 制造业采购堡垒机…

【AIGC】关于我用AI这玩意儿搞到人生第一笔副业这件事

前言 起初只是对AI感兴趣 后来没想到这玩意儿还能让我接兼职 我已经嗅到了AI的商机 接下来就是挖掘更钝金主爸爸 低收入一定要学&#xff01;&#xff01;&#xff01;&#xff01; 新手可以先从Midiourney入手 PS&#xff1a;如果不知道怎么学&#xff0c;可以扫描下方二…

76. 最小覆盖子串(困难)

76. 最小覆盖子串 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转&#xff1a;76. 最小覆盖子串 2.详细题解 在s中寻找一个最短的子串&#xff0c;使之包含t中的所有字符&#xff0c;t中可能存在多个相同字符&#xff0c;寻找的子串也应至少含有…

富豪王思聪的“爱情喜剧”从万达排片到网红聊天

王思聪&#xff0c;这位人生如戏、戏如人生的富二代&#xff0c; 在爱情的战场上可谓是屡战屡败&#xff0c;屡败屡战。 想当年&#xff0c;他向戚薇发起了猛烈的爱情攻势&#xff0c; 豪言壮语道&#xff1a;“若我以万达25%的排片量换你一笑&#xff0c;你可愿与我共舞&am…

计算机网络之数据通信原理

1.通信系统的基本组成 信源&#xff1a;信息的发出者&#xff1b; 信宿&#xff1a;信息的接收者&#xff1b; 载体&#xff1a;信息的传送通道&#xff1b; 变换器&#xff1a;将信息变换成载体上可传输的信号&#xff1b; 反变换器&#xff1a;将载体上传输的信号变换成信…

mysql GROUP_CONCAT分组连接

文章目录 GROUP_CONCAT 分组连接GROUP_CANCAT 的使用分班级列出名单分班级列出名单并包含显示性别组合IFNULL组合IF组合case when GROUP_CONCAT 分组连接 准备的数据示例 CREATE TABLE students (id int(11) NOT NULL AUTO_INCREMENT,name varchar(20) DEFAULT NULL,classNa…

如何快速交付网络基础设施运维管理软件项目?

​ 基于nVisual网络基础设施数字孪生管理工具 开发项目需求 项目交付成本节省50%、进度提高100% ​ &#xff1e;&#xff1e;&#xff1e;nVisual主要功能&#xff1c;&#xff1c;&#xff1c; 01 场 景 ★ 支持层次化的场景结构 ★ 支持多种空间场景 ​ 02 规 划 ★ 丰…

SpringBoot集成IotDB

1、引入依赖 <dependency><groupId>org.apache.iotdb</groupId><artifactId>iotdb-session</artifactId><version>0.14.0-preview1</version></dependency><dependency><groupId>cn.hutool</groupId><a…