通过数组和枚举简化GPIO操作编码



        在工作中,经常遇到大量使用GPIO作为数字量输入输出来控制设备或采集状态,每次定义操作不同的GPIO针脚既麻烦又容易出错,于是就想要简化操作过程。对于数字量输入来说就是采集对应针脚的状态;而输出则是根据逻辑关系置位或复位对应得针脚。

        为了使用方便,我们按可复用和经常变化的部分叫软件的实现划分为2个部分。相对固定的部分我们封装成操作函数供调用,对于经常变化的部分(如硬件配置等)我们另外实现,并调用前面封装的函数实现功能。

        现在我们只要实现了通用性较好的函数封装,剩下就是调用来实现具体控制的问题。那么怎么封装这些函数呢?

        我们首先定义两个枚举类型分别定义如下:

//定义数字量输出通道枚举类型,规定通道的范围
typedef enum {DOChannel1,DOChannel2,DOChannel3,DOChannel4,DOChannel5,DOChannelNum
} DigitalOutput;//定义数字量输入通道枚举类型,规定通道的范围
typedef enum {DIChannel1,DIChannel2,DIChannel3,DIChannel4,DIChannel5,DIChannelNum
} DigitalInput;

        数字量输入输出的枚举主要是为了方便操作和识别,通道数量出现变化时只需要增加枚举两种的通道定义即可。此处数字量输入输出均定义了5个通道。枚举量的最后一个成员代表了通道的数量,在枚举全部通道时能够很好的避免超出范围的错误。

        同时还要定义如下的结构体,用于定义需要操作GPIO目标。

//定义用于针脚操作的目标针脚类型
typedef struct{GPIO_TypeDef* GPIOx;uint16_tGPIO_Pin;
}TargetPin;

        有了上述的定义则可以实现前面设想的操作了,接下来我们还需要定义两个数字量输入输出通道的TargetPin类型的数组,用于存放想要操作的目标通道,和前面枚举两种定义的通道一致,此处也是5个通道。

//定义DI通道的全部目标针脚数组
TargetPindiPin[]={{GPIOE,GPIO_Pin_2},{GPIOE,GPIO_Pin_3},{GPIOE,GPIO_Pin_4},{GPIOE,GPIO_Pin_5},{GPIOE,GPIO_Pin_6}};//定义DO通道的全部目标针脚数组
TargetPindoPin[]={{GPIOD,GPIO_Pin_3},{GPIOD,GPIO_Pin_4},{GPIOD,GPIO_Pin_5},{GPIOD,GPIO_Pin_6},{GPIOD,GPIO_Pin_7}};

        有了以上2个数组就可以在避免在操作过程中大量使用条件分支语句(Switch或if语句),简化编码和避免在增加通道时号要修改函数的情况。现在如果通道数量出现变化则只需要修改枚举量和数组的值就可。或者操作的管脚出现变化则只需要修改数组的值就可以了。而不需要去修改函数体,而且函数体的编码也非常简单。

        对数字量输出的操作如下,在操作全部通道时,以枚举变量作为循环变量,以枚举的最后定义的数量来控制,并以枚举量的取值作为数组下标,有效避免出现超出范围的错误,同时在通道数量和通道对应的具体针脚发生变化时,无需修改函数。

//操作全部继电器DO通道
//输入参数TargetPin *doPin为要操作的DO通道列表
//输入参数BOOL *commands欲写给DO通道的值列表
void OperationAllRelayChannel(TargetPin*doPin,BOOL *commands)
{DigitalOutputDOChannel;for(DOChannel=DOChannel1;DOChannel<DOChannelNum;DOChannel++){OperationSingleRelayChannel(doPin[DOChannel],commands[DOChannel]);}
}//操作单个继电器DO通道
//输入参数TargetPin doPin为要操作的DO通道
//输入参数BOOL command欲写给DO通道的值
void OperationSingleRelayChannel(TargetPindoPin,BOOL command)
{if(command==True){GPIO_SetBits(doPin.GPIOx,doPin.GPIO_Pin);}else{GPIO_ResetBits(doPin.GPIOx,doPin.GPIO_Pin);}
}

        对数字量输入的操作函数的编写采用与数字量输出相同的思路。对于枚举之所以可以用作数组下标,是因为枚举没被指定值时,总是从0开始向上累加,正好与数组下标是一致的。这要做还有一个好处是,通道与具体的GPIO引脚是由TargetPin数组的赋值顺序决定的,修改非常方便。

//获取全部DI量状态输入值
//输入参数TargetPin *diPin为需要读取的DI通道列表
//输入参数BOOL *result为读取的通道值返回列表
void GetAllDIStatusInput(TargetPin *diPin,BOOL*result)
{DigitalInputDIChannel;for(DIChannel=DIChannel1;DIChannel<DIChannelNum;DIChannel++){result[DIChannel]=GetSingleDIStatusInput(diPin[DIChannel]);}
}//获取单个DI量状态输入值
//输入参数TargetPin diPin是需要读取的DI通道
//返回值为读取的通道值
BOOL GetSingleDIStatusInput(TargetPin diPin)
{uint8_treadValue;readValue= GPIO_ReadInputDataBit(diPin.GPIOx,diPin.GPIO_Pin);return(readValue>0)?True:False;
}

        通过以上的编码操作DI、DO已经很方便了,但在操作单个DO通道的函数中还有一个if…else语句给人的感觉比较不太好。因为操作简单就是置位和复位,所以我们定义一个指向函数的指针数组,如下:

/*定义操作GPIO管脚的函数指针*/
void (*OperationGPIOBits[])(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)={GPIO_ResetBits,GPIO_SetBits};

        有了这个指向函数的指针数组我们可以将上面的操作单个DO通道的函数简化为如下:

//操作单个继电器DO通道
//输入参数TargetPin doPin为要操作的DO通道
//输入参数BOOL command欲写给DO通道的值
void OperationSingleRelayChannel(TargetPindoPin,BOOL command)
{OperationGPIOBits[command](doPin.GPIOx,doPin.GPIO_Pin);
}

        其中command是一个布尔变量取值为0和1,正好与指向函数的指针数组对应,实现在command取不同值时,调用复位或置位函数。

        以上代码在IAR EWARM和STM32F103VET平台测试正确。

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

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

相关文章

【论文党福利】如何提取图像中的数据

【论文党福利】如何提取图像中的数据 从事科研的老师和同学们在撰写论文时&#xff0c;经常需要将文献中的曲线与自己的结果进行对比&#xff0c;为获取原始数据&#xff0c;最靠谱的方法当然是找原作者要。如果没有要到呢&#xff1f;本文将成为论文党的福利&#xff0c;为你…

添加串口和虚拟终端输出帮助调试

&#xfeff;&#xfeff;在使用IAR开发STM32项目时&#xff0c;使用串口或者是虚拟终端来输出我们想看的信息是一个非常好而且简便的方式。 首先来看看串口怎么实现信息输出。简单来说串口输出信息就是将标准输出重定向到串口&#xff0c;在上位机的超级终端或者串口助手等工…

1.1股票数据预处理练习

第一阶段、一个简单策略入门量化投资 1.1股票数据预处理练习 无论我们要对股票市场进行何种探索&#xff0c;在开始前&#xff0c;研究如何获取数据&#xff0c;并进行对应的预处理都是必要的。 本节以美股为例&#xff0c;进行股票数据预处理的练习。正文如下&#xff1a; …

1-2 移动均线交叉策略1

第一阶段、一个简单策略入门量化投资 1-2 移动均线交叉策略1 第一阶段一个简单策略入门量化投资1-2 移动均线交叉策略1前言获取数据移动均线交叉策略数据可视化绘制折线图绘制K线图绘制移动均线 移动均线交叉策略回测什么是回测回溯买卖信号计算收益 未完待续完整代码 前言 …

STM32F412应用开发笔记之一:初识NUCLEO-F412ZG

&#xfeff;&#xfeff;今天终于收到了期待已久的NUCLEO-F412ZG&#xff0c;感谢电子发烧友论坛&#xff01; 近几年来基本都是在STM32平台上做一些设计开发工作。STM32F103、STM32F107、STM32F429等都应用过&#xff0c;但却从没有申请过试用。没想到这次申请居然能被选中&a…

STM32F412应用开发笔记之二:基本GPIO控制

&#xfeff;&#xfeff;NUCLEO-F412ZG板子上的元器件并没有完全焊接&#xff0c;除去ST-LINK部分和电源部分后&#xff0c;还有用一个USB主机接口&#xff0c;三个LED灯和两个按钮&#xff0c;不过很多功能引脚都已经引到了插针。查看原理图可发现&#xff0c;由原理图模块的…

1-3移动均线交叉策略2

第一阶段、一个简单策略入门量化投资 1-3移动均线交叉策略2 上一篇文章1-2 移动均线交叉策略1中我们最后提到&#xff1a; 如果我们从第一天买入股票&#xff0c;一直持有股票&#xff0c;最后一天卖出&#xff0c;获得的收益是每股124.02美元&#xff0c;收益率为412% 如果…

1-4移动均线交叉策略3

第一阶段、一个简单策略入门量化投资 1-4移动均线交叉策略3 上一文1-3移动均线交叉策略2中&#xff0c;我们得到的结果是令人失望的。但我们的探索还要继续。 我们知道&#xff0c;使用投资组合的方式进行分散投资是降低风险的好办法。尽管移动均线交叉策略的表现并不理想&a…

STM32学习及应用笔记一:SysTick定时器学习及应用

&#xfeff;&#xfeff; 这几年一直使用STM32的MCU&#xff0c;对ARM内核的SysTick计时器也经常使用&#xff0c;但几乎没有仔细了解过。最近正好要在移植一个新的操作系统时接触到了这块&#xff0c;据比较深入的了解了一下。 1、SysTick究竟是什么&#xff1f; 关于SysT…

使用Atom快速打造好用的Markdown编辑器

使用Atom快速打造好用的Markdown编辑器 Atom当前主流的跨平台的三大编辑器(Atom,sublime,vscode)之一 今天尝试了使用Atom来打造Markdown编辑器&#xff0c;快速上手且易用&#xff0c;墙裂推荐&#xff01; 下面直接进入正题&#xff0c;一步步介绍如何使用Atom快速打造好用…

PID控制器开发笔记之一:PID算法原理及基本实现

&#xfeff;&#xfeff; 在自动控制中&#xff0c;PID及其衍生出来的算法是应用最广的算法之一。各个做自动控制的厂家基本都有会实现这一经典算法。我们在做项目的过程中&#xff0c;也时常会遇到类似的需求&#xff0c;所以就想实现这一算法以适用于更多的应用场景。…

十分钟能学会的简单python爬虫

简单爬虫三步走&#xff0c;So easy~ 本文介绍一个使用python实现爬虫的超简单方法&#xff0c;精通爬虫挺难&#xff0c;但学会实现一个能满足简单需求的爬虫&#xff0c;只需10分钟&#xff0c;往下读吧~ 该方法不能用于带有反爬机制的页面&#xff0c;但对于我这样的非专业…

PID控制器开发笔记之二:积分分离PID控制器的实现

前面的文章中&#xff0c;我们已经讲述了PID控制器的实现&#xff0c;包括位置型PID控制器和增量型PID控制器。但这个实现只是最基本的实现&#xff0c;并没有考虑任何的干扰情况。在本节及后续的一些章节&#xff0c;我们就来讨论一下经典PID控制器的优化与改进。这一节我们首…

利用python实现短信和电话提醒功能

有时候&#xff0c;我们需要程序帮我们自动检测某些事件的发生 这个需求是广泛存在的 因此&#xff0c;这里整理了利用python实现短信和电话提醒功能的方法 主要需要完成以下4个步骤&#xff1a; - 安装核心库&#xff1a;twilio - 注册账号及配置 - 发送短信示例 - 电话…

PID控制器开发笔记之三:抗积分饱和PID控制器的实现

积分作用的引入是为了消除系统的静差&#xff0c;提高控制精度。但是如果一个系统总是存在统一个方向的偏差&#xff0c;就可能无限累加而进而饱和&#xff0c;极大影响系统性能。抗积分饱和就是用以解决这一问题的方法之一。这一节我们就来实现抗积分饱和的PID算法。 1、抗积…

Git 忽略编译后文件

当我们第一次对某个Git仓库中的项目进行编译后&#xff0c;未追踪的文件通常有两类。 一类是项目新增但还未提交的文件&#xff0c; 另一类是像 .pyc、.obj、.exe 等编译后的二进制文件。 显然前者应该出现在 git status 的输出中&#xff0c;而后者会让我们困惑究竟发生了什…

如何获取STM32 MCU的唯一ID

前段时间由于应用需要对产品授权进行限制&#xff0c;所以研究了一下有关STM32 MCU的唯一ID的资料&#xff0c;并最终利用它实现了我们的目标。 1、基本描述 在STM32的全系列MCU中均有一个96位的唯一设备标识符。在ST的相关资料中&#xff0c;对其功能的描述有3各方面&#x…

SHA256算法原理详解

1. SHA256简介 SHA256是SHA-2下细分出的一种算法 SHA-2&#xff0c;名称来自于安全散列算法2&#xff08;英语&#xff1a;Secure Hash Algorithm 2&#xff09;的缩写&#xff0c;一种密码散列函数算法标准&#xff0c;由美国国家安全局研发&#xff0c;属于SHA算法之一&…

学习笔记:区块链概念入门

本文是100天区块链学习计划的第二篇学习笔记&#xff0c;其实就是按照阮一峰的网络日志-区块链入门教程的讲解进行的简单梳理。也是时间有点紧张的原因&#xff0c;相比于上一篇SHA256算法原理详解&#xff0c;个人感觉质量和原创程度明显下降。待对区块链有了更深的理解后&…

PID控制器开发笔记之四:梯形积分PID控制器的实现

从微积分的基本原理看&#xff0c;积分的实现是在无限细分的情况下进行的矩形加和计算。但是在离散状态下&#xff0c;时间间隔已经足够大&#xff0c;矩形积分在某些时候显得精度要低了一些&#xff0c;于是梯形积分被提出来以提升积分精度。 1、梯形积分基本思路 在PID控制…