news 2026/4/16 1:28:19

【ARM】从零封装STM32标准库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【ARM】从零封装STM32标准库

这篇文章是 STM32F10x系列 GPIO 外设的寄存器定义和操作函数。头文件stm32f10x.h定义了 GPIO 和 RCC 外设的寄存器结构体、基地址映射、引脚编号枚举以及工作模式/速度配置类型。stm32f10x_gpio.h声明了三个关键函数:GPIO_SetBits/ResetBits用于控制引脚输出电平,GPIO_Init函数实现引脚模式初始化,通过分析GPIO_Mode参数判断输入/输出模式,并配置CRL/CRH寄存器设置具体引脚的工作模式和速度。整个设计采用寄存器直接映射方式,通过结构体指针访问外设寄存器,实现了对 STM32 GPIO 外设的底层硬件控制。

stm32f10x.h

#ifndef__STM32F10X_H__#define__STM32F10X_H__//volatile表⽰容易变得变量,防⽌编译器优化,#define__IOvolatiletypedefunsignedintuint32_t;typedefunsignedshortuint16_t;// GPIO寄存器结构体定义typedefstruct{__IOuint32_tCRL;//端⼝配置低寄存器,偏移地址0X00__IOuint32_tCRH;//端⼝配置⾼寄存器,地址偏移0X04__IOuint32_tIDR;//端⼝数据输⼊寄存器,地址偏移0X08__IOuint32_tODR;//端⼝数据输出寄存器,地址偏移0X0C__IOuint32_tBSRR;//端⼝位设置、清除寄存器,地址偏移0X10__IOuint32_tBRR;//端⼝位清除寄存器,地址偏移0X14__IOuint32_tLCKR;//端⼝配置锁定寄存器,地址偏移0X18}GPIO_TypeDef;typedefstruct{__IOuint32_tCR;__IOuint32_tCFGR;__IOuint32_tCIR;__IOuint32_tAPB2RSTR;__IOuint32_tAPB1RSTR;__IOuint32_tAHBENR;__IOuint32_tAPB2ENR;__IOuint32_tAPB1ENR;__IOuint32_tBDCR;__IOuint32_tCSR;}RCC_TypeDef;/*⽚上外设基地址*/#definePERIPH_BASE((unsignedint)0x40000000)/*APB2总线基地址*/#defineAPB2PERIPH_BASE(PERIPH_BASE+0x10000)/*AHB总线基地址*/#defineAHBPERIPH_BASE(PERIPH_BASE+0x20000)/*RCC外设基地址*/#defineRCC_BASE(AHBPERIPH_BASE+0x1000)#defineRCC_APB2ENR*(unsignedint*)(RCC_BASE+0x18)/*GPIO外设基地址*/#defineGPIOA_BASE(APB2PERIPH_BASE+0x0800)#defineGPIOB_BASE(APB2PERIPH_BASE+0x0C00)#defineGPIOC_BASE(APB2PERIPH_BASE+0x1000)#defineGPIOD_BASE(APB2PERIPH_BASE+0x1400)#defineGPIOE_BASE(APB2PERIPH_BASE+0x1800)#defineGPIOF_BASE(APB2PERIPH_BASE+0x1C00)#defineGPIOG_BASE(APB2PERIPH_BASE+0x2000)/* GPIOC寄存器地址*/#defineGPIOC_CRL*(unsignedint*)(GPIOC_BASE+0x00)#defineGPIOC_CRH*(unsignedint*)(GPIOC_BASE+0x04)#defineGPIOC_IDR*(unsignedint*)(GPIOC_BASE+0x08)#defineGPIOC_ODR*(unsignedint*)(GPIOC_BASE+0x0C)#defineGPIOC_BSRR*(unsignedint*)(GPIOC_BASE+0x10)#defineGPIOC_BRR*(unsignedint*)(GPIOC_BASE+0x14)#defineGPIOC_LCKR*(unsignedint*)(GPIOC_BASE+0x18)#defineGPIOA((GPIO_TypeDef*)GPIOA_BASE)#defineGPIOB((GPIO_TypeDef*)GPIOB_BASE)#defineGPIOC((GPIO_TypeDef*)GPIOC_BASE)#defineGPIOD((GPIO_TypeDef*)GPIOD_BASE)#defineGPIOE((GPIO_TypeDef*)GPIOE_BASE)#defineGPIOF((GPIO_TypeDef*)GPIOF_BASE)#defineGPIOG((GPIO_TypeDef*)GPIOG_BASE)// RCC 外设声明#defineRCC((RCC_TypeDef*)RCC_BASE)#defineGPIO_Pin_0(uint16_t)0x0001)#defineGPIO_Pin_1((uint16_t)0x0002)#defineGPIO_Pin_2((uint16_t)0x0004)#defineGPIO_Pin_3((uint16_t)0x0008)#defineGPIO_Pin_4((uint16_t)0x0010)#defineGPIO_Pin_5((uint16_t)0x0020)#defineGPIO_Pin_6((uint16_t)0x0040)#defineGPIO_Pin_7((uint16_t)0x0080)#defineGPIO_Pin_8((uint16_t)0x0100)#defineGPIO_Pin_9((uint16_t)0x0200)#defineGPIO_Pin_10((uint16_t)0x0400)#defineGPIO_Pin_11((uint16_t)0x0800)#defineGPIO_Pin_12((uint16_t)0x1000)#defineGPIO_Pin_13((uint16_t)0x2000)#defineGPIO_Pin_14((uint16_t)0x4000)#defineGPIO_Pin_15((uint16_t)0x8000)typedefenum{GPIO_Speed_10MHz=1,// 10MHZ (01)bGPIO_Speed_2MHz,// 2MHZ (10)bGPIO_Speed_50MHz// 50MHZ (11)b}GPIOSpeed_TypeDef;typedefenum{GPIO_Mode_AIN=0x0,GPIO_Mode_IN_FLOATING=0x04,GPIO_Mode_IPD=0x28,GPIO_Mode_IPU=0x48,GPIO_Mode_Out_OD=0x14,GPIO_Mode_Out_PP=0x10,GPIO_Mode_AF_OD=0x1C,GPIO_Mode_AF_PP=0x18}GPIOMode_TypeDef;typedefstruct{uint16_tGPIO_Pin;GPIOSpeed_TypeDef GPIO_Speed;GPIOMode_TypeDef GPIO_Mode;}GPIO_InitTypeDef;#endif

stm32f10x_gpio.h

#ifndef__STM32F10X_GPIO__#define__STM32F10X_GPIO__#include"stm32f10x.h"voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct);#endif
#include"stm32f10x_gpio.h"voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){GPIOx->BSRR=GPIO_Pin;}voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){GPIOx->BRR=GPIO_Pin;}/** *函数功能:初始化引脚模式 *参数说明: GPIOx,该参数为 GPIO_TypeDef 类型的指针,指向 GPIO 端⼝的地址 * GPIO_InitTypeDef:GPIO_InitTypeDef 结构体指针,指向初始化变量 */voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct){uint32_tcurrentmode=0x00,currentpin=0x00,pinpos=0x00,pos=0x00;uint32_ttmpreg=0x00,pinmask=0x00;/*---------------- GPIO 模式配置 -------------------*/// 把输⼊参数 GPIO_Mode 的低四位暂存在 currentmodecurrentmode=((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x0F);// bit4是1表⽰输出,bit4是0则是输⼊// 判断bit4是1还是0,即⾸选判断是输⼊还是输出模式if((((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x10))!=0x00){// 输出模式则要设置输出速度currentmode|=(uint32_t)GPIO_InitStruct->GPIO_Speed;}/*-----GPIO CRL 寄存器配置 CRL 寄存器控制着低 8 位 IO- ----*/// 配置端⼝低 8 位,即 Pin0~Pin7if(((uint32_t)GPIO_InitStruct->GPIO_Pin&((uint32_t)0x00FF))!=0x00){// 先备份 CRL 寄存器的值tmpreg=GPIOx->CRL;// 循环,从 Pin0 开始配对,找出具体的 Pinfor(pinpos=0x00;pinpos<0x08;pinpos++){//pos的值为1左移pinpos位pos=((uint32_t)0x01)<<pinpos;//令 pos 与输⼊参数 GPIO_PIN 作位与运算currentpin=(GPIO_InitStruct->GPIO_Pin)&pos;//若 currentpin=pos,则找到使⽤的引脚if(currentpin==pos){//pinpos 的值左移两位(乘以 4),因为寄存器中 4 个位配置⼀个引脚pos=pinpos<<2;//把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变pinmask=((uint32_t)0x0F)<<pos;tmpreg&=~pinmask;// 向寄存器写⼊将要配置的引脚的模式tmpreg|=(currentmode<<pos);// 判断是否为下拉输⼊模式if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPD){// 下拉输⼊模式,引脚默认置 0,对 BRR 寄存器写 1 对引脚置 0GPIOx->BRR=(((uint32_t)0x01)<<pinpos);}else{// 判断是否为上拉输⼊模式if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPU){// 上拉输⼊模式,引脚默认值为 1,对 BSRR 寄存器写 1 对引脚置 1GPIOx->BSRR=(((uint32_t)0x01)<<pinpos);}}}}// 把前⾯处理后的暂存值写⼊到 CRL 寄存器之中GPIOx->CRL=tmpreg;}/*--------GPIO CRH 寄存器配置 CRH 寄存器控制着⾼ 8 位 IO- -----*/// 配置端⼝⾼ 8 位,即 Pin8~Pin15if(GPIO_InitStruct->GPIO_Pin>0x00FF){// 先备份 CRH 寄存器的值tmpreg=GPIOx->CRH;// 循环,从 Pin8 开始配对,找出具体的 Pinfor(pinpos=0x00;pinpos<0x08;pinpos++){pos=(((uint32_t)0x01)<<(pinpos+0x08));// pos 与输⼊参数 GPIO_PIN 作位与运算currentpin=((GPIO_InitStruct->GPIO_Pin)&pos);//若 currentpin=pos,则找到使⽤的引脚if(currentpin==pos){//pinpos 的值左移两位(乘以 4),因为寄存器中 4 个位配置⼀个引脚pos=pinpos<<2;//把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变pinmask=((uint32_t)0x0F)<<pos;tmpreg&=~pinmask;// 向寄存器写⼊将要配置的引脚的模式tmpreg|=(currentmode<<pos);// 判断是否为下拉输⼊模式if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPD){// 下拉输⼊模式,引脚默认置 0,对 BRR 寄存器写 1 可对引脚置 0GPIOx->BRR=(((uint32_t)0x01)<<(pinpos+0x08));}// 判断是否为上拉输⼊模式if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPU){// 上拉输⼊模式,引脚默认值为 1,对 BSRR 寄存器写 1 可对引脚置 1GPIOx->BSRR=(((uint32_t)0x01)<<(pinpos+0x08));}}}GPIOx->CRH=tmpreg;}}


以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/5 13:28:24

LeagueAkari:英雄联盟开源智能助手使用完全指南

LeagueAkari&#xff1a;英雄联盟开源智能助手使用完全指南 【免费下载链接】LeagueAkari ✨兴趣使然的&#xff0c;功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari 你是否曾经在英…

作者头像 李华
网站建设 2026/4/4 6:37:21

终极指南:如何快速修复洛雪音乐六音音源失效问题

终极指南&#xff1a;如何快速修复洛雪音乐六音音源失效问题 【免费下载链接】New_lxmusic_source 六音音源修复版 项目地址: https://gitcode.com/gh_mirrors/ne/New_lxmusic_source 还在为洛雪音乐1.6.0版本更新后无法播放音乐而烦恼吗&#xff1f;当您喜爱的歌曲突然…

作者头像 李华
网站建设 2026/4/10 2:19:19

Lucky Draw年会抽奖系统:零门槛搭建企业庆典神器

&#x1f3af; 项目亮点速览 【免费下载链接】lucky-draw 年会抽奖程序 项目地址: https://gitcode.com/gh_mirrors/lu/lucky-draw Lucky Draw作为专为企业年会设计的现代化抽奖解决方案&#xff0c;以其零部署成本和极致易用性脱颖而出。系统基于Vue.js前端框架开发&am…

作者头像 李华
网站建设 2026/4/15 11:23:14

RDP Wrapper完全攻略:让Windows家庭版也能多用户远程桌面

还在为Windows家庭版无法多用户远程桌面而烦恼吗&#xff1f;RDP Wrapper Library这个神奇的开源工具&#xff0c;能帮你彻底解决这个问题&#xff01;通过巧妙的技术手段&#xff0c;它让任何Windows版本都能支持并发远程连接&#xff0c;而且完全免费。 【免费下载链接】rdpw…

作者头像 李华
网站建设 2026/4/12 0:25:21

DLSS Swapper:游戏性能优化的智能管家

DLSS Swapper&#xff1a;游戏性能优化的智能管家 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 在追求极致游戏体验的征程中&#xff0c;每一个帧率提升都值得珍视。DLSS Swapper作为一款专为现代PC玩家设计的智能工…

作者头像 李华
网站建设 2026/4/15 0:33:40

3分钟搭建永久有效的网易云音乐直链解析API

3分钟搭建永久有效的网易云音乐直链解析API 【免费下载链接】netease-cloud-music-api 网易云音乐直链解析 API 项目地址: https://gitcode.com/gh_mirrors/ne/netease-cloud-music-api 还在为网易云音乐分享链接频繁失效而烦恼吗&#xff1f;网易云音乐直链解析API为您…

作者头像 李华