航芯ACM32G103开发板评测 02-GPIO输入输出

航芯ACM32G103开发板评测 02-GPIO输入输出

航芯ACM32G103开发板评测 GPIO输入输出应用

  1. 软硬件平台
    ACM32G103 Board开发板
    MDK-ARM Keil
    在这里插入图片描述

  2. GPIO输出典型应用——点灯

  3. GPIO输入典型应用——按键

GPIO 功能概述

GPIO 是通用输入/输出(General Purpose I/O)的简称,主要用于工业现场需要用到数字量输入/输出的场合,例如:

  • 输出功能:继电器、 LED、蜂鸣器等的控制
  • 输入功能:传感器状态、高低电平等信息的读取
  • 复用功能:片内外设的对外接口
  • 时序模拟:模拟 SPI、I2C 和 UART 等常用接口的时序

GPIO 功能特性

  • 多种工作模式:每个 GPIO 引脚可以独立配置为输出(推挽或开漏)、输入、外设复用功能或模拟模式。每个 GPIO 引脚可以独立配置为上拉、下拉或浮空。
  • 灵活的复用模式:复用功能(AF)的备用引脚,极大提高了端口利用的灵活性。GPIO引脚通过配置相关的寄存器可以用作复用功能输入/输出引脚。
    在这里插入图片描述
    在这里插入图片描述
GPIO具体细节见航芯ACM32G103_用户手册V1.3 P393

查看acm32官方库函数文件,查看api函数

/* Exported functions --------------------------------------------------------*/
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
void GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
GPIO_PinState GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
GPIO_PinState GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin, GPIO_PinState PinState);
void GPIO_Write(GPIO_TypeDef *GPIOx, uint16_t PortVal);
void GPIO_ToggleBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
void GPIO_PinLockConfig(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);

在这里插入图片描述

GPIO输出 LED点灯

在航芯ACM32G103开发板中,一共有3个led,但是只有一个user_led可以去控制,其中,pow_led com_led作为提示作用。
接下来就是gpio端口初始化的函数简单分析。

在这里插入图片描述


#define BSP_LED_GPIO            GPIOF
#define BSP_LED_PIN             GPIO_PIN_3
#define BSP_LED_MODE            GPIO_MODE_OUTPUT_PP
#define BSP_LED_PULL            GPIO_PULLUP
#define BSP_LED_DRIVE           GPIO_DRIVE_LEVEL3
#define BSP_LED_ALTERNATE       GPIO_FUNCTION_0
#define BSP_LED_CLK_ENABLE()    __RCC_GPIOF_CLK_ENABLE()void BSP_LED_Init(void)
{GPIO_InitTypeDef  GPIO_InitStruct;/* Enable the GPIO_LED Clock */BSP_LED_CLK_ENABLE();GPIO_InitStruct.Pin       = BSP_LED_PIN;GPIO_InitStruct.Mode      = BSP_LED_MODE;GPIO_InitStruct.Pull      = BSP_LED_PULL;GPIO_InitStruct.Drive     = BSP_LED_DRIVE;GPIO_InitStruct.Alternate = BSP_LED_ALTERNATE;GPIO_Init(BSP_LED_GPIO, &GPIO_InitStruct);GPIO_WriteBit(BSP_LED_GPIO, BSP_LED_PIN, GPIO_PIN_SET);
}

ACM32G103的gpio端口初始化,与stm32等其他mcu基本上没有太大的区别。唯一的区别是GPIO_InitStruct结构体里一些成员有不同。

//stm32f103 hal
typedef struct
{uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIO_mode_define */uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.This parameter can be a value of @ref GPIO_pull_define */uint32_t Speed;     /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;//stm32f103 std
typedef struct
{uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIOSpeed_TypeDef */GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;//acm32g103 spl
typedef struct
{uint32_t    Pin;               /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins */uint32_t    Mode;              /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIO_mode */uint32_t    Pull;              /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.This parameter can be a value of @ref GPIO_pull */uint32_t    Drive;             /*!< Specifies the Output drive capability for the selected pins.This parameter can be a value of @ref GPIO_drive */uint32_t    Alternate;         /*!< Peripheral to be connected to the selected pinsThis parameter can be a value of @ref GPIOEx_function_selection */
} GPIO_InitTypeDef;

其中主要的区别是acm32中有一个指定选定引脚的输出驱动能力Drive成员,GPIOx 的 PIN驱动能力5V 耐压 IO 的驱动能力配置:

/** @defgroup GPIO_drive* @brief GPIO Output drive capability* @{*/
/*!< Output drive capability up to 2mA, please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL0                      (0x00000000U)   
/*!< Output drive capability up to 4mA, please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL1                      (0x00000001U)   /*!< Output drive capability up to 6mA, please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL2                      (0x00000002U)  
/*!< Output drive capability up to 8mA, please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL3                      (0x00000003U)   
/*!< Output drive capability up to 10mA,please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL4                      (0x00000004U)   
/*!< Output drive capability up to 12mA,please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL5                      (0x00000005U)   
/*!< Output drive capability up to 14mA,please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL6                      (0x00000006U)  /*!< Output drive capability up to 16mA,please refer to the product datasheet */
#define  GPIO_DRIVE_LEVEL7                      (0x00000007U)  

GPIO控制函数

//设置或清除选定的数据端口位。
void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin, GPIO_PinState PinState)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_ALL_PIN(GPIOx, GPIO_Pin));assert_param(IS_GPIO_PIN_STATE(PinState));if (GPIO_PIN_RESET == PinState)GPIOx->BSC = GPIO_Pin << 16U;elseGPIOx->BSC = GPIO_Pin;
}
/******************************************************************************
*@brief : LED on
*@param : none
*@return: none
******************************************************************************/
void BSP_LED_On(void)
{GPIO_WriteBit(BSP_LED_GPIO, BSP_LED_PIN, GPIO_PIN_RESET);
}/******************************************************************************
*@brief : LED off
*@param : none
*@return: none
******************************************************************************/
void BSP_LED_Off(void)
{GPIO_WriteBit(BSP_LED_GPIO, BSP_LED_PIN, GPIO_PIN_SET);
}/******************************************************************************
*@brief : LED toggle
*@param : none
*@return: none
******************************************************************************/
void BSP_LED_Toggle(void)
{GPIO_ToggleBits(BSP_LED_GPIO, BSP_LED_PIN);
}

led_example测试函数

void bsp_led_example(void)
{printfS("bsp_led_example led_flashing \r\n");BSP_LED_On();printfS("bsp_led_example led_on \r\n");DelayMs(1000);BSP_LED_Off();printfS("bsp_led_example led_off \r\n");DelayMs(500);
}

在这里插入图片描述

GPIO输入 按键控制

在航芯ACM32G103开发板中,一共有2个按键,但是只有一个user_key可以去控制,其中一个是rst复位按键。

按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开, 使用按键时会产生图 按键抖动说明图中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。

在这里插入图片描述

本实验板连接的按键带硬件消抖功能, 见图 按键原理图 ,它利用电容充放电的延时,消除了波纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可。

接下来就是按键key端口初始化的函数简单分析。

BSP_PB_Init初始化配置过程中,基本上就是GPIO端口初始化,和中断配置初始化。

在这里插入图片描述

/******************************************************************************
*@brief : PB init
*@param : none
*@return: none
******************************************************************************/
void BSP_PB_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;EXTI_InitTypeDef EXTI_InitStruct;BSP_PB_CLK_ENABLE();GPIO_InitStruct.Pin       = BSP_PB_PIN;GPIO_InitStruct.Mode      = BSP_PB_MODE;GPIO_InitStruct.Pull      = BSP_PB_PULL;GPIO_InitStruct.Drive     = BSP_PB_DRIVE;GPIO_InitStruct.Alternate = BSP_PB_ALTERNATE;GPIO_Init(BSP_PB_GPIO, &GPIO_InitStruct);EXTI_InitStruct.GPIOx     = BSP_PB_GPIO;EXTI_InitStruct.Line      = BSP_PB_PIN;EXTI_InitStruct.Mode      = EXTI_MODE_IT;EXTI_InitStruct.Trigger   = EXTI_TRIGGER_FALLING;EXTI_InitStruct.Cmd       = ENABLE;EXTI_Init(&EXTI_InitStruct);EXTI_ClearITPendingBit(BSP_PB_PIN);NVIC_ClearPendingIRQ(BSP_PB_IRQ);NVIC_SetPriority(BSP_PB_IRQ, 0x00);NVIC_EnableIRQ(BSP_PB_IRQ);
}/******************************************************************************
*@brief : get PB state
*@param : none
*@return: none
******************************************************************************/
uint32_t BSP_PB_GetState(void)
{return (GPIO_ReadPin(BSP_PB_GPIO, BSP_PB_PIN));
}
void APP_Test(void)
{uint32_t state;printfS("SPL GPIO Demo\r\n");printfS("LED flashing frequency: 1Hz.\r\n");printfS("The user presses the key to stop flashing, press the key again, and flash again.\r\n");g_press = 0;state = 0;while(1){if (g_press != 0){DelayMs(50);g_press = 0;if (state == 0)state = 1;elsestate = 0;}if (state == 0){BSP_LED_Toggle();printfS("BSP_LED_Toggle \r\n");}else{BSP_LED_Off();}DelayMs(500);};
}void EXTI15_10_IRQHandler(void)
{if (EXTI->PDR & BSP_PB_PIN){EXTI->PDR = BSP_PB_PIN;PB_IRQHandler();}
}

上面的方法是利用按键中断去判断的,下面使用MultiButton开源框架,进行按键检测。

MultiButton按键检测

MultiButton开源框架仓库 https://github.com/0x1abin/MultiButton

参考博客https://blog.csdn.net/qq_36075612/article/details/115901032

MultiButton | 一个小巧简单易用的事件驱动型按键驱动模块 https://zhuanlan.zhihu.com/p/128961191

本次使用的是博客中的版本,仓库版本的代码可能与下面代码不一样,应该是更新了代码和api。

使用方法

1.先申请一个按键结构。

2.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平。

3.注册按键事件。

4.启动按键。

5.设置一个5ms间隔的定时器循环调用后台处理函数。

//按键状态读取接口
unsigned char btn0_id = 0;
struct Button button0;uint8_t  read_button0_GPIO(void)
{return (GPIO_ReadPin(BSP_PB_GPIO, BSP_PB_PIN));
}void button_callback(void *button)
{uint32_t btn_event_val; btn_event_val = get_button_event((struct Button *)button); switch(btn_event_val){case PRESS_DOWN:printf("---> key1 press down! <---\r\n"); break; case PRESS_UP: printf("***> key1 press up! <***\r\n");break; case PRESS_REPEAT: printf("---> key1 press repeat! <---\r\n");break; case SINGLE_CLICK: printf("---> key1 single click! <---\r\n");break; case DOUBLE_CLICK: printf("***> key1 double click! <***\r\n");break; case LONG_PRESS_START: printf("---> key1 long press start! <---\r\n");break; case LONG_PRESS_HOLD: printf("***> key1 long press hold! <***\r\n");break; }
}
特性

MultiButton 使用C语言实现,基于面向对象方式设计思路,每个按键对象单独用一份数据结构管理:

struct Button {uint16_t ticks;uint8_t  repeat: 4;uint8_t  event : 4;uint8_t  state : 3;uint8_t  debounce_cnt : 3;uint8_t  active_level : 1;uint8_t  button_level : 1;uint8_t  (*hal_button_Level)(void);BtnCallback  cb[number_of_event];struct Button* next;
};

这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。

按键事件
事件说明
PRESS_DOWN按键按下,每次按下都触发
PRESS_UP按键弹起,每次松开都触发
PRESS_REPEAT重复按下触发,变量repeat计数连击次数
SINGLE_CLICK单击按键事件
DOUBLE_CLICK双击按键事件
LONG_PRESS_START达到长按时间阈值时触发一次
LONG_PRESS_HOLD长按期间一直触发
/******************************************************************************
*@brief : main program
*@param : none
*@return: none
******************************************************************************/
int main(void)
{board_hardware_init();printfS("board_hardware_init [ok] \r\n");//Timer_Update_Test();//初始化按键对象button_init(&button0, read_button0_GPIO, 0);button_attach(&button0, PRESS_DOWN,       button_callback);button_attach(&button0, PRESS_UP,         button_callback);button_attach(&button0, PRESS_REPEAT,     button_callback);button_attach(&button0, SINGLE_CLICK,     button_callback);button_attach(&button0, DOUBLE_CLICK,     button_callback);button_attach(&button0, LONG_PRESS_START, button_callback);button_attach(&button0, LONG_PRESS_HOLD,  button_callback);//启动按键button_start(&button0);while(1){//bsp_led_example();button_ticks();DelayMs(5);}}

在这里插入图片描述

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

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

相关文章

[Flutter]WindowsOS中相关配置

Flutter项目在Windows平台上如何配置 目录 Flutter项目在Windows平台上如何配置 写在开头 正文 1、OS准备 2、编译环境准备 ① 下载AndroidStudio ② 下载dart ③ 下载flutter ④ 下载并安装VS ⑤ 在AS中配置dart和flutter 3、配置中遇到的问题 写在结尾 写在开头…

C++ stack使用、模拟实现、OJ题

目录 一、介绍 二、常用函数 三、模拟实现 四、OJ练习题 1、最小栈 2、栈的压入、弹出序列 3、逆波兰表达式(后缀转中缀) 4、中缀转后缀思路 5、用栈实现队列 一、介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除…

自动驾驶论文

文章目录 一、Convolutional Social Pooling for Vehicle Trajectory Prediction二、QCNet&#xff1a;Query-Centric Trajectory Prediction三、VectorNet: Encoding HD Maps and Agent Dynamics from Vectorized Representation 一、Convolutional Social Pooling for Vehicl…

iOS 小组件开发

iOS14之后Apple引入了新的WidgetKit&#xff0c;舍弃了原有额TodayExtension。 开发准备&#xff1a; 新的WidgetExtension只能通过SwiftUI进行开发&#xff1b; Widget有三种尺寸&#xff1a;systemSmall、 systemMedium、systemLarge&#xff0c;三种尺寸对应固定的UI类型布…

BIND-DNS配置介绍

一、主要配置文件 /etc/named.conf options { //Option 段全部配置 listen-on port 53 { 127.0.0.1; };//表示BIND将在53端口监听&#xff0c;若需要对所有IP进行监听&#xff0c;则修改为// listen-on port 53 { any; }; directory "/var/named"…

(六)数码管动态刷新

文章目录 如何实现利用人眼的余晖效应&#xff08;100hz无闪烁&#xff09;1ms刷一个数码管 8个看起来就是一块亮的 结合前面内容进行操作前面内容传送门&#xff1a;如何段选原理图代码写法这里借助isp复制共阴数码管码值 如何位选原理图代码写法 如何消隐在每次 段选 赋值之前…

K8S集群部署MySql

挂载MySQL数据卷 在k8s集群中挂载MySQL数据卷 需要安装一个NFS。 在主节点安装NFS yum install -y nfs-utils rpcbind 在主节点创建目录 mkdir -p /nfs chmod 777 /nfs 更改归属组与用户 chown -R nfsnobody:nfsnobody /nfs 配置共享目录 echo "/nfs *(insecure,rw,s…

Linux操作系统基础(3):Linux终端的使用

1. Linux终端的介绍 Linux 终端是指在 Linux 操作系统下用于与用户进行交互的命令行界面&#xff08;基于文本的交互&#xff09;。它是用户与操作系统进行直接交互的主要方式&#xff0c;可以通过输入命令来执行各种操作&#xff0c;如文件管理、进程控制、系统配置等。 Lin…

【WPF.NET开发】WPF中的输入

本文内容 输入 API事件路由处理输入事件文本输入触摸和操作侧重点鼠标位置鼠标捕获命令输入系统和基元素 Windows Presentation Foundation (WPF) 子系统提供了一个功能强大的 API&#xff0c;用于从各种设备&#xff08;包括鼠标、键盘、触摸和触笔&#xff09;获取输入。 本…

CTF流量分析经典例题详解

目录 入门题型 题目&#xff1a;Cephalopod(图片提取) 题目&#xff1a;特殊后门(icmp协议信息传输) 题目&#xff1a;手机热点(蓝牙传输协议obex,数据提取) 题目&#xff1a;想蹭网先解开密码(无线密码破解) 进阶题型 题目&#xff1a;抓到一只苍蝇(数据包筛选,数据提…

蓝牙物联网智能车用语音控制系统模块设计

随着信息产业的快速发展&#xff0c;简单的控制操作机器已经不能满足人类的欲望&#xff0c;利用语音识别技术让机器理解人类的语言&#xff0c;以及实现人机交互成为新的研究内容。对用户来说&#xff0c;这种人机交互的方式当是最自然的一种方式。同时&#xff0c;使人们在车…

【Java开发岗面试】八股文—Java虚拟机(JVM)

声明&#xff1a; 背景&#xff1a;本人为24届双非硕校招生&#xff0c;已经完整经历了一次秋招&#xff0c;拿到了三个offer。本专题旨在分享自己的一些Java开发岗面试经验&#xff08;主要是校招&#xff09;&#xff0c;包括我自己总结的八股文、算法、项目介绍、HR面和面试…

小球自由下落-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第23讲。 小球自由下落&…

第一个Qt程序----Hello word!

从今天起就开始我们的第一个Qt小程序&#xff0c;点击New Project后点击右侧的Application后点击Qt Widgets Application。Qt Widgets 模块提供了一组UI元素用于创建经典的桌面风格的用户界面&#xff0c;Widgets是小部件的意思&#xff0c;也可以称为控件&#xff0c;因此Qt …

粒子群优化pso结合bp神经网络优化对csv文件预测matlab(3)

1.csv数据为密西西比数据集&#xff0c;获取数据集可以管我要&#xff0c;数据集内容形式如下图&#xff1a; 2.代码 这里参考的是b站的一位博主。 数据集导入教程在我的另一篇文章bp写过&#xff0c;需要的话可以去看一下 psobp.m close all clc%读取数据 inputX; outputY;…

(学习打卡2)重学Java设计模式之六大设计原则

前言&#xff1a;听说有本很牛的关于Java设计模式的书——重学Java设计模式&#xff0c;然后买了(*^▽^*) 开始跟着小傅哥学Java设计模式吧&#xff0c;本文主要记录笔者的学习笔记和心得。 打卡&#xff01;打卡&#xff01; 六大设计原则 &#xff08;引读&#xff1a;这里…

K8S本地开发环境-minikube安装部署及实践

引言 在上一篇介绍了k8s的入门和实战&#xff0c;本章就来介绍一下在windows环境如何使用minikube搭建K8s集群&#xff0c;好了废话不多说&#xff0c;下面就和我一起了解Minikube吧。 什么是Minikube&#xff1f; Minikube 是一种轻量级的 Kubernetes 实现&#xff0c;可在本…

【docker】安装 Redis

查看可用的 redis版本 docker search redis拉取 redis最新镜像 docker pull redis:latest查看本地镜像 docker images创建挂在文件 mkdir -pv /test1/docker_volume/redis/datamkdir -pv /test1/docker_volume/redis/confcd /test1/docker_volume/redis/conf/touch redis.con…

IPC之十二:使用libdbus在D-Bus上异步发送/接收信号的实例

IPC 是 Linux 编程中一个重要的概念&#xff0c;IPC 有多种方式&#xff0c;本 IPC 系列文章的前十篇介绍了几乎所有的常用的 IPC 方法&#xff0c;每种方法都给出了具体实例&#xff0c;前面的文章里介绍了 D-Bus 的基本概念以及调用远程方法的实例&#xff0c;本文介绍 D-Bus…