news 2026/4/17 17:24:41

【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/18 7:54:07

QQ音乐加密文件解密:macOS用户的完整解决方案

QQ音乐加密文件解密&#xff1a;macOS用户的完整解决方案 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac&#xff0c;qmc0,qmc3转mp3, mflac,mflac0等转flac)&#xff0c;仅支持macOS&#xff0c;可自动识别到QQ音乐下载目录&#xff0c;默认转换结果存…

作者头像 李华
网站建设 2026/4/17 20:36:20

付费墙访问工具深度解析:5种创新解决方案的技术实现与应用指南

在当今信息爆炸的时代&#xff0c;付费墙已成为众多优质内容平台的标准配置&#xff0c;为用户获取信息带来了诸多不便。本文将通过技术层面的深度分析&#xff0c;为你全面解析5款主流付费墙访问工具的技术原理、性能表现和最佳选择策略&#xff0c;帮助你在信息获取便利性和版…

作者头像 李华
网站建设 2026/4/18 7:53:09

Windows右键菜单重构指南:三步实现桌面操作高效优化

Windows右键菜单重构指南&#xff1a;三步实现桌面操作高效优化 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 还在被杂乱的右键菜单困扰吗&#xff1f;每次点击…

作者头像 李华
网站建设 2026/4/18 5:43:07

智慧树自动学习插件:解放双手的网课高效学习方案

智慧树自动学习插件&#xff1a;解放双手的网课高效学习方案 【免费下载链接】zhihuishu 智慧树刷课插件&#xff0c;自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 在繁忙的学业和工作中&#xff0c;你是否曾经为了完成网课…

作者头像 李华
网站建设 2026/4/18 6:57:35

Windows窗口置顶神器:告别窗口遮挡的终极解决方案

Windows窗口置顶神器&#xff1a;告别窗口遮挡的终极解决方案 【免费下载链接】AlwaysOnTop Make a Windows application always run on top 项目地址: https://gitcode.com/gh_mirrors/al/AlwaysOnTop 在日常电脑使用中&#xff0c;你是否经常遇到重要窗口被其他程序覆…

作者头像 李华
网站建设 2026/4/18 3:48:08

碧蓝航线Alas自动化脚本完整指南:轻松打造智能游戏管家

碧蓝航线Alas自动化脚本完整指南&#xff1a;轻松打造智能游戏管家 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 碧蓝航线…

作者头像 李华