本帖最后由 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
其实如果不介意只初始化一个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]
一周热门 更多>