OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 16459|回复: 70

9月15日更新下载!!! 超级方便的GPIO端口配置函数,寄存器版本和库函数版本均可使用

[复制链接]

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
发表于 2018-7-12 19:10:59 | 显示全部楼层 |阅读模式
本帖最后由 warship 于 2018-9-15 10:48 编辑

GPIO端口的配置是每个程序都要用到的,
并且还不止配置一个,如LED灯、键盘、IO控制端口等等,
用库函数则每配置一个端口就一堆代码,看着头疼。
用寄存器版本则很不直观,
今天我看原子的寄存器版本有一个外部中断配置的函数,
用起来很方便,受到启发,
就着手参考优化了库函数的原型代码
编了这个GPIO的端口配置函数(初版时每次只配置一个引脚,现在应坛友需求,改为一次可配多个引脚)。

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


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

//配置PA8和PD2为LED指示灯
My_GPIO_Init(GPIOA,  Pin_8,  Mode_Out_PP+Speed_50MHz);    //LED0
My_GPIO_Init(GPIOD,  Pin_2,  Mode_Out_PP+Speed_50MHz);    //LED1

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






EXTI_TEST.zip

152.19 KB, 下载次数: 493

9月15日更新

我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-9 12:00:42 | 显示全部楼层
Chaos123 发表于 2018-9-9 11:43
刚注册了个帮你点赞了,希望楼主能一直更新

谢谢,觉得好用您可以推广推广。
有人用才有更新的动力。
现在基本的工作已经完成了70%了吧。
如果上面再加一层意义明确,面向应用的宏定义,
就可以无须翻看手册了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 1 反对 0

使用道具 举报

29

主题

338

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2018-4-13
在线时间
170 小时
发表于 2018-9-8 15:06:49 | 显示全部楼层
本帖最后由 xiatianyun 于 2018-9-8 15:08 编辑

其实如果不介意只初始化一个pin带来的for循环浪费的话完全可以简单封装一下初始化函数,就可以不用在用户程序中写一堆初始化数据结构的代码了。
[mw_shl_code=c,true]//GPIO_Init()库函数的二次封装。
//调用前必须使所用的GPIO外设时钟总线使能。
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIOMode_TypeDef GPIO_Mode, GPIOSpeed_TypeDef GPIO_Speed)
{
    GPIO_InitTypeDef GPIO_InitStruct; //声明初始化数据结构。
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed;
    GPIO_Init(GPIOx, &GPIO_InitStruct);
}[/mw_shl_code]
[mw_shl_code=c,true]//板载led初始化。
void led_Init(void)
{
    //GPIO_InitTypeDef GPIO_InitStruct; //声明初始化数据结构。

    //GPIOB和GPIOE时钟使能。
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

    //设置LED0。
    My_GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_OD, GPIO_Speed_10MHz); //开漏输出
    //设置LED1.除了端口组不一样外,其他一样。
    My_GPIO_Init(GPIOE, GPIO_Pin_5, GPIO_Mode_Out_OD, GPIO_Speed_10MHz); //开漏输出
    //初始化使led等熄灭。
    //如果不处理则led相应端口初始化输出为0,灯被点亮。
    LED0_OFF;
    LED1_OFF;
}[/mw_shl_code]

回复 支持 1 反对 0

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-12 19:11:57 | 显示全部楼层
本帖最后由 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;  /* 对于上拉输入模式,则置位端口 */      
}


我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-12 19:14:03 | 显示全部楼层
本帖最后由 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

我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-12 19:17:09 | 显示全部楼层
因为这个配置函数是必须且经常用到的,
可以作为系统基本函数。
建议增加到原子工程的sys.c文件中,
宏定义放在sys.h文件中
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-12 19:21:23 | 显示全部楼层
本帖最后由 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按键

我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1665
金钱
1665
注册时间
2016-4-29
在线时间
266 小时
发表于 2018-7-12 21:42:53 | 显示全部楼层
谢谢分享,收藏了
回复 支持 反对

使用道具 举报

4

主题

20

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

谢谢鼓励,大家集思广益。
你说得很对,我都想甩开库函数自己搞一套了。哈哈。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

谢谢,欢迎试用,多提宝贵意见。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

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

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-13 08:20:10 | 显示全部楼层
本帖最后由 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 上拉
如果是的话,其实这种代码更精简高效,只不过是太不直观了,也不方便。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6252
金钱
6252
注册时间
2018-6-27
在线时间
534 小时
发表于 2018-7-13 08:27:07 | 显示全部楼层
简单,有效,好理解,谢谢分享。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

感谢支持。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

8

主题

569

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2363
金钱
2363
注册时间
2015-5-8
在线时间
320 小时
发表于 2018-7-13 08:38:47 | 显示全部楼层
不错,学习了
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-13 08:40:42 | 显示全部楼层

谢谢,欢迎试用,多提宝贵意见。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

55

主题

474

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2374
金钱
2374
注册时间
2017-8-7
在线时间
207 小时
发表于 2018-7-13 09:57:32 | 显示全部楼层
不错不错
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

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

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

你搞一个LED工程传上来,
我改好后,作为范例。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

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

实验1 跑马灯实验.rar

102.45 KB, 下载次数: 142

回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

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

EXTI_TEST.zip

136.08 KB, 下载次数: 144

我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

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

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

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

你赶紧更新一下(附件我更新了一下),
刚才我忘记开外部中断的AFIO时钟了。这里我对原子的SYS中不合理部分进行了一些改进,
并且使用了我最新研究的位操作功能,
比传统代码更高效,更易理解。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

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

使用道具 举报

9

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2017-5-21
在线时间
18 小时
发表于 2018-7-14 08:51:40 来自手机 | 显示全部楼层
感谢分享
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-25 22:11:10 | 显示全部楼层

感谢支持。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-30 20:16:43 | 显示全部楼层
xianshasaman 发表于 2018-7-13 10:43
其实如果只在开机的时候初始化,多慢都能接受,直接把原库函数封装成一个方便的形式也行。如果需要在运行过 ...

这个提议能够再具体一些吗?
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

4

主题

39

帖子

0

精华

高级会员

Rank: 4

积分
588
金钱
588
注册时间
2018-8-17
在线时间
81 小时
发表于 2018-8-30 20:56:21 | 显示全部楼层
谢谢分享,非常棒!习惯了原子例程方式,这种还用不习惯,相信后面加深了解 会越来越顺手
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2018-9-5 15:27:00 | 显示全部楼层
warship 发表于 2018-8-30 20:16
这个提议能够再具体一些吗?

我用原子的流水灯例程改了改,大致就是把用到的gpio管脚集中到一起初始化,并给每个io一个用于索引的id序号,其他程序调用gpio功能的时候只用这个序号即可。
并增加了用到的bitband别名地址和寄存器地址,来实现更快速的操作。不可软件更改的映射关系用const结构数组做成了一个表,方便配置而且节省内存,需要的IO往表里填就行。代码主要在gpio.c和gpio.h里面。
这个只是个雏形,仅供参考。


实验1 跑马灯实验.rar

2.12 MB, 下载次数: 978

修改的流水灯例程

回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-5 20:22:30 | 显示全部楼层
xianshasaman 发表于 2018-9-5 15:27
我用原子的流水灯例程改了改,大致就是把用到的gpio管脚集中到一起初始化,并给每个io一个用于索引的id序 ...

感觉你这个有点儿复杂,
我那个函数无须调用库函数,
直接用寄存器实现,
也没有几句,代码效率很高的。

后面的控制灯亮灯灭,
直接用形如PEout(3)=0的语句本身就是位段操作呀。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2018-9-5 22:05:00 | 显示全部楼层
warship 发表于 2018-9-5 20:22
感觉你这个有点儿复杂,
我那个函数无须调用库函数,
直接用寄存器实现,

这个主要是场合不一样。比如要做一些功能复杂的项目,维护代码的时候,这么搞不容易被画电路的坑,也不容易被自己坑。就是写库麻烦点,用起来就爽了。

但是要是做教学程序又不一样,肯定是每个功能的文件可以单独剪裁比较方便,分开的配置和使用更好。
回复 支持 反对

使用道具 举报

29

主题

338

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2018-4-13
在线时间
170 小时
发表于 2018-9-6 00:19:51 | 显示全部楼层
谢谢分享。
在学习GPIO配置时就想到可能存在统一简单的配置写法,不把初始化参数在GPIO_Init()外部事先用一推代码填写,而是直接封装在一个函数的参数中来使用。
不过,库函数版也有它的好处,就是Pin可以一次初始化多个,也就是你说的库函数中使用了for代码。
对于像我一样的初学者往往一个pin一个pin的初始化,这个函数很直接。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-6 19:31:02 | 显示全部楼层
xiatianyun 发表于 2018-9-6 00:19
谢谢分享。
在学习GPIO配置时就想到可能存在统一简单的配置写法,不把初始化参数在GPIO_Init()外部事先用 ...

你说得很对,
确实这个函数不能多个pin一起配
因为我这个为了直观,直接使用了pin的引脚号,
而库函数采用的是互不干涉的0001、0002、0004、0008等的BIT定位值,
可以通过使用"或"运算同时加入多个pin(后来我也意识到库函数用for的目的)
但如果配置单个pin的话,用for就降低效率了。
其实最高效率就是直接写寄存器,一次可以多个pin, 一条语句搞定,但可读性太差。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2018-8-29
在线时间
23 小时
发表于 2018-9-8 09:42:19 | 显示全部楼层
楼主能否更新一下定时器的位带操作
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-8 11:07:37 | 显示全部楼层
Chaos123 发表于 2018-9-8 09:42
楼主能否更新一下定时器的位带操作

看到大家都对位带操作不感兴趣,
后来就没有更新了,
您用吗?
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

22

主题

147

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3979
金钱
3979
注册时间
2015-4-18
在线时间
403 小时
发表于 2018-9-8 13:21:52 | 显示全部楼层
warship 发表于 2018-7-12 19:21
有了这个配置函数,今后的GPIO配置就超级清爽了,
比如两个LED灯,三个按键的配置,
原先有一大堆的代码 ...

你这代码用起来稳定吗。有没什么BUG
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-9-8 13:26:50 | 显示全部楼层
其实新人更喜欢看这种代码,原子可以参考下哦
猪猪熊呢?
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-8 17:49:00 | 显示全部楼层
752151619 发表于 2018-9-8 13:21
你这代码用起来稳定吗。有没什么BUG

我自己也一直在用的,
没有发现BUG。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

2

主题

64

帖子

0

精华

高级会员

Rank: 4

积分
946
金钱
946
注册时间
2014-11-2
在线时间
367 小时
发表于 2018-9-8 19:46:04 | 显示全部楼层
感觉还是没有我的方便,附上网址:https://www.a_m_o_bbs.com/thread-5671113-1-1.html
回复 支持 反对

使用道具 举报

2

主题

64

帖子

0

精华

高级会员

Rank: 4

积分
946
金钱
946
注册时间
2014-11-2
在线时间
367 小时
发表于 2018-9-8 19:50:15 | 显示全部楼层
这是STM8的
在IAR的c/c++ compiler选项卡language中设置c++,不然会报错

#pragma diag_suppress=pe1665    //屏蔽警告
/**************************************************/
#define PP    1       //CR1 上拉
#define OD    0      //CR1  开漏
#define FAST  1     //CR2 输出时快速模式
#define SLOW  0    //CR2 输出时慢速模式
#define EINT  1      //CR2 输入时开中断
#define DINT  0      //CR2 输入时关中断
/**************************************************/
#define PIN(port,bit,cr1,cr2,out,name) \
inline void  name##_H()                 {P##port##_ODR|=(u8)(1<<bit);}\
inline void  name##_L()                 {P##port##_ODR&=(u8)~(1<<bit);}\
inline void  name##_T()                 {P##port##_ODR^=(u8)(1<<bit);}\
inline void  name##(u8 x)               {x ? name##_H():name##_L();}\
inline void  name##_U()                 {P##port##_CR1|=(u8)(1<<bit);}\
inline void  name##_D()                 {P##port##_CR1&=(u8)~(1<<bit);}\
inline void  name##_CR1(u8 x)           {x ? name##_U():name##_D();}\
inline void  name##_S()                 {P##port##_CR2|=(u8)(1<<bit);}\
inline void  name##_C()                 {P##port##_CR2&=(u8)~(1<<bit);}\
inline void  name##_CR2(u8 x)           {x ? name##_S():name##_C();}\
inline u8    name##()                   {return P##port##_IDR&(u8)(1<<bit) ? 1:0;}\
inline void  name##_O()                 {P##port##_DDR|=(u8)(1<<bit);name##_CR1(cr1);name##_CR2(cr2);name##(out);}\
inline void  name##_I()                 {P##port##_DDR&=(u8)~(1<<bit);name##_CR1(cr1);name##_CR2(cr2);}
/**************************************************/
把上面代码保存成一个头文件,如 def.h
使用前调用该文件就可以了

譬如:
#include "def.h"
PIN(C,3,PP,FAST,1,LED);
PIN(C,2,PP,DINT,1,KEY);
//PIN(端口号A~I,引脚号0~7,CR1,CR2,输出模式时IO初始值,引脚名称)

void main (void)
{    LED_O();  //设置IO输出
     KEY_I();   //设置IO输入

     while(1)
     {   if(!KEY())
         {    LED_H();//LED(1);
         }
         else
         {    LED_L();//LED(0);
         }
     }
}




这个是M0的头文件


#pragma diag_suppress=pe1665    //屏蔽警告
/**************************************************/
#define PIN(port,bit,rcc,mode,speed,ppod,pupd,name)                                                            \
inline void  name##_H()      { GPIO##port##->BSRR = GPIO_Pin_##bit; }                                \
inline void  name##_L()      { GPIO##port##->BRR = GPIO_Pin_##bit; }                                 \
inline void  name##_T()      { GPIO##port##->ODR&GPIO_Pin_##bit ? name##_L():name##_H(); }           \
inline u8    name##()        { return (GPIO##port##->IDR&GPIO_Pin_##bit) ? 1:0; }                    \
inline void  name##(u32 x)   { x ? name##_H():name##_L(); }                                          \
inline void  name##_O(u32 x) { GPIO_InitTypeDef GPIO_InitStructure;                                  \
                                RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);      \
                                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_##mode;                      \
                                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##bit;                         \
                                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_##speed;                   \
                                GPIO_InitStructure.GPIO_OType= GPIO_OType_##ppod;                     \
                                GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_##pupd;                       \
                                GPIO_Init(GPIO##port, &GPIO_InitStructure);                           \
                                x ? name##_H():name##_L();   }                                        \
inline void  name##_I()      { GPIO_InitTypeDef GPIO_InitStructure;                                  \
                                RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);      \
                                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_##mode;                      \
                                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##bit;                         \
                                GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_##pupd;                       \
                                GPIO_Init(GPIO##port, &GPIO_InitStructure); }
/**************************************************/



/**************************************************/
// Rcc:   APB1,APB2,AHB
// Mode:  AN,IN,OUT,AF
// Speed: 2MHZ,10MHz,50MHz
// Ppod:  PP,OD
// Pupd:  NOPULL,UP,DOWN
/**************************************************/
// PIN(Port,Bit,Rcc,Mode,Speed,Ppod,Pupd,Name)

PIN(F,  0, AHB, OUT, 10MHz, PP, NOPULL, LED);
PIN(A,  1, AHB,  IN,  2MHz, OD,     UP, KEY);

LED_O(1);
KEY_I();




这个是M3的头文件


#pragma diag_suppress=pe1665    //屏蔽警告
/**************************************************/
#define PIN(port,bit,rcc,mode,speed,name)                                                            \
inline void  name##_H(void)  { GPIO##port##->BSRR = GPIO_Pin_##bit; }                                \
inline void  name##_L(void)  { GPIO##port##->BRR = GPIO_Pin_##bit; }                                 \
inline void  name##_T(void)  { GPIO##port##->ODR&GPIO_Pin_##bit ? name##_L():name##_H(); }           \
inline u8    name##(void)    { return (GPIO##port##->IDR&GPIO_Pin_##bit) ? 1:0; }                    \
inline void  name##(u32 x)   { x ? name##_H():name##_L(); }                                          \
inline void  name##_O(u32 x) { GPIO_InitTypeDef GPIO_InitStructure;                                  \
                                RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);      \
                                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_##mode;                      \
                                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##bit;                         \
                                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_##speed;                   \
                                GPIO_Init(GPIO##port, &GPIO_InitStructure);                           \
                                x ? name##_H():name##_L();   }                                        \
inline void  name##_I(void)    { GPIO_InitTypeDef GPIO_InitStructure;                                  \
                                RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);      \
                                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_##mode;                      \
                                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##bit;                         \
                                GPIO_Init(GPIO##port, &GPIO_InitStructure); }
/**************************************************/


// Mode:  AIN,IN_FLOATING,IPD,IPU,Out_OD,Out_PP,AF_OD,AF_PP
// Speed: 2MHZ,10MHz,50MHz
// Rcc:   APB1,APB2,AHB
/**************************************************/
// PIN(Port,Bit,Rcc,Mode,Speed,Name)
/**************************************************/

PIN(B,0,APB2,Out_PP,50MHz,LED);
PIN(B,0,APB2,IPU,50MHz,KEY);

LED_O(1);
KEY_I();




这个是M4的头文件

#pragma diag_suppress=pe1665    //屏蔽警告
/***********************************************************************/
inline void GPIO_MODE_PUPD(GPIO_TypeDef* GPIOx,uint32_t mode,uint32_t pupd,uint16_t bit)
{   GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (bit * 2));
     GPIOx->MODER |= (mode << (bit * 2));
     GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)bit * 2));
     GPIOx->PUPDR |= (pupd << (bit * 2));
}
/***********************************************************************/
inline void GPIO_SPEED_OT(GPIO_TypeDef* GPIOx,uint32_t speed,uint16_t ot,uint16_t bit)
{   GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (bit * 2));
     GPIOx->OSPEEDR |= (speed << (bit * 2));
     GPIOx->OTYPER  &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)bit));
     GPIOx->OTYPER |= (uint16_t)(ot << ((uint16_t)bit));
}
/***********************************************************************/
inline void GPIO_IN(GPIO_TypeDef* GPIOx,uint32_t pupd,uint16_t bit)
{   GPIO_MODE_PUPD(GPIOx,GPIO_Mode_IN,pupd,bit);
}
/***********************************************************************/
inline void GPIO_AN(GPIO_TypeDef* GPIOx,uint32_t pupd,uint16_t bit)
{   GPIO_MODE_PUPD(GPIOx,GPIO_Mode_AN,pupd,bit);
}
/***********************************************************************/
inline void GPIO_OUT(GPIO_TypeDef* GPIOx,uint32_t speed,uint32_t pupd,uint16_t ot,uint16_t bit)
{   GPIO_SPEED_OT(GPIOx,speed,ot,bit);
     GPIO_MODE_PUPD(GPIOx,GPIO_Mode_OUT,pupd,bit);
}
/***********************************************************************/
inline void GPIO_AF(GPIO_TypeDef* GPIOx,uint32_t speed,uint32_t pupd,uint16_t ot,uint16_t bit)
{   GPIO_SPEED_OT(GPIOx,speed,ot,bit);
     GPIO_MODE_PUPD(GPIOx,GPIO_Mode_AF,pupd,bit);
}
/***********************************************************************/
inline void GPIOS_IN(GPIO_TypeDef* GPIOx,uint32_t pupd,uint16_t bits)
{   uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
     for(pinpos = 0x00; pinpos < 0x10; pinpos++)
     {   pos = ((uint32_t)0x01) << pinpos;
         currentpin = bits & pos;
         if(currentpin == pos)
         {   GPIO_MODE_PUPD(GPIOx,GPIO_Mode_IN,pupd,pinpos);
         }
     }
}
/***********************************************************************/
inline void GPIOS_AN(GPIO_TypeDef* GPIOx,uint32_t pupd,uint16_t bits)
{   uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
     for(pinpos = 0x00; pinpos < 0x10; pinpos++)
     {   pos = ((uint32_t)0x01) << pinpos;
         currentpin = bits & pos;
         if(currentpin == pos)
         {   GPIO_MODE_PUPD(GPIOx,GPIO_Mode_AN,pupd,pinpos);
         }
     }
}
/***********************************************************************/
inline void GPIOS_OUT(GPIO_TypeDef* GPIOx,uint32_t speed,uint32_t pupd,uint16_t ot,uint16_t bits)
{   uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
     for(pinpos = 0x00; pinpos < 0x10; pinpos++)
     {   pos = ((uint32_t)0x01) << pinpos;
         currentpin = bits & pos;
         if(currentpin == pos)
         {   GPIO_SPEED_OT(GPIOx,speed,ot,pinpos);
             GPIO_MODE_PUPD(GPIOx,GPIO_Mode_OUT,pupd,pinpos);
         }
     }
}
/***********************************************************************/
inline void GPIOS_AF(GPIO_TypeDef* GPIOx,uint32_t speed,uint32_t pupd,uint16_t ot,uint8_t af,uint16_t bits)
{   uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
     for(pinpos = 0x00; pinpos < 0x10; pinpos++)
     {   pos = ((uint32_t)0x01) << pinpos;
         currentpin = bits & pos;
         if(currentpin == pos)
         {   GPIO_PinAFConfig(GPIOx,pinpos,af);
             GPIO_SPEED_OT(GPIOx,speed,ot,pinpos);
             GPIO_MODE_PUPD(GPIOx,GPIO_Mode_AF,pupd,pinpos);
         }
     }
}
/***********************************************************************/
#define PIN(rcc,port,bit,ot,pupd,speed,af,name)\
inline void name##_H()          {GPIO##port##->ODR|=(1<<bit);}\
inline void name##_L()          {GPIO##port##->ODR&=~(1<<bit);}\
inline void name##_T()          {GPIO##port##->ODR^=(1<<bit);}\
inline void name##(u8 x)        {x ? name##_H():name##_L();}\
inline u8   name##()            {return GPIO##port##->IDR&(1<<bit) ? 1:0;}\
inline void name##_OUT()        {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIO_OUT(GPIO##port,GPIO_Speed_##speed,GPIO_PuPd_##pupd,GPIO_OType_##ot,bit);}\
inline void name##_AF()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIO_PinAFConfig(GPIO##port, GPIO_PinSource##bit, GPIO_AF_##af);\
                                  GPIO_AF(GPIO##port,GPIO_Speed_##speed,GPIO_PuPd_##pupd,GPIO_OType_##ot,bit);}\
inline void name##_IN()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIO_IN(GPIO##port,GPIO_PuPd_##pupd,bit);}\
inline void name##_AN()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIO_AN(GPIO##port,GPIO_PuPd_##pupd,bit);}
/***********************************************************************/
#define PINS(rcc,port,bits,ot,pupd,speed,af,name)\
inline void name##_OUT()        {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIOS_OUT(GPIO##port,GPIO_Speed_##speed,GPIO_PuPd_##pupd,GPIO_OType_##ot,bits);}\
inline void name##_AF()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIOS_AF(GPIO##port,GPIO_Speed_##speed,GPIO_PuPd_##pupd,GPIO_OType_##ot,GPIO_AF_##af,bits);}\
inline void name##_IN()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIOS_IN(GPIO##port,GPIO_PuPd_##pupd,bits);}\
inline void name##_AN()         {RCC_##rcc##PeriphClockCmd(RCC_##rcc##Periph_GPIO##port, ENABLE);\
                                  GPIOS_AN(GPIO##port,GPIO_PuPd_##pupd,bits);}
/***********************************************************************/
#define GPIO_AF_                0xFF
/***********************************************************************/



PIN(AHB1,A,0,OD,NOPULL,2MHz,,KEY);
PIN(AHB1,B,0,PP,NOPULL,100MHz,,LED);
PIN(AHB1,A,9,PP,UP,50MHz,USART1,TXD1);
PIN(AHB1,A,10,OD,UP,50MHz,USART1,RXD1);

PIN(AHB1,G,12,PP,NOPULL,50MHz,FSMC,CS);
PIN(AHB1,F,0,PP,NOPULL,50MHz,FSMC,RS);
PIN(AHB1,D,4,PP,NOPULL,50MHz,FSMC,NOE);
PIN(AHB1,D,5,PP,NOPULL,50MHz,FSMC,NWE);
PINS(AHB1,F,0xf03f,PP,NOPULL,50MHz,FSMC,ADR00_09);
PINS(AHB1,G,0x003f,PP,NOPULL,50MHz,FSMC,ADR10_15);
PINS(AHB1,D,0x3800,PP,NOPULL,50MHz,FSMC,ADR16_18);
PINS(AHB1,D,0xc003,PP,NOPULL,50MHz,FSMC,DB00_03);
PINS(AHB1,E,0xff80,PP,NOPULL,50MHz,FSMC,DB04_12);
PINS(AHB1,D,0x0700,PP,NOPULL,50MHz,FSMC,DB13_15);
PINS(AHB1,E,0x0003,PP,NOPULL,50MHz,FSMC,NBL);


KEY_IN();
LED_OUT();
TXD1_AF();
RXD1_AF();

NOE_AF(); NWE_AF();//SRAM FSMC Contorl
NBL_AF(); NCE_AF();
DB00_03_AF();DB04_12_AF();DB13_15_AF();//SRAM FSMC Data & Addr
ADR00_09_AF(); ADR10_15_AF(); ADR16_18_AF();
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-8 21:24:47 | 显示全部楼层
way2888 发表于 2018-9-8 19:50
这是STM8的
在IAR的c/c++ compiler选项卡language中设置c++,不然会报错

感谢分享,有空研究借鉴一下。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

22

主题

147

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3979
金钱
3979
注册时间
2015-4-18
在线时间
403 小时
发表于 2018-9-9 08:17:27 | 显示全部楼层
warship 发表于 2018-9-8 17:49
我自己也一直在用的,
没有发现BUG。

你这个只能一个口一个口的初始化配置吧
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-9 08:41:56 | 显示全部楼层
本帖最后由 warship 于 2018-9-9 09:17 编辑
752151619 发表于 2018-9-9 08:17
你这个只能一个口一个口的初始化配置吧

是的,这个重点是代码直观易懂。这里没有使用库函数,效率比较高。
实际库函数是:
即使你只配置一个端口,
它都要16个端口一个一个查询比较,
看哪一个端口匹配了你的输入参数,
所以它可以支持多个端口,
但是感觉很笨且效率低。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2018-8-29
在线时间
23 小时
发表于 2018-9-9 10:39:48 | 显示全部楼层
warship 发表于 2018-9-8 11:07
看到大家都对位带操作不感兴趣,
后来就没有更新了,
您用吗?

用起来很爽啊,结合寄存器手册简单易懂,位带操作也没那么难,希望楼主还能再更新一波,当次伸手党
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2018-8-29
在线时间
23 小时
发表于 2018-9-9 10:41:35 | 显示全部楼层
目前也没发现BUG,把以前的代码替换了一下,就是很多warning........我在RCT6上用的 AFIO很多warning 不过照样用    我把楼主的阉割了一下,只用了用到的寄存器
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-9 11:03:23 | 显示全部楼层
Chaos123 发表于 2018-9-9 10:41
目前也没发现BUG,把以前的代码替换了一下,就是很多warning........我在RCT6上用的 AFIO很多warning 不过 ...

非常荣幸还能对您有所助益,
我将最新的宏定义放在了https://github.com/ShuifaHe/STM32/tree/BITBAND
您可以移步下载试用,放在github也便于更新管理,
有什么意见建议也可反馈讨论修改,
希望能够得到您的鼓励和支持(请按星星点赞,谢谢)
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-9-9 11:10:17 | 显示全部楼层
Chaos123 发表于 2018-9-9 10:39
用起来很爽啊,结合寄存器手册简单易懂,位带操作也没那么难,希望楼主还能再更新一波,当次伸手党

确实如此,看来您深得其精髓。
位带操作效率高,
其实比库函数要强得太多了,
我后来还尝试了多位的操作,
如果完善后搞一份方便查阅的说明文档,
用起来就方便了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2018-8-29
在线时间
23 小时
发表于 2018-9-9 11:43:54 | 显示全部楼层
warship 发表于 2018-9-9 11:03
非常荣幸还能对您有所助益,
我将最新的宏定义放在了https://github.com/ShuifaHe/STM32/tree/BITBAND
...

刚注册了个帮你点赞了,希望楼主能一直更新
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2018-8-29
在线时间
23 小时
发表于 2018-9-9 11:44:48 | 显示全部楼层
比库函数快,但是以前写寄存器太麻烦了,还得看着手册一步步的,贼慢
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-28 02:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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