OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...

查看: 419|回复: 24

发福利了!!! 奉献一个我自己编写的超级方便的GPIO端口配置函数,寄存器版本和库函数版本均可使用

[复制链接]

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
发表于 7 天前 | 显示全部楼层 |阅读模式
正点原子公众号
本帖最后由 warship 于 2018-7-14 11:46 编辑

GPIO端口的配置是每个程序都要用到的,
并且还不止配置一个,如LED灯、键盘、IO控制端口等等,
用库函数则每配置一个端口就一堆代码,看着头疼。
用寄存器版本则很不直观,
今天我看原子的寄存器版本有一个外部中断配置的函数,
用起来很方便,受到启发,
就着手参考优化了库函数的原型代码(分析了才知道这个库函数的版本效率很低,居然用到for循环!!)
编了这个GPIO的端口配置函数。

已经实测通过,超级好用,不敢独占,贴出来给大家分享一下,
无论你是用库函数编程,还是用寄存器编程都可以使用。
*************** 华丽的分界线 *******************************


有了这个配置函数,今后的GPIO配置就超级清爽了,
比如两个LED灯,三个按键的配置,
原先有一大堆的代码,既杂乱又哆嗦,
现在只须如下代码(示例):

//配置PA8和PD2为LED指示灯
My_GPIO_Init(GPIO_A, 8, Mode_Out_PP, Speed_50MHz);    //LED0
My_GPIO_Init(GPIO_D, 2, Mode_Out_PP, Speed_50MHz);    //LED1

//配置三个按键PC1 、PC13、PA0
My_GPIO_Init(GPIO_C, 1, Mode_IPU, 0);     //配置KEY1按键   
My_GPIO_Init(GPIO_C, 13, Mode_IPU, 0);   //配置KEY2按键
My_GPIO_Init(GPIO_A, 0, Mode_IPD, 0);    //配置WK_UP按键
******************************************************************
应网友要求,在21楼修改了原子的试验5(外部中断试验)作为范例,
现将附件移到顶楼,方便下载测试。
附件的sys.c文件中,对原子代码不合理的部分进行了修改(文件中有注释说明),
扩展并使用了我最新研究成果,直接进行位段操作,
用位段操作编出来的代码更高效、程序的可读性更强,更容易理解上手。大家可以与原子的源码进行对比,就会有体会了。
有问题欢迎提出来讨论交流哈。
关于位段操作的研究讨论可移步http://www.openedv.com/forum.php ... 4196&extra=page%3D1





EXTI_TEST.zip

136.08 KB, 下载次数: 22

0714更新

回复

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
本帖最后由 warship 于 2018-7-14 18:57 编辑

以下是底层实现代码:建议复制后直接放在SYS.C文件中
**************************************************************************************
//GPIO端口配置函数
//
//输入参数:
//GPIOx:直接填写0~6代表GPIOA~G, 或使用宏定义
//BITx: 端口位号(即端口数字号,如PA4则参数为4)
//Mode: 端口模式,共8种,请使用模式的宏定义或直接填写数值,
//      函数不检查该参数,请勿超出这8种的范围自创模式!!!
//Speed:端口速度, 共3种,请使用速度的宏定义或直接填写数值(1/2/3),
//      该参数仅在输出模式下有作用,设输入模式时,可以随便填一个值
//返回值: 无. 端口组或端口号超出范围时将直接返回.
//该函数没有使用库函数, 使用时也无须包含stm32f10x_gpio.h
//使用示例:  My_GPIO_Init(GPIO_D, 5, Mode_Out_OD, Speed_50MHz); 即可设置PD5为开漏输出

void My_GPIO_Init(u8 GPIOx, u8 BITx, u8 Mode, u8 Speed)
{
  
  GPIO_TypeDef *pAddr;     //指向GPIO寄存器组基址的地址指针
        
  u32 currentmode = 0x00, pinpos = 0x00, pos = 0x00;
  u32 tmpreg = 0x00, pinmask = 0x00;
        
  if(GPIOx>6 || BITx>15) return;  //端口参数超出范围,直接返回
        
  pAddr=(GPIO_TypeDef *)(GPIOA_BASE+0x400*GPIOx); //计算对应的GPIO端口基址, 每组端口占用地址空间为400H
  
/*---------------------------- GPIO 模式配置 -----------------------*/
  currentmode = ((u32)Mode) & ((u32)0x0F); //取模式参数低4位存入currentmode
  if ( Mode & 0x10) //如果第5位为1,则为输出模式
   {
    currentmode |= (u32)(Speed & 0x03);  //仅在输出模式下,速度参数才有效
   }
/*---------------------------- GPIO CRL 配置 ------------------------*/
  if ( BITx <8 )  //如果端口线号<8, 则配置CRL
  {
    pinpos=BITx;
    tmpreg = pAddr->CRL;         //取CRL原有值
    pos = pinpos << 2;           //BIT位置计算,每线占4BIT
    /* 清0相应的CRL寄存器BIT位 */
    pinmask = ((u32)0x0F) << pos;
    tmpreg &= ~pinmask;
    /* 写模式配置相应的BIT位 */
    tmpreg |= (currentmode << pos);
    pAddr->CRL = tmpreg; //完成CRL配置
  }
/*---------------------------- GPIO CRH 配置 ------------------------*/
  else   //端口线号>=8, 则配置CRL
  {
    tmpreg = pAddr->CRH;  //取CRH原有值
    pinpos=BITx-0x08;
    pos = pinpos << 2;
        /* 清0相应的CRH寄存器BIT位 */
    pinmask = ((u32)0x0F) << pos;
    tmpreg &= ~pinmask;
     /* 写模式配置相应的BIT位 */
    tmpreg |= (currentmode << pos);
    pAddr->CRH = tmpreg; //完成CRH配置
  } //最后如果是上拉下拉输入模式,则初始化一下相应端口电平
  if (Mode == Mode_IPD) pAddr->BRR=1<<BITx;  /* 对于下拉输入模式,则复位端口 */
  else if(Mode == Mode_IPU) pAddr->BSRR=1<<BITx;  /* 对于上拉输入模式,则置位端口 */      
}


回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
本帖最后由 warship 于 2018-7-12 19:31 编辑

用到的宏定义:
#define        Mode_AIN                                                        0x0   //模拟输入
#define        Mode_IN_FLOATING                        0x04        //浮空输入
#define        Mode_IPD                                                        0x28        //下拉输入
#define        Mode_IPU                                                        0x48        //上拉输入

#define        Mode_Out_OD                                                0x14        //开漏输出
#define        Mode_Out_PP                                                0x10        //推挽输出
#define        Mode_AF_OD                                                0x1C        //复用开漏
#define        Mode_AF_PP                                                0x18        //复用推挽        

#define        Speed_10MHz                                                0x1
#define        Speed_2MHz                                                0x2
#define        Speed_50MHz                                                0x3
//以下宏定义是原子版本已有的
#define GPIO_A             0
#define GPIO_B             1
#define GPIO_C             2
#define GPIO_D             3
#define GPIO_E             4
#define GPIO_F             5
#define GPIO_G            6

回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
因为这个配置函数是必须且经常用到的,
可以作为系统基本函数。
建议增加到原子工程的sys.c文件中,
宏定义放在sys.h文件中
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
正点原子公众号
本帖最后由 warship 于 2018-7-12 19:32 编辑

有了这个配置函数,今后的GPIO配置就超级清爽了,
比如两个LED灯,三个按键的配置,
原先有一大堆的代码,既杂乱又哆嗦,
现在只须如下代码(示例):

//配置AP8和PD2为LED指示灯
My_GPIO_Init(GPIO_A, 8, Mode_Out_PP, Speed_50MHz);    //LED0
My_GPIO_Init(GPIO_D, 2, Mode_Out_PP, Speed_50MHz);    //LED1

//配置三个按键PC1 、PC13、PA0
My_GPIO_Init(GPIO_C, 1, Mode_IPU, 0);     //配置KEY1按键   
My_GPIO_Init(GPIO_C, 13, Mode_IPU, 0);   //配置KEY2按键
My_GPIO_Init(GPIO_A, 0, Mode_IPD, 0);    //配置WK_UP按键

回复 支持 反对

使用道具 举报

  离线 

18

主题

511

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1142
金钱
1142
注册时间
2016-4-29
在线时间
175 小时
发表于 7 天前 | 显示全部楼层
谢谢分享,收藏了
回复 支持 反对

使用道具 举报

  离线 

2

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2017-1-31
在线时间
7 小时
发表于 7 天前 | 显示全部楼层
确实方便不少,而且真的很多类似的其它配置都可以这样,要是官方固件库或者原子库里有这样的一些初始化设置函数真的就方便多了
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
一毛零Logo 发表于 2018-7-12 21:45
确实方便不少,而且真的很多类似的其它配置都可以这样,要是官方固件库或者原子库里有这样的一些初始化设置 ...

谢谢鼓励,大家集思广益。
你说得很对,我都想甩开库函数自己搞一套了。哈哈。
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 7 天前 | 显示全部楼层
d1z1y2 发表于 2018-7-12 21:42
谢谢分享,收藏了

谢谢,欢迎试用,多提宝贵意见。
回复 支持 反对

使用道具 举报

  离线 

500

主题

9万

帖子

31

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
129729
金钱
129729
注册时间
2010-12-1
在线时间
1169 小时
发表于 6 天前 | 显示全部楼层
谢谢分享。
和我们寄存器版本的配置代码类似,不过你这个更精简一些。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层
本帖最后由 warship 于 2018-7-13 08:22 编辑
正点原子 发表于 2018-7-13 01:31
谢谢分享。
和我们寄存器版本的配置代码类似,不过你这个更精简一些。

你说的是这种配置方法吗:  
        GPIOA->CRL&=0XFFFFFFF0;        //PA0设置成输入,默认下拉         
        GPIOA->CRL|=0X00000008;
         
        GPIOE->CRL&=0XFFF000FF;        //PE2~4设置成输入         
        GPIOE->CRL|=0X00088800;                                    
        GPIOE->ODR|=7<<2;                   //PE2~4 上拉
如果是的话,其实这种代码更精简高效,只不过是太不直观了,也不方便。
回复 支持 反对

使用道具 举报

  离线 

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2018-6-27
在线时间
8 小时
发表于 6 天前 | 显示全部楼层
简单,有效,好理解,谢谢分享。
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层
PeterYu 发表于 2018-7-13 08:27
简单,有效,好理解,谢谢分享。

感谢支持。
回复 支持 反对

使用道具 举报

  离线 

6

主题

488

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1546
金钱
1546
注册时间
2015-5-8
在线时间
256 小时
发表于 6 天前 | 显示全部楼层
不错,学习了
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层

谢谢,欢迎试用,多提宝贵意见。
回复 支持 反对

使用道具 举报

  离线 

41

主题

390

帖子

0

精华

高级会员

Rank: 4

积分
992
金钱
992
注册时间
2017-8-7
在线时间
147 小时
发表于 6 天前 | 显示全部楼层
不错不错
回复 支持 反对

使用道具 举报

  离线 

15

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2014-4-29
在线时间
197 小时
发表于 6 天前 | 显示全部楼层
其实如果只在开机的时候初始化,多慢都能接受,直接把原库函数封装成一个方便的形式也行。如果需要在运行过程中频繁的修改配置,楼主的方法就非常有用。一般正常的程序,管脚号基本不会共用,speed参数也不会变,需要修改的参数一般都是mode参数,比如通信时IO方向切换。
楼主可以额外加一个通用的快速修改某个管脚的GPIO_mode的功能,另外可以把位带操作整合进来,增加一个通用的快速的IO读写功能
回复 支持 反对

使用道具 举报

  离线 

51

主题

426

帖子

0

精华

高级会员

Rank: 4

积分
854
金钱
854
注册时间
2014-3-7
在线时间
161 小时
发表于 6 天前 | 显示全部楼层
warship 发表于 2018-7-12 19:21
有了这个配置函数,今后的GPIO配置就超级清爽了,
比如两个LED灯,三个按键的配置,
原先有一大堆的代码 ...

搞一个led工程上传上来,可以吗?
嗯呢
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层
ssssssssssss 发表于 2018-7-13 13:44
搞一个led工程上传上来,可以吗?

你搞一个LED工程传上来,
我改好后,作为范例。
回复 支持 反对

使用道具 举报

  离线 

51

主题

426

帖子

0

精华

高级会员

Rank: 4

积分
854
金钱
854
注册时间
2014-3-7
在线时间
161 小时
发表于 6 天前 | 显示全部楼层
本帖最后由 ssssssssssss 于 2018-7-13 14:05 编辑
warship 发表于 2018-7-13 13:50
你搞一个LED工程传上来,
我改好后,作为范例。

好啊,我这里有个led的,这个是f1的

实验1 跑马灯实验.rar

102.45 KB, 下载次数: 10

嗯呢
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层
本帖最后由 warship 于 2018-7-14 11:51 编辑
看了一下,你这个是战舰的第一个试验,太简单了。

我改了一下第五试验,东西多一点。
范例代码已移至顶楼(此楼是老文件,勿下!!)

EXTI_TEST.zip

136.08 KB, 下载次数: 11

回复 支持 反对

使用道具 举报

  离线 

51

主题

426

帖子

0

精华

高级会员

Rank: 4

积分
854
金钱
854
注册时间
2014-3-7
在线时间
161 小时
发表于 6 天前 | 显示全部楼层
warship 发表于 2018-7-13 14:32
看了一下,你这个是战舰的第一个试验,太简单了。
我改了一下第五试验,东西多一点。

可以扩展一下,stm8,f0,2,3,4,7,多谢分享哈
嗯呢
回复 支持 反对

使用道具 举报

  离线 

17

主题

515

帖子

1

精华

高级会员

Rank: 4

积分
892
金钱
892
注册时间
2018-5-11
在线时间
163 小时
 楼主| 发表于 6 天前 | 显示全部楼层
本帖最后由 warship 于 2018-7-13 14:47 编辑
ssssssssssss 发表于 2018-7-13 14:39
可以扩展一下,stm8,f0,2,3,4,7,多谢分享哈

你赶紧更新一下(附件我更新了一下),
刚才我忘记开外部中断的AFIO时钟了。这里我对原子的SYS中不合理部分进行了一些改进,
并且使用了我最新研究的位操作功能,
比传统代码更高效,更易理解。
回复 支持 反对

使用道具 举报

  离线 

51

主题

426

帖子

0

精华

高级会员

Rank: 4

积分
854
金钱
854
注册时间
2014-3-7
在线时间
161 小时
发表于 6 天前 | 显示全部楼层
本帖最后由 ssssssssssss 于 2018-7-13 15:40 编辑
warship 发表于 2018-7-13 14:41
你赶紧更新一下(附件我更新了一下),
刚才我忘记开外部中断的AFIO时钟了。这里我对原子的SYS中不合理 ...

这么 厉害 我看看,果然楼主对位带操作非常熟悉啊,佩服,有空扩展一下其他st其他单片机
嗯呢
回复 支持 反对

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2017-5-21
在线时间
4 小时
发表于 5 天前 来自手机 | 显示全部楼层
感谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




关闭

"原子哥”推荐上一条 /1 下一条

QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-7-19 15:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */