STM32 开发 - 点灯案例(点灯案例实现、点灯案例解读)

点灯案例实现

#include <stdint.h>

typedef volatile struct
{
    uint32_t CRL;  // 0x00
    uint32_t CRH;  // 0x04
    uint32_t IDR;  // 0x08
    uint32_t ODR;  // 0x0C
    uint32_t BSRR; // 0x10
    uint32_t BRR;  // 0x14
    uint32_t LCKR; // 0x18
} GPIO_TypeDef;

#define GPIOB_BASE 0x40010C00UL
#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE)

int main()
{
    uint32_t *pAPB2ENR = (uint32_t *)0x40021018;
    *pAPB2ENR |= (1 << 3);

    // 清除 PB5 的配置位 [23:20]
    uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
    clear_mask = clear_mask << (5 * 4); // 00000000 11110000 00000000 00000000
    clear_mask = ~clear_mask;           // 11111111 00001111 11111111 11111111
    GPIOB->CRL = GPIOB->CRL & clear_mask;

    // 设置 PB5 为推挽输出模式,最大速度为 50MHz
    uint32_t config_value = 0x3;         // 00000000 00000000 00000000 00000011
    config_value = config_value << (5 * 4); // 00000000 00110000 00000000 00000000
    GPIOB->CRL = GPIOB->CRL | config_value;

    // 点亮 PB5
    uint32_t pin_mask = 1;    // 00000000 00000000 00000000 00000001
    pin_mask = pin_mask << 5; // 00000000 00000000 00000000 00010000
    pin_mask = ~pin_mask; // 11111111 11111111 11111111 11101111
    GPIOB->ODR = GPIOB->ODR & pin_mask;

    while (1)
    {
    }
}

点灯案例解读

1、时钟使能
  1. 参考【硬件手册】,找到灯 LED0 的 GPIO 为 PB5,PB5 表示它在 GPIO 端口 B 的第 5 号引脚
  1. 参考【STM32 参考手册】,找到 GPIOB 对应的总线,这里是 APB2
  1. 参考【STM32 参考手册】,找到复位和时钟控制 RCC 的起始地址,这里是 0x4002 1000 - 0x4002 13FF
  1. 参考【STM32 参考手册】,找到 APB2 对应的时钟寄存器 RCC_APB2ENR,偏移量为 018h
  • 注:018h 是一种表示十六进制数的写法,主要用于某些汇编语言和旧式编程环境中
h 后缀:表示这是一个十六进制数(Hexadecimal)

前导 0:是可选的,用于对齐或格式美观,例如,018h 和 18h 相同

实际值:18h = 0x18 = 24(十进制)
寄存器名偏移量地址说明
RCC_CR0x000x40021000时钟控制寄存器
RCC_CFGR0x040x40021004时钟配置寄存器
RCC_CIR0x080x40021008时钟中断寄存器
RCC_APB2RSTR0x0C0x4002100CAPB2 外设复位寄存器
RCC_APB1RSTR0x100x40021010APB1 外设复位寄存器
RCC_AHBENR0x140x40021014AHB 外设时钟使能
RCC_APB2ENR0x180x40021018APB2 外设时钟使能
RCC_APB1ENR0x1C0x4002101CAPB1 外设时钟使能
RCC_BDCR0x200x40021020备份域控制寄存器
RCC_CSR0x240x40021024控制 / 状态寄存器
  1. 参考【STM32 参考手册】,GPIOB 时钟使能位是第 3 位(从 0 开始),使能 GPIOB 时钟
位号名称说明
0AFIOEN复用功能 IO 时钟使能
2IOPAENGPIOA 时钟使能
3IOPBENGPIOB 时钟使能
4IOPCENGPIOC 时钟使能
5IOPDENGPIOD 时钟使能
6IOPEENGPIOE 时钟使能
uint32_t *pAPB2ENR = (uint32_t *)0x40021018;
*pAPB2ENR |= (1 << 3);
2、点亮灯
  1. 参考【STM32 参考手册】,找到 GPIOB 的起始地址,这里是 0X4001 0C00 - 0x4001 0FFF
寄存器名偏移量地址说明
GPIOB_CRL0x000x4001 0C00配置 PB0 ~ PB7 的模式(输入 / 输出等)
GPIOB_CRH0x040x4001 0C04配置 PB8 ~ PB15 的模式(输入 / 输出等)
GPIOB_IDR0x080x4001 0C08读取引脚输入电平
GPIOB_ODR0x0C0x4001 0C0C控制引脚输出电平
GPIOB_BSRR0x100x4001 0C10原子操作(置位 / 复位引脚)
GPIOB_BRR0x140x4001 0C14快速复位引脚(仅写)
GPIOB_LCKR0x180x4001 0C18锁定引脚配置
保留0x1C~0x3FF-未使用,为未来扩展预留
  1. 参考【STM32 参考手册】,操作 GPIOx_CRL,清除 PB5 的配置位
// 清除 PB5 的配置位 [23:20]
uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
clear_mask = clear_mask << (5 * 4); // 00000000 11110000 00000000 00000000
clear_mask = ~clear_mask;           // 11111111 00001111 11111111 11111111
GPIOB->CRL = GPIOB->CRL & clear_mask;
  1. 参考【STM32 参考手册】,操作 GPIOx_CRL,设置 PB5 为推挽输出模式,最大速度为 50MHz
// 设置 PB5 为推挽输出模式,最大速度为 50MHz
uint32_t config_value = 0x3;         // 00000000 00000000 00000000 00000011
config_value = config_value << (5 * 4); // 00000000 00110000 00000000 00000000
GPIOB->CRL = GPIOB->CRL | config_value;
  1. 参考【STM32 参考手册】,操作 GPIOB_ODR,点亮 PB5
uint32_t pin_mask = 1;    // 00000000 00000000 00000000 00000001
pin_mask = pin_mask << 5; // 00000000 00000000 00000000 00010000
pin_mask = ~pin_mask; // 11111111 11111111 11111111 11101111
GPIOB->ODR = GPIOB->ODR & pin_mask;

补充学习

1、GPIOx_CRLGPIOx_CRH
  1. GPIOx_CRL(Port Configuration Register Low)用于配置 GPIO 端口低 8 位引脚(Pin0 - Pin7)的工作模式,每个引脚占用 4 个位,共 32 位

  2. GPIOx_CRH(Port Configuration Register High)用于配置 GPIO 端口高 8 位引脚(Pin8 - Pin15)的工作模式,每个引脚占用 4 个位,共 32 位

  • 每个引脚的配置由 CNFy[1:0]MODEy[1:0] 组成
位域说明
CNFy[1:0]配置位,控制引脚的工作模式
MODEy[1:0]模式位,控制输出模式的速率或输入模式
CNFy输入模式(MODEy = 00输出模式(MODEy > 00
00模拟输入通用推挽输出
01浮空输入(复位默认)通用开漏输出
10上拉 / 下拉输入复用功能推挽输出
11保留复用功能开漏输出
2、清除配置位
  1. 清除 PB0 的配置位
// 清除 PB0 的配置位 [3:0]
uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
clear_mask = clear_mask << (0 * 4); // 00000000 00000000 00000000 00001111
clear_mask = ~clear_mask;           // 11111111 11111111 11111111 11110000
GPIOB->CRL = GPIOB->CRL & clear_mask;
  1. 清除 PB1 的配置位
// 清除 PB1 的配置位 [7:4]
uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
clear_mask = clear_mask << (1 * 4); // 00000000 00000000 00000000 11110000
clear_mask = ~clear_mask;           // 11111111 11111111 11111111 00001111
GPIOB->CRL = GPIOB->CRL & clear_mask;
  1. 清除 PB2 的配置位
// 清除 PB2 的配置位 [11:8]
uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
clear_mask = clear_mask << (1 * 4); // 00000000 00000000 00001111 00000000
clear_mask = ~clear_mask;           // 11111111 11111111 11110000 11111111
GPIOB->CRL = GPIOB->CRL & clear_mask;
  • 依次类推,清除 PB5 的配置位
// 清除 PB5 的配置位 [23:20]
uint32_t clear_mask = 0xF;       // 00000000 00000000 00000000 00001111
clear_mask = clear_mask << (5 * 4); // 00000000 11110000 00000000 00000000
clear_mask = ~clear_mask;           // 11111111 00001111 11111111 11111111
GPIOB->CRL = GPIOB->CRL & clear_mask;
2、GPIOB_ODR
位域说明
ODRy[15:0]每个 ODRy 位对应一个 GPIO 引脚
0:输出低电平
1:输出高电平
保留[31:16 ]保留
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值