一、端口配置低寄存器(GPIOx_CRL)(Port Configuration Register Low)
偏移地址:0x00
复位值:0x4444 4444

二、端口配置高寄存器(GPIOx_CRH)(Port Configuration Register High)
偏移地址:0x04
复位值:0x4444 4444

三、端口输入数据寄存器(GPIOx_IDR)(Intput Data Register)
地址偏移:0x08
复位值:0x0000 XXXX

四、端口输出数据寄存器(GPIOx_ODR)(Output Data Register)
地址偏移:0Ch
复位值:0x0000 0000

五、端口位设置/清除寄存器(GPIOx_BSRR)( Bit Setting/Reset Register)
地址偏移:0x10
复位值:0x0000 0000

六、端口位清除寄存器(GPIOx_BRR)( Bit Reset Register)
地址偏移:0x14
复位值:0x0000 0000

七、端口配置锁定寄存器(GPIOx_LCKR)(Port configuration LOCK Register)
地址偏移:0x18
复位值:0x0000 0000

八、C语言的封装
stm32F103_gpio_reg.h
c
#ifndef __STM32F103_GPIO_REG_H
#define __STM32F103_GPIO_REG_H
#include <stdint.h> // 引入标准整数类型(uint32_t等),替代unsigned int更规范
// ===================== 1. 总线基地址定义 =====================
#define PERIPH_BASE ((uint32_t)0x40000000) // 外设基地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) // APB2总线基地址
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000) // AHB总线基地址
// ===================== 2. RCC时钟寄存器(GPIO依赖) =====================
#define RCC_BASE (AHBPERIPH_BASE + 0x1000) // RCC基地址
// APB2外设时钟使能寄存器 (RCC_APB2ENR)
#define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x18))
// GPIO时钟使能位定义
#define RCC_APB2ENR_IOPAEN ((uint32_t)0x00000004) // GPIOA时钟使能
#define RCC_APB2ENR_IOPBEN ((uint32_t)0x00000008) // GPIOB时钟使能
#define RCC_APB2ENR_IOPCEN ((uint32_t)0x00000010) // GPIOC时钟使能
#define RCC_APB2ENR_IOPDEN ((uint32_t)0x00000020) // GPIOD时钟使能
#define RCC_APB2ENR_IOPEEN ((uint32_t)0x00000040) // GPIOE时钟使能
#define RCC_APB2ENR_IOPFEN ((uint32_t)0x00000080) // GPIOF时钟使能
#define RCC_APB2ENR_IOPGEN ((uint32_t)0x00000100) // GPIOG时钟使能
// ===================== 3. GPIO寄存器基地址 =====================
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) // GPIOA基地址
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) // GPIOB基地址
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) // GPIOC基地址
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) // GPIOD基地址
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) // GPIOE基地址
#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00) // GPIOF基地址
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000) // GPIOG基地址
// ===================== 4. GPIO寄存器偏移量(所有GPIO通用) =====================
#define GPIO_CRL_OFFSET ((uint32_t)0x00) // 端口配置低寄存器(Pin0~7)
#define GPIO_CRH_OFFSET ((uint32_t)0x04) // 端口配置高寄存器(Pin8~15)
#define GPIO_IDR_OFFSET ((uint32_t)0x08) // 输入数据寄存器
#define GPIO_ODR_OFFSET ((uint32_t)0x0C) // 输出数据寄存器
#define GPIO_BSRR_OFFSET ((uint32_t)0x10) // 位设置/复位寄存器
#define GPIO_BRR_OFFSET ((uint32_t)0x14) // 位复位寄存器
#define GPIO_LCKR_OFFSET ((uint32_t)0x18) // 配置锁定寄存器
// ===================== 5. 通用GPIO寄存器宏定义(核心,一键访问任意端口寄存器) =====================
// 示例:GPIO_REG(GPIOA, CRL) 等价于 GPIOA的CRL寄存器地址
#define GPIO_REG(PORT, REG) (*(volatile uint32_t *)(PORT##_BASE + GPIO_##REG##_OFFSET))
// ===================== 6. 简化操作的宏(可选,提升代码可读性) =====================
// 置位某引脚(通过BSRR,原子操作,无需关中断)
#define GPIO_SET_PIN(PORT, PIN) (GPIO_REG(PORT, BSRR) = (1 << PIN))
// 复位某引脚(通过BSRR的高16位)
#define GPIO_RESET_PIN(PORT, PIN) (GPIO_REG(PORT, BSRR) = (1 << (PIN + 16)))
// 读取某引脚电平
#define GPIO_READ_PIN(PORT, PIN) ((GPIO_REG(PORT, IDR) & (1 << PIN)) ? 1 : 0)
#endif /* __STM32F103_GPIO_REG_H */
main.c
c
#include "stm32f103_GPIO_REG_H"
// 简单延时函数
void Delay_ms(uint32_t ms)
{
uint32_t i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 1141; j++);
}
int main(void)
{
// 步骤1:开启GPIOB和GPIOA时钟
RCC_APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPAEN;
// 步骤2:配置PB0为推挽输出(50MHz)
// 清空PB0的CRL位(0~3位)
GPIO_REG(GPIOB, CRL) &= ~((uint32_t)0x0000000F);
// 配置MODE0=11(50MHz输出),CNF0=00(推挽输出)
GPIO_REG(GPIOB, CRL) |= ((uint32_t)0x00000003);
// 步骤3:配置PA0为上拉输入
// 清空PA0的CRL位(0~3位)
GPIO_REG(GPIOA, CRL) &= ~((uint32_t)0x0000000F);
// MODE0=00(输入模式),CNF0=10(上拉/下拉输入)
GPIO_REG(GPIOA, CRL) |= ((uint32_t)0x00000008);
// 上拉:ODR置1,下拉置0
GPIO_REG(GPIOA, ODR) |= (1 << 0);
// 主循环
while(1)
{
// 如果PA0为高电平,PB0亮;否则灭
if(GPIO_READ_PIN(GPIOA, 0))
{
GPIO_SET_PIN(GPIOB, 0); // PB0置1(亮)
}
else
{
GPIO_RESET_PIN(GPIOB, 0); // PB0置0(灭)
}
Delay_ms(100);
}
}