HPM6750开发笔记《GPIO例程深度解析》

目录

创建工程:

代码分析:

1.头文件包含:

2.宏定义:

3.中断服务程序(ISR):

清除中断标志:

处理 LED 状态切换:

处理用户按键状态:

处理其他情况:

4.void test_gpio_input_interrupt(void):

打印提示信息:

初始化 LED GPIO:

配置 GPIO 引脚为输入模式:

配置中断触发类型:

启用 GPIO 中断:

设置中断优先级:

进入低功耗模式:

5.void test_gpio_toggle_output(void):

打印提示信息:

初始化 LED GPIO:

循环切换 LED 状态:

打印测试完成信息:

6.int main(void)

初始化板级硬件:

测试 GPIO 输出状态切换:

测试 GPIO 输入中断:

进入无限循环:

运行现象:


创建工程:

首先还是在HPM SDK里面创建工程选项如下图:


代码分析:

/*
 * Copyright (c) 2021 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "board.h"
#include "hpm_gpio_drv.h"

#define GPIO_TOGGLE_COUNT 5

void isr_gpio(void)
{
    gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
                        BOARD_APP_GPIO_PIN);
#ifdef BOARD_LED_GPIO_CTRL
    gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                          BOARD_LED_GPIO_PIN);
    printf("toggle led pin output\n");
#else
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
    if (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == false) {
        printf("user key pressed\n");
    } else {
        printf("user key released\n");
    }
#else
    printf("user key pressed\n");
#endif
#endif

}
SDK_DECLARE_EXT_ISR_M(BOARD_APP_GPIO_IRQ, isr_gpio)

void test_gpio_input_interrupt(void)
{
    gpio_interrupt_trigger_t trigger;

    printf("input interrupt\n");
#ifdef BOARD_LED_GPIO_CTRL
    printf("user led will be switched on off based on user switch\n");
    gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                           BOARD_LED_GPIO_PIN);
#endif
    gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
                           BOARD_APP_GPIO_PIN);
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
    trigger = gpio_interrupt_trigger_edge_both;
#else
    trigger = gpio_interrupt_trigger_edge_falling;
#endif
    gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
                           BOARD_APP_GPIO_PIN, trigger);
    gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
                           BOARD_APP_GPIO_PIN);
    intc_m_enable_irq_with_priority(BOARD_APP_GPIO_IRQ, 1);
    while (1) {
        __asm("wfi");
    }
}

#ifdef BOARD_LED_GPIO_CTRL
void test_gpio_toggle_output(void)
{
    printf("toggling led %u times in total\n", GPIO_TOGGLE_COUNT);
    gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                           BOARD_LED_GPIO_PIN);
    gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                        BOARD_LED_GPIO_PIN, board_get_led_gpio_off_level());

    for (uint32_t i = 0; i < GPIO_TOGGLE_COUNT; i++) {
        gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                            BOARD_LED_GPIO_PIN);
        board_delay_ms(500);
        gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
                            BOARD_LED_GPIO_PIN);
        board_delay_ms(500);
        printf("toggling led %u/%u times\n", i + 1, GPIO_TOGGLE_COUNT);
    }
}
#endif

int main(void)
{
    board_init();
    board_init_gpio_pins();
    printf("gpio \n");

#ifdef BOARD_LED_GPIO_CTRL
    test_gpio_toggle_output();
#endif
    test_gpio_input_interrupt();

    while (1);
    return 0;
}

1.头文件包含:
#include "board.h"
#include "hpm_gpio_drv.h"

这里包含了与嵌入式系统板级支持和GPIO驱动相关的头文件。


2.宏定义:
#define GPIO_TOGGLE_COUNT 5

这个宏定义表示在测试中要切换LED状态的次数。


3.中断服务程序(ISR):
void isr_gpio(void) {
    // 处理GPIO中断
}
SDK_DECLARE_EXT_ISR_M(BOARD_APP_GPIO_IRQ, isr_gpio)

这定义了一个GPIO中断服务程序(ISR),当GPIO中断发生时执行。在中断服务程序中,通过 gpio_clear_pin_interrupt_flag 函数清除中断标志,然后根据硬件配置,切换LED状态或输出用户按键的状态。

清除中断标志
gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);
处理 LED 状态切换:
#ifdef BOARD_LED_GPIO_CTRL
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
printf("toggle led pin output\n");
处理用户按键状态:
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
if (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == false) {
    printf("user key pressed\n");
} else {
    printf("user key released\n");
}

如果硬件支持双边沿触发的中断(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT 宏被定义且等于 1),则通过 gpio_read_pin 函数检查用户按键的状态。如果按键被按下,则打印 "user key pressed";如果按键被释放,则打印 "user key released"。

处理其他情况:
#else
printf("user key pressed\n");
#endif

如果没有硬件支持双边沿触发的中断,直接打印 "user key pressed"。


4.void test_gpio_input_interrupt(void):
void test_gpio_input_interrupt(void) {
    // 测试GPIO输入中断
}
打印提示信息
printf("input interrupt\n");

打印一条提示消息,指示该函数用于测试 GPIO 的输入中断功能。

初始化 LED GPIO
#ifdef BOARD_LED_GPIO_CTRL
printf("user led will be switched on off based on user switch\n");
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
#endif

定义了 BOARD_LED_GPIO_CTRL 宏,表示存在 LED 的 GPIO 控制器,那么打印一条消息提示 LED 的状态将会根据用户开关的状态进行切换,并通过 gpio_set_pin_output 函数将 LED 的 GPIO 引脚设置为输出模式。

配置 GPIO 引脚为输入模式
gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);

通过调用 gpio_set_pin_input 函数将指定的 GPIO 引脚配置为输入模式。

配置中断触发类型
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
trigger = gpio_interrupt_trigger_edge_both;
#else
trigger = gpio_interrupt_trigger_edge_falling;
#endif
gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN, trigger);

根据硬件支持的中断触发类型,配置 GPIO 引脚的中断触发类型。如果支持双边沿触发中断,则设置 triggergpio_interrupt_trigger_edge_both,否则设置为 gpio_interrupt_trigger_edge_falling

启用 GPIO 中断
gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);

通过调用 gpio_enable_pin_interrupt 函数启用 GPIO 引脚的中断。

设置中断优先级
intc_m_enable_irq_with_priority(BOARD_APP_GPIO_IRQ, 1);

通过调用 intc_m_enable_irq_with_priority 函数,设置与 GPIO 中断相关的中断优先级。

进入低功耗模式
while (1) {
    __asm("wfi");
}

进入一个无限循环,并在循环中调用 __asm("wfi"); 进入等待中断(WFI)指令,使处理器进入低功耗模式,等待 GPIO 中断的发生。

在这个测试函数中,主要目的是配置和启用 GPIO 的输入中断,并在进入低功耗模式后等待中断的发生。当 GPIO 中断触发时,与中断相关的处理函数 isr_gpio 将被调用。这个测试函数用于验证嵌入式系统中 GPIO 输入中断的正常工作。


5.void test_gpio_toggle_output(void):
打印提示信息
printf("toggling led %u times in total\n", GPIO_TOGGLE_COUNT);

打印一条消息,指示该函数将会切换 LED 总共 GPIO_TOGGLE_COUNT 次。

初始化 LED GPIO
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, board_get_led_gpio_off_level());

使用 gpio_set_pin_output 函数将 LED 的 GPIO 引脚设置为输出模式,并使用 gpio_write_pin 函数设置 LED 的初始状态,根据板级支持的函

printf("toggling led test completed\n");

board_get_led_gpio_off_level 来确定 LED 的初始状态。

循环切换 LED 状态
for (uint32_t i = 0; i < GPIO_TOGGLE_COUNT; i++) {
    gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
    board_delay_ms(500);
    gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
    board_delay_ms(500);
    printf("toggling led %u/%u times\n", i + 1, GPIO_TOGGLE_COUNT);
}

在一个循环中,使用 gpio_toggle_pin 函数切换 LED 的输出状态,然后通过 board_delay_ms 函数延迟 500 毫秒,再次切换状态,以模拟 LED 的开关操作。在每次切换之后,打印一条消息,显示切换的次数。

打印测试完成信息
printf("toggling led test completed\n");

总体而言,test_gpio_toggle_output 函数用于测试嵌入式系统中 GPIO 输出状态切换的功能。通过在循环中切换 LED 的状态,它模拟了 LED 的开关操作,并通过打印相关信息,显示切换的次数和测试完成的消息。


6.int main(void)

int main(void) 函数是嵌入式系统中的主函数,它是程序的入口点。以下是 main 函数的主要步骤的解释:

初始化板级硬件
board_init();
board_init_gpio_pins();

调用 board_init 函数和 board_init_gpio_pins 函数,用于初始化板级硬件,包括系统时钟、GPIO 等。

测试 GPIO 输出状态切换:
#ifdef BOARD_LED_GPIO_CTRL
test_gpio_toggle_output();
#endif

定义了 BOARD_LED_GPIO_CTRL 宏,表示存在 LED 的 GPIO 控制器,那么调用 test_gpio_toggle_output 函数,测试 GPIO 输出状态切换功能。

测试 GPIO 输入中断

调用 test_gpio_input_interrupt 函数,测试 GPIO 输入中断功能。

进入无限循环

main 函数的主要作用是初始化嵌入式系统的硬件环境,然后进行 GPIO 功能的测试。具体测试的内容包括 GPIO 输出状态切换和 GPIO 输入中断。在这个例子中,通过宏的定义来判断是否存在 LED 的 GPIO 控制器,以确定是否执行 GPIO 输出状态切换的测试。无论是否进行 GPIO 输出状态切换测试,都会执行 GPIO 输入中断的测试。程序最终进入一个无限循环,保持运行状态。


运行现象:

  • 支持双沿触发模式的芯片,工程配置的是双沿触发模式,每次按键按下和释放都会翻转一次LED状态,并打印两次LED切换输出。

  • 当工程正确运行后,可以观察到LED闪烁5次,之后按下GPIO按键(请确认具体开发板 按键 部分描述)可以翻转LED的状态,串口终端会输出如下信息:

toggling led 5 times in total
toggling led 1/5 times
toggling led 2/5 times
toggling led 3/5 times
toggling led 4/5 times
toggling led 5/5 times
input interrupt
user led will be switched on off based on user switch
toggle led pin output
toggle led pin output

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++核心编程(二)】

一、类和对象 C面向对象的三大特性为:封装、继承、多态。 C认为万事万物都皆为对象&#xff0c;对象上有其属性和行为。 例如: 人可以作为对象&#xff0c;属性有姓名、年龄、身高、体重...&#xff0c;行为有走、跑、跳、吃饭、唱歌... 车也可以作为对象&#xff0c;属性…

kbdnecat.DLL文件缺失,软件或游戏无法启动运营,快速修复方法

“kbdnecat.DLL文件是什么&#xff1f;为什么一起动游戏或软件&#xff0c;Windows就报错“kbdnecat.DLL文件缺失&#xff0c;软件无法启动””&#xff0c;应该怎么修复呢&#xff1f; 首先&#xff0c;先来了解“kbdnecat.DLL文件”是什么&#xff1f; kbdnecat.DLL是一个动…

TCP_可靠数据传输原理

引言 在网络通信中&#xff0c;TCP是确保数据可靠传输的关键协议。但在我们深入研究TCP拥塞控制技术之前&#xff0c;让我们先探索可靠数据传输的原理&#xff0c;特别是TCP头部中一些重要字段的作用。 网络层提供了点对点的通信服务&#xff0c;努力交付数据报&#xff0c;但…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)在EventLoop的任务队列中添加新任务

任务队列是一个链表&#xff0c;每个节点包含channel类型、文件描述符和操作类型。在添加节点时&#xff0c;需要考虑线程同步&#xff0c;并确保节点被正确地添加到链表中。节点的操作可以写到另一个函数中&#xff0c;以便于程序的维护。在添加任务节点时&#xff0c;需要加互…

Peter算法小课堂—动态规划

Peter推荐算法书&#xff1a;《算法导论》 图示&#xff1a; 目录 钢条切割 打字怪人 钢条切割 算法导论&#xff08;第四版&#xff09;第十四章第一节&#xff1a;钢条切割 题目描述&#xff1a; 给定一根长度为 n 英寸的钢条和一个价格表 &#xff0c;其中 i1,2,…,n …

后台管理系统 -- 点击导航栏菜单对应的面包屑和标签(Tag)的动态编辑功能

相信很多时候,面包屑和标签(Tag)的功能几乎是后台管理系统标配。 就是会随着路由的跳转来进行相应的动态更新。 我先展示一下效果: 1.面包屑 先说一下思路&#xff1a; 我们导航菜单点击之后,将当前显示路由对象存储到Vuex的storge里面,然后在面包屑组件里面,读取这个状态即可…

初识大数据,一文掌握大数据必备知识文集(9)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

数字化制造安全防线:迅软DSE助力通用设备企业终端安全卫士

客户简要介绍 某公司是一家主要生产新型激光打印机、喷墨打印机、其它打印机、精密多功能机、传真机等办公自动化用品的企业。公司与顾客建立长期的信赖忠诚关系”的方针&#xff0c;逐步完善公司的各项运营&#xff0c;不断扩充市场前景。产品除国内销售外&#xff0c;还销往…

使用 go-elasticsearch v8 基本请求

使用 go-elasticsearch 请求示例 你可以通过参考Go 官方文档找到简单的示例&#xff0c;所以我认为先看看这个是个好主意。 连接客户端有两种方式&#xff0c;如下图。 至于两者的特点&#xff0c;TypedClient有类型&#xff0c;更容易编写&#xff0c;但文档较少。另外&…

利用码云(Gitee)与IDEA轻松管理远程代码库的完整指南

目录 前言1 码云简介2 码云上创建远程库3 IDEA集成码云的步骤3.1 安装Gitee插件并建立连接3.2 项目分享到码云3.3 拉取代码 4 码云复制Github4.1 迁移github项目到码云4.2 代码同步 结语 前言 在软件开发领域&#xff0c;代码托管平台是开发者不可或缺的利器。Github作为全球最…

uniapp中uview组件丰富的Code 验证码输入框的使用方法

目录 基本使用 #自定义提示语 #保持倒计时 API #Props #Methods #Event 基本使用 通过ref获取组件对象&#xff0c;再执行后面的操作&#xff0c;见下方示例。 通过seconds设置需要倒计的秒数(默认60)通过ref调用组件内部的start方法&#xff0c;开始倒计时通过监听cha…

梯度下降算法 寻找函数最小值 找最快下山路线 python写个梯度下降算法示例

梯度下降算法是一种用于寻找函数最小值的优化算法。 它在机器学习和深度学习中被广泛使用&#xff0c;特别是在训练神经网络时。我们可以通过一个简单的生活中的例子来理解它&#xff1a; 想象你在一座山上&#xff0c;需要找到最快的路线下山。你不能一眼看到最低点&#xf…

RKE安装k8s及部署高可用rancher

一 了解 Rancher 1 推荐架构 安装 Rancher 的方式有两种&#xff1a;单节点安装和高可用集群安装。因为单节点安装只适用于测试和 demo 环境&#xff0c;而且单节点安装和高可用集群安装之间不能进行数据迁移&#xff0c;所以推荐从一开始就使用高可用集群安装的方式安装 Ran…

Java经典框架之SpringDataJPA

SpringDataJPA Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Spring整合Hibernate 2…

解决Gitlab Prometheus导致的磁盘空间不足问题

解决Gitlab Prometheus导致的磁盘空间不足问题 用docker搭建了一个gitlab服务&#xff0c;已经建立了多个项目上传&#xff0c;但是突然有一天就503了。 df -TH查看系统盘&#xff0c;发现已经Used 100%爆满了。。。 &#x1f4a1;Tips&#xff1a;/dev/vda1目录是系统盘目录。…

x-cmd pkg | lazygit - git 命令的终端 UI

目录 简介首次用户功能特点类似工具与竞品进一步探索 简介 lazygit 由 Jesse Duffield 于 2018 年使用 Go 语言构建的 git 终端交互式命令行工具&#xff0c;旨在终端界面中便捷管理 git 存储库。 首次用户 使用 x lazygit 即可自动下载并使用 在终端运行 eval "$(curl …

Qt实现文本编辑器(二)

上一章节讲述了如何制作文本编辑页面&#xff0c;以及应该有哪些功能需要实现&#xff0c;只是做了展示效果&#xff0c;实际的点击事件并没有处理。今天来具体讲解下是如何实现菜单栏以及工具栏上对应的需求吧~ 功能实现 功能&#xff1a; 1、动作消息触发 2、具体功能&am…

vue +elementui 项目登录通过不同账号切换侧边栏菜单的颜色

前景提要&#xff1a;要求不同权限账号登录侧边栏颜色不一样。分为 theme&#xff1a;1代表默认样式&#xff0c;theme:2代表深色主题样式。 1.首先定义一个主题文件 theme.js&#xff0c;定义两个主题样式 // 主要是切换菜单栏和菜单头部主题的设计&#xff0c;整体主题样式切…

electron进程通信之预加载脚本和渲染进程对主进程通信

主进程和预加载脚本通信 主进程 mian,js 和预加载脚本preload.js,在主进程中创建预加载脚本, const createWindow () > {// Create the browser window.const mainWindow new BrowserWindow({width: 300,height: 300,// 指定预加载脚本webPreferences: {preload: path.j…

基于rockpi4b启动流程(2)

uboot启动kernel 基于上篇文章,将开发板烧录loder和system镜像,即可开机进console。 我们将系统停到uboot命令行,printenv看下环境变量 => printenv arch=arm baudrate=1500000 board=evb_rk3399 board_name=evb_rk3399 boot_a_script=load ${devtype} ${devnum}:${di…