接触单片机也有两年了,之前是一直使用库函数的操作方式,然后逐渐有,提高封装函数通用性稍微强一点的想法。库函数因为是有别人写好的一系列封装函数,所以库不变的情况下,还是比较方便的。参考了各位大佬们分享的帖子,后面自己再处理了一下。
上内容:(用枚是为了收纳方便)
/**************GPIO.H文件**************/
#ifndef __GPIO_H
#define __GPIO_H
#include "stm32f10x.h" // Device header
typedef enum //枚举:PIN脚
{
PIN0 = 1<<0 , PIN1 = 1<<1 ,
PIN2 = 1<<2 , PIN3 = 1<<3 ,
PIN4 = 1<<4 , PIN5 = 1<<5 ,
PIN6 = 1<<6 , PIN7 = 1<<7 ,
PIN8 = 1<<8 , PIN9 = 1<<9 ,
PIN10 = 1<<10 , PIN11 = 1<<11 ,
PIN12 = 1<<12 , PIN13 = 1<<13 ,
PIN14 = 1<<14 , PIN15 = 1<<15 ,
}GPIO_PIN_TypeDef;
typedef enum //枚举:引脚输入/输出模式
{
GPIO_MODE_IN_ANALOG = 0 , //模拟输入模式
GPIO_MODE_IN_FLOAT = 1 , //浮空输入模式
GPIO_MODE_IN_PUPD = 2 , //上拉下拉输入模式
GPIO_MODE_OUT_PP = 0 , //推挽输出
GPIO_MODE_OUT_OD = 1 , //开漏输出
GPIO_MODE_OUT_AFPP = 2 , //复用推挽输出
GPIO_MODE_OUT_APOD = 3 , //复用开漏输出
}GPIO_MODE_TypeDef;
typedef enum //枚举:引脚输出速度
{
GPIO_SPEED_IN = 0 , //GPIO输入模式
GPIO_SPEED_10M = 1 , //GPIO输出速度10Mhz
GPIO_SPEED_20M = 2 , //GPIO输出速度20Mhz
GPIO_SPEED_50M = 3 , //GPIO输出速度50Mhz
}GPIO_SPEED_TypeDef;
typedef struct { //结构体:GPIO引脚配置项目
GPIO_TypeDef* GPIO_x;
uint32_t GPIO_PIN_X;
uint32_t GPIO_MODE;
uint32_t GPIO_SPEED;
uint8_t GPIO_InitState;
}GPIO_InitList;
static GPIO_InitList GPIO_Init_List[ 120 ] = //添加、修改需要配置的GPIO口
{// GPIO_X, PIN脚,引脚输入/输出模式,引脚输出速度 ,初始输出状态(高低电平)
{GPIOC, PIN1 , GPIO_MODE_OUT_PP ,GPIO_SPEED_50M, 1 },
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},
{GPIOC, PIN12, GPIO_MODE_OUT_PP ,GPIO_SPEED_50M, 0 },
};
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页)。M4同M3类似,只是寄存器地址变了。
typedef enum //GPIO宏定义及地址映射
{
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4002000C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x4002040C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4002080C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x40020C0C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4002100C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x4002140C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x4002180C
#define GPIOH_ODR_Addr (GPIOH_BASE+12) //0x40021C0C
#define GPIOI_ODR_Addr (GPIOI_BASE+12) //0x4002200C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40020008
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40020408
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40020808
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40020C08
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40020808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40021408
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40021808
#define GPIOH_IDR_Addr (GPIOH_BASE+8) //0x40021C08
#define GPIOI_IDR_Addr (GPIOI_BASE+8) //0x40022008
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输出
GPIO_Init_Base_END = 0, //结束,防止枚举内容为空,无实际意义
}GPIO_Init_Base_;
void GPIO_Set(GPIO_TypeDef* GPIOx, uint32_t BITx, uint32_t MODE, uint32_t OSPEED_MODE);
void GPIO_Init_(void);
#endif
/**************GPIO.C文件**************/
#include "GPIO.h"
/**
* @brief 通用GPIO设置函数
*
* @param @arg GPIOx:GPIOA~GPIOI.
@arg BITx:0X0000~0XFFFF.位设置,每个位代表一个IO,第0位代表Px0,第1位代表Px1,依次类推.比如0X0101,代表同时设置Px0和Px8.
@arg MODE:模式选择0~3:输入模式下,0,模拟输入;1,浮空输入(复位状态);2,上拉/下拉输入模式;3,保留;
输出模式下,0,通用推挽输出;1,通用开漏输出;2,复用推挽输出;3,复用开漏输出;
@arg OSPEED_MODE:速度模式选择0~3:0,输入(系统复位默认状态);1:10M输出;2:20M输出;3:50M输出.
* @retval 无
*/
void GPIO_Set(GPIO_TypeDef* GPIOx, uint32_t BITx, uint32_t MODE, uint32_t OSPEED_MODE)
{
u32 pinpos=0,pinposlh=0,pos=0,curpin=0;
for(pinpos=0;pinpos<16;pinpos++)
{
pos=1<<pinpos; //一个个位检查
curpin=BITx&pos;//检查引脚是否要设置
if(curpin==pos) //需要设置
{
if(pinpos < 8)//设置的管脚为0~7
{
pinposlh = pinpos;
GPIOx->CRL &= ~(0xF<<(4*pinposlh));//清除需要设置的位
GPIOx->CRL |= (OSPEED_MODE<<(4*pinposlh));//设置新的速度模式
GPIOx->CRL |= (MODE<<(4*pinposlh+2));//设置新的输入输出模式
}
else //设置的管脚为8~15
{
pinposlh = pinpos-8;
GPIOx->CRH &= ~(0xF<<(4*pinposlh));//清除需要设置的位
GPIOx->CRH |= (OSPEED_MODE<<(4*pinposlh));//设置新的速度模式
GPIOx->CRH |= (MODE<<(4*pinposlh+2));//设置新的输入输出模式
}
}
}
}
void GPIO_Init_(void) //GPIO引脚逐一初始化函数
{
uint8_t GPIO_InitList_Len;
RCC->APB2ENR |= 1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8; //打开GPIOA-G的7个时钟,适用STM32F103RC系列单片机
while(GPIO_InitList_Len <= 120) //只放在主循环前,while()循环影响不大
{
if(GPIO_Init_List[GPIO_InitList_Len].GPIO_x != 0)
{
GPIO_Set(GPIO_Init_List[GPIO_InitList_Len].GPIO_x, GPIO_Init_List[GPIO_InitList_Len].GPIO_PIN_X, GPIO_Init_List[GPIO_InitList_Len].GPIO_MODE, GPIO_Init_List[GPIO_InitList_Len].GPIO_SPEED);
if(GPIO_Init_List[GPIO_InitList_Len].GPIO_InitState) //对初始状态为高电平的引脚配置,默认低电平。
{
GPIO_Init_List[GPIO_InitList_Len].GPIO_x -> ODR |= (GPIO_Init_List[GPIO_InitList_Len].GPIO_PIN_X);
}
GPIO_InitList_Len ++;
}
else
{
GPIO_InitList_Len ++;
}
}
}
/**************主函数**************/
#include "GPIO.h"
int main(void)
{
GPIO_Init_();
while (1)
{
}
}
希望各位大佬们不吝赐教,恳请各位大佬们提出宝贵意见与想法
,感谢!
STM32F103RC单片机的GPIO初始化封装.zip
(582.06 KB, 下载次数: 7)
|