查看原文
其他

基于面向对象思维的STM32开发基本思路--以GPIO口的操作为例

野生程序猿 电子开发学习 2021-01-31


开发单片机也都是用C语言较多,大多数都是面向过程编程。这样很容易造成全局变量满天飞,变量声明来回穿插的局面,这种现象是很不好的,往往会牵一发而动全身,不利于代码维护和后期移植。群友“野生程序猿”分享了一个自己对标准库的封装,采用面向对象的思想来封装库,进而可以高效的进行开发。感谢群友“野生程序猿”的分享。


正文开始:


Stm32的标准库很多人都在用,相对于寄存器来说开发效率高很多,很利于新手入门。但是作者在使用了Stm32标准库以来的心得就是,重复工作做的太多。Stm32标准库里面的结构体成员太多了,每次使用都需要查固件库手册,配置一个外设需要的步骤也很多,搞错一个步骤都会造成配置外设失败。以至于每次开发新工程,大多数人写代码都会选择从原来的工程里面复制,不会自己重新编写。

简单举个例子,使用标准库控制一个LED(操作一个IO),需要的步骤有哪些?

1、新建一个GPIO_InitTypeDef结构体

GPIO_InitTypeDef GPIO_InitStruct; 


2、开启时钟,首先要查阅手册确定GPIO所挂载的时钟总线,找到开启时钟的函数RCC_APB2PeriphClockCmd,然后开启GPIOx的时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 


3、填充结构体,根据用途填充结构体成员,包含模式、速率、管脚号等

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;


4、初始化结构体指针

GPIO_Init(GPIOB, &GPIO_InitStruct);


5、操作IO

GPIO_SetBits(GPIOB,GPIO_Pin_8);
GPIO_ResetBits(GPIOB,GPIO_Pin_9);


到此,一个IO初始化完成。操作IO也是有响应的库函数,需要填入GPIOx和GPIO_Pin_x等参数,这些参数就需要和初始化的端口一致,要不然操作也不会成功。整体给人的感觉逻辑特别乱。

很多人移植程序的时候总会出错,很多是忘记修改时钟部分,还有是忘记修改端口号,层层调试找Bug。想给LED更换一个端口的时候,工程里面所有相关的与LED相关的操作都要修改。这就是前面说的,移植效率很低。当然这个也可以通过宏定义或者位带操作来进行简化,但这不是我们今天的主题。

下面给大家介绍一种基础的面向对象方式开发STM32的GPIO的方式。这是作者自己对stm32标准库中GPIO部分stm32f10x_gpio进行二次封装,除去了繁杂的配置步骤,省略了枯燥的查手册过程。将这个库函数初步命名为stm32f10x_gpio_simp,后缀simp就是simple的缩写,就是简单的意思,目的是为了让stm32的开发更简单,不用在底层配置浪费很多时间,让精力都放在上层应用算法的开发上。自己一直在用,开发效率确实很高,面向对象的操作方式也让人很舒服。现在分享给大家一起探讨一下。废话不多说,先教大家怎么用。

举例:我需要创建两个LED和一个KEY按键

1、将stm32f10x_gpio_simp.c文件包含到工程中,

2、在需要的位置#include"stm32f10x_gpio_simp.h"包含头文件

3、新建结构体,根据自己的外设命名并填入GPIOx和GPIO_Pin_x

Stm32f10x_GPIO_Typedef KEY = {     //创建一个按键端口
.GPIOx= GPIOA,
.GPIO_Pin= GPIO_Pin_0
};

Stm32f10x_GPIO_Typedef LED = {     //创建一个LED端口
    .GPIOx = GPIOA,
    .GPIO_Pin = GPIO_Pin_1
};

Stm32f10x_GPIO_Typedef LED1 = {    //创建一个LED1端口
    .GPIOx = GPIOA,
    .GPIO_Pin = GPIO_Pin_2
};


4、根据需求配置端口模式

_stm32f10x_gpio_setin_Mode_IPU(KEY);   //配置KEY端口上拉输入模式

_stm32f10x_gpio_setout_Mode_PP(LED);   //配置LED端口推挽输出模式

_stm32f10x_gpio_setout_Mode_PP(LED1);  //配置LED端口推挽输出模式


stm32f10x_gpio_simp里面有一系列配置操作库函数,入口参数均为的外设名称,所有IO操作均使用这种方式。具体可以到stm32f10x_gpio_simp.h中查看。这个库函数执行完成以后,将会对GPIO的时钟、模式等一系列参数全部配置,使用者不用再关心这些细节工作。

5、根据需求读取IO端口或者控制IO输出。所有操作函数入口参数均为外设名。


if (RESET == _stm32f10x_gpio_in(KEY)){        //检测KEY端口状态
stm32f10x_gpio_out_h(LED);                //LED置高
_stm32f10x_gpio_out_invers(LED1);         //LED1端口输出反转
}
else{
_stm32f10x_gpio_out_l(LED);               //LED低
}


至此我们的IO操作就完成了。大概思路可以看出来,所有IO操作均是对结构体对象操作的。这样有几点好处:

1、使程序易读性更强,后期更好维护。

2、修改端口时,修改结构体参数即可。移植更方便。

3、随用随建,开发更快。


后续还会分享基于这种思维点亮一个RGB灯以及实现呼吸灯的实例。


simp库函数,里面包含.c和.h,使用时添加进工程即可。需要这个工程文件的可以添加微信客服为好友, 微信客服微信号:electricstudyer,二维码如下:



历史好文集合(点击标题可跳转):

四轴学习课程连接、资料分享、交流群汇总

PCB设计就别再用AD了,有更好的选择!

[飞控]从零开始建模(一)-牛顿欧拉方程

开源STM32F1小四轴完整资料发布一(源代码、原理图、3D库、PCB)

如何制作炫酷的PCB板3D效果图

灵动微MM32F103C8T6使用初体验

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存