3.STM32寄存器点灯实战:从命名规则到GPIO配置全解析

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

引言:本文面向 STM32 初学者和嵌入式开发入门者,旨在通过一个完整的「点亮 LED」实战项目,帮助读者理解 STM32 的命名规则、GPIO 输入输出模式以及寄存器配置方法。文章从基础概念讲起,逐步深入到数据手册查阅、寄存器操作和代码实现,最终带领读者完成从原理分析到实际点灯的全过程。阅读本文后,你将掌握使用寄存器直接控制 STM32 GPIO 的核心方法,为后续学习更复杂的嵌入式开发打下坚实基础。

一、STM32命名规则

1、产品系列
STM32 表示 ST 公司品牌下 Cortex-Mx 平台架构的 32 位处理器系列

2、产品类型
F:基础型,通用型
A:汽车级别
L:低功耗
S:标准型
T:触摸感应
W:无线产品
G:F 的升级款,同等资源的 F1/3/4 芯片提供更多的增强型外设
C:低成本,高性价比

3、产品特定功能-子系列
050:ARM Cortex-M0 内核,
051:ARM Cortex-M0 内核,入门级
100:ARM Cortex-M3 内核,超值型,外设资源相对较少
101:ARM Cortex-M3 内核,基本型,
102:ARM Cortex-M3 内核,USB
103:ARM Cortex-M3 内核,增强型,含 USB
303:是 103 的升级版,带 DSP 和模拟外设
105:ARM Cortex-M3 内核,USB 互联网型
107:ARM Cortex-M3 内核,USB 互联网型+以太网型
108:ARM Cortex-M3 内核,IEEE802.15.4 标准
151:ARM Cortex-M3 内核,无 LCD 资源
152/162:ARM Cortex-M3 内核,LCD 资源
407:ARM Cortex-M4 内核高性能,带 DSP 和浮点运算
415/417:ARM Cortex-M4 内核高性能

4、芯片引脚数量
D->14, F->20, E->25&24, G->28, K->32, T->36, H->40, S->44, C->48&49;
U->63, R->64&66; J->72; M->80; O->90; V->100; Q->132; Z->144; A->169;
I->176&176+25; B->208; N->216; X->256;
汽车级
8->48
9->64
A->80

5、闪存容量
0 --> 1KB; 1 --> 2KB; 2 --> 4KB; 3 --> 8KB; 4 --> 16KB; 5 --> 25KB; 6 --> 32KB;
7 --> 48KB; 8 --> 64KB; 9 --> 72KB; A --> 96KB; B --> 128KB; Z --> 192KB;
C --> 256KB; D --> 384KB; E --> 512KB; F --> 768KB; G --> 1024KB;
H --> 1536KB; I --> 2048KB;

6、封装类型
B- plastic DIP
D- ceramic DIP
G- ceramic QFP
H-LFBGA/TFBGA
I-UFBGA pitch 0.5mm
J-UFBGA pitch 0.8mm
K-UFBGA pitch 0.65mm
M-plastic SOP,SO
P-TSSOP
Q-plastic QFP
T-QFP
U-UFQFPN
V-VFQFPN
Y-WLCSP

7、工作温度
6&A : -40~85℃;
7&B : -40~105℃;
3&C : -40~125℃;
D : -40~150℃;
————————————————
以上文本为CSDN博主「Jonathan_NYF」的原创文章。
原文链接:https://blog.csdn.net/qq_39747958/article/details/134931252

注意:如有需要更详细的说明请移步该博主文章;

二、点亮学海的那盏灯

电路及基础分析

任务需求:点亮发光二极管
需要PC13引脚输出高电平1;

三、根据任务需求查看数据手册

下面我们先来分析一下基本输入输出模式;

输入模式

浮空输入

优点:电平完全由外部决定

缺点:当外部电平不稳定时,对系统是灾难性的

自行在单片机外部接一个上拉电阻

上拉输入

当外部电路电压不稳定时,打开上拉电阻(MCU内部提供)可提供一个稳定的高电平

下拉输入

当外部电路提供电压时,打开下拉电阻可提供一个稳定的低电平

模拟输入

输出

推挽输出

(输出数据寄存器置一则IO口置一;反之置零)

P-MOS(栅极低电平导通)处于可导通的状态;此时IO口接vdd(高电平)

N-MOS(栅极高电平导通)处于可导通的状态;此时IO口接vss(低电平)

开漏输出

P-MOS不工作

开漏本身不能输出高电平,但如果想输出的话

可使用打开内部上拉或者外接上拉电阻实现,外接输出电平更加灵活

复用开漏

复用推挽

总结

共八种输入输出模式

浮空输入

上拉输入

下拉输入

模拟输入

推挽输出

开漏输出

复用推挽

复用开漏

根据本次项目需求找到对应开发用到的引脚(本次以PC2为例),根据数据手册来配置引脚;

1.采用配置寄存器方式完成;

要操作寄存器直接控制,首先,先参考数据手册看看点亮LED需要进行什么配置;

为了方便理解,直接截图放到此处;

点灯操作步骤:

1、看实物找自己想点亮的灯

2、看原理图-分析电路原理(高电平亮还是低电平亮、接到哪一个引脚)

3、配置为输出模式

4、配置为推挽输出或者开漏输出

5、配置输出速度

6、输出数据0、1(ODR)

步骤:

根据原理图分析LED18对应的网络标签为PC2 ; 且低电平点亮;

先配置端口模式(MODE->输出模式(01/10/11);CNF->推挽输出(00)(可以输出0/1));

端口输出数据使用输出数据寄存器(ODR);

具体实现:

1.PC2选用低寄存器->配置为输出模式,推挽输出;

*(volatile unsigned int *)0x40011000 |=(1<<8);// 配置CRL寄存器bit8=1:MODE1[1:0]的bit0置1,配合bit9=0,将PC2配置为输出模式(速度10MHz)
*(volatile unsigned int *)0x40011000 &=~(1<<9);// 配置CRL寄存器bit9=0:MODE1[1:0]的bit1置0,与bit8=1组合为01,即输出模式、最大速度10MHz
*(volatile unsigned int *)0x40011000 &=~(1<<10);// 配置CRL寄存器bit10=0:CNF1[1:0]的bit0置0,与bit11=0组合为00,即通用推挽输出
*(volatile unsigned int *)0x40011000 &=~(1<<11);// 配置CRL寄存器bit11=0:CNF1[1:0]的bit1置0,与bit10=0组合为00,即通用推挽输出
运算过程

*(volatile unsigned int *)0x40011000 |=(1<<8);//1 对应位设置为1 但是不影响其他位

当前值为 0x40011000 处的寄存器地址:

  原值:         xxxx xxxx xxxx xxxx 
| 掩码 0x100:   0000 0001 0000 0000 
   -------------------------------- 
  结果:         xxxx xxx1 xxxx xxxx 
                        ↑ 第8位被强制置1,其余位保持不变

因为或运算的特性:1 | 任何位 = 10 | 任何位 = 原值,所以只会把目标位设为 1,其他位不受影响——这正是注释里说的"对应位设置为1,但是不影响其他位"。

补充说明

严格来说,直接写 0x40011000 |= ... 在 C 语言里不能通过编译(常量不能作为左值)。实际工程中通常写成指针解引用的形式;

其中 volatile 是为了防止编译器优化掉对硬件寄存器的读写。

RCC时钟使能
  • 找RCC相关寄存器 这里看下GPIOC连到了哪个总线上

  • 找到相关寄存器

  • 分析寄存器这个位置需要写1使能GPIOC端口

  • 找RCC这个寄存器的地址

偏移地址 0x18

基地址:在第二章存储器映射

寄存器地址=0x40021000+0x18=0x40021018

*(volatile unsigned int *)0x40021018 |=(1<<4);

这行代码和之前原理相同,都是通过绝对地址直接操作硬件寄存器,把目标位置 1。

逐段拆解

*(volatile unsigned int *)0x40021018 |= (1 << 4);

部分

含义

0x40021018

寄存器的物理地址

(volatile unsigned int *)

把这个整数地址强制转换为「指向 unsigned int 的指针」

*

解引用指针,即操作该地址里存的值

|= (1 << 4)

把第 4 位(bit4)置 1,其他位不变

运算过程

1 << 4 = 0x10 = 二进制 0001 0000,即只有第 4 位是 1。

寄存器原值: xxxx xxxx xxxx xxxx 
| 掩码0x10: 0000 0000 0001 0000 
--------------------------------- 
结果:       xxxx xxxx xxx1 xxxx 
                         ↑ 第4位被置1

0x40021018 是 STM32 系列中 RCC(复位和时钟控制)外设 的地址区间,具体是 RCC_APB2ENR(APB2 外设时钟使能寄存器)。1 << 4 对应 bit4,在 STM32F1 系列中该位通常是 IOPCEN(GPIOC 端口时钟使能)

所以这行代码的实际意图是:

使能 GPIOC 端口的时钟——在使用 GPIOC 之前必须先打开它的时钟,否则外设不工作。

  • 完整的模式配置(输出模式、推挽输出)

*(volatile unsigned int *)0x40021018 |=(1<<4);//RCC时钟使能
*(volatile unsigned int *)0x40011000 |=(1<<8);//1 对应位设置为1 但是不影响其他位
*(volatile unsigned int *)0x40011000 &=~(1<<9);//写0 目的最终配置为输出模式
*(volatile unsigned int *)0x40011000 &=~(1<<10);//写0 目的最终配置为推挽输出
*(volatile unsigned int *)0x40011000 &=~(1<<11);//写0 目的最终配置为推挽输出
2.配置输出数据寄存器(ODR)

//以下代码二选一,分别实现灯灭以及灯亮的效果;
*(volatile unsigned int *)0x4001100C |=(1<<2);//输出1
*(volatile unsigned int *)0x4001100C &=~(1<<2);//输出0
3.添加.s启动文件
;******************** (C) COPYRIGHT 2017 STMicroelectronics ********************
;* File Name          : startup_stm32f103xe.s
;* Author             : MCD Application Team
;* Description        : STM32F103xE Devices vector table for MDK-ARM toolchain. 
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions ISR address
;*                      - Configure the clock system
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the Cortex-M3 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;******************************************************************************
;* @attention
;*
;* Copyright (c) 2017-2021 STMicroelectronics.
;* All rights reserved.
;*
;* This software is licensed under terms that can be found in the LICENSE file
;* in the root directory of this software component.
;* If no LICENSE file comes with this software, it is provided AS-IS.
;*
;******************************************************************************
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size		EQU     0x400
            AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size      EQU     0x200
            AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit
            PRESERVE8
            THUMB
; Vector Table Mapped to Address 0 at Reset
AREA    RESET, DATA, READONLY
EXPORT  __Vectors
EXPORT  __Vectors_End
EXPORT  __Vectors_Size
__Vectors       DCD     __initial_sp               ; Top of Stack
DCD     Reset_Handler              ; Reset Handler
DCD     NMI_Handler                ; NMI Handler
DCD     HardFault_Handler          ; Hard Fault Handler
DCD     MemManage_Handler          ; MPU Fault Handler
DCD     BusFault_Handler           ; Bus Fault Handler
DCD     UsageFault_Handler         ; Usage Fault Handler
DCD     0                          ; Reserved
DCD     0                          ; Reserved
DCD     0                          ; Reserved
DCD     0                          ; Reserved
DCD     SVC_Handler                ; SVCall Handler
DCD     DebugMon_Handler           ; Debug Monitor Handler
DCD     0                          ; Reserved
DCD     PendSV_Handler             ; PendSV Handler
DCD     SysTick_Handler            ; SysTick Handler
            ; External Interrupts
            DCD     WWDG_IRQHandler            ; Window Watchdog
            DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
            DCD     TAMPER_IRQHandler          ; Tamper
            DCD     RTC_IRQHandler             ; RTC
            DCD     FLASH_IRQHandler           ; Flash
            DCD     RCC_IRQHandler             ; RCC
            DCD     EXTI0_IRQHandler           ; EXTI Line 0
            DCD     EXTI1_IRQHandler           ; EXTI Line 1
            DCD     EXTI2_IRQHandler           ; EXTI Line 2
            DCD     EXTI3_IRQHandler           ; EXTI Line 3
            DCD     EXTI4_IRQHandler           ; EXTI Line 4
            DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
            DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
            DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
            DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
            DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
            DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
            DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
            DCD     ADC1_2_IRQHandler          ; ADC1 &amp; ADC2
            DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
            DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
            DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
            DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
            DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
            DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
            DCD     TIM1_UP_IRQHandler         ; TIM1 Update
            DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
            DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
            DCD     TIM2_IRQHandler            ; TIM2
            DCD     TIM3_IRQHandler            ; TIM3
            DCD     TIM4_IRQHandler            ; TIM4
            DCD     I2C1_EV_IRQHandler         ; I2C1 Event
            DCD     I2C1_ER_IRQHandler         ; I2C1 Error
            DCD     I2C2_EV_IRQHandler         ; I2C2 Event
            DCD     I2C2_ER_IRQHandler         ; I2C2 Error
            DCD     SPI1_IRQHandler            ; SPI1
            DCD     SPI2_IRQHandler            ; SPI2
            DCD     USART1_IRQHandler          ; USART1
            DCD     USART2_IRQHandler          ; USART2
            DCD     USART3_IRQHandler          ; USART3
            DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
            DCD     RTC_Alarm_IRQHandler        ; RTC Alarm through EXTI Line
            DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
            DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
            DCD     TIM8_UP_IRQHandler         ; TIM8 Update
            DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
            DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
            DCD     ADC3_IRQHandler            ; ADC3
            DCD     FSMC_IRQHandler            ; FSMC
            DCD     SDIO_IRQHandler            ; SDIO
            DCD     TIM5_IRQHandler            ; TIM5
            DCD     SPI3_IRQHandler            ; SPI3
            DCD     UART4_IRQHandler           ; UART4
            DCD     UART5_IRQHandler           ; UART5
            DCD     TIM6_IRQHandler            ; TIM6
            DCD     TIM7_IRQHandler            ; TIM7
            DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
            DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
            DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
            DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 &amp; Channel5
__Vectors_End
__Vectors_Size  EQU  __Vectors_End - __Vectors
            AREA    |.text|, CODE, READONLY
; Reset handler
Reset_Handler   PROC
EXPORT  Reset_Handler             [WEAK]
IMPORT  __main
IMPORT  SystemInit
LDR     R0, =SystemInit
BLX     R0
LDR     R0, =__main
BX      R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler     PROC
EXPORT  NMI_Handler                [WEAK]
B       .
ENDP
HardFault_Handler
PROC
EXPORT  HardFault_Handler          [WEAK]
B       .
ENDP
MemManage_Handler
PROC
EXPORT  MemManage_Handler          [WEAK]
B       .
ENDP
BusFault_Handler
PROC
EXPORT  BusFault_Handler           [WEAK]
B       .
ENDP
UsageFault_Handler
PROC
EXPORT  UsageFault_Handler         [WEAK]
B       .
ENDP
SVC_Handler     PROC
EXPORT  SVC_Handler                [WEAK]
B       .
ENDP
DebugMon_Handler
PROC
EXPORT  DebugMon_Handler           [WEAK]
B       .
ENDP
PendSV_Handler  PROC
EXPORT  PendSV_Handler             [WEAK]
B       .
ENDP
SysTick_Handler PROC
EXPORT  SysTick_Handler            [WEAK]
B       .
ENDP
Default_Handler PROC
EXPORT  WWDG_IRQHandler            [WEAK]
EXPORT  PVD_IRQHandler             [WEAK]
EXPORT  TAMPER_IRQHandler          [WEAK]
EXPORT  RTC_IRQHandler             [WEAK]
EXPORT  FLASH_IRQHandler           [WEAK]
EXPORT  RCC_IRQHandler             [WEAK]
EXPORT  EXTI0_IRQHandler           [WEAK]
EXPORT  EXTI1_IRQHandler           [WEAK]
EXPORT  EXTI2_IRQHandler           [WEAK]
EXPORT  EXTI3_IRQHandler           [WEAK]
EXPORT  EXTI4_IRQHandler           [WEAK]
EXPORT  DMA1_Channel1_IRQHandler   [WEAK]
EXPORT  DMA1_Channel2_IRQHandler   [WEAK]
EXPORT  DMA1_Channel3_IRQHandler   [WEAK]
EXPORT  DMA1_Channel4_IRQHandler   [WEAK]
EXPORT  DMA1_Channel5_IRQHandler   [WEAK]
EXPORT  DMA1_Channel6_IRQHandler   [WEAK]
EXPORT  DMA1_Channel7_IRQHandler   [WEAK]
EXPORT  ADC1_2_IRQHandler          [WEAK]
EXPORT  USB_HP_CAN1_TX_IRQHandler  [WEAK]
EXPORT  USB_LP_CAN1_RX0_IRQHandler [WEAK]
EXPORT  CAN1_RX1_IRQHandler        [WEAK]
EXPORT  CAN1_SCE_IRQHandler        [WEAK]
EXPORT  EXTI9_5_IRQHandler         [WEAK]
EXPORT  TIM1_BRK_IRQHandler        [WEAK]
EXPORT  TIM1_UP_IRQHandler         [WEAK]
EXPORT  TIM1_TRG_COM_IRQHandler    [WEAK]
EXPORT  TIM1_CC_IRQHandler         [WEAK]
EXPORT  TIM2_IRQHandler            [WEAK]
EXPORT  TIM3_IRQHandler            [WEAK]
EXPORT  TIM4_IRQHandler            [WEAK]
EXPORT  I2C1_EV_IRQHandler         [WEAK]
EXPORT  I2C1_ER_IRQHandler         [WEAK]
EXPORT  I2C2_EV_IRQHandler         [WEAK]
EXPORT  I2C2_ER_IRQHandler         [WEAK]
EXPORT  SPI1_IRQHandler            [WEAK]
EXPORT  SPI2_IRQHandler            [WEAK]
EXPORT  USART1_IRQHandler          [WEAK]
EXPORT  USART2_IRQHandler          [WEAK]
EXPORT  USART3_IRQHandler          [WEAK]
EXPORT  EXTI15_10_IRQHandler       [WEAK]
EXPORT  RTC_Alarm_IRQHandler        [WEAK]
EXPORT  USBWakeUp_IRQHandler       [WEAK]
EXPORT  TIM8_BRK_IRQHandler        [WEAK]
EXPORT  TIM8_UP_IRQHandler         [WEAK]
EXPORT  TIM8_TRG_COM_IRQHandler    [WEAK]
EXPORT  TIM8_CC_IRQHandler         [WEAK]
EXPORT  ADC3_IRQHandler            [WEAK]
EXPORT  FSMC_IRQHandler            [WEAK]
EXPORT  SDIO_IRQHandler            [WEAK]
EXPORT  TIM5_IRQHandler            [WEAK]
EXPORT  SPI3_IRQHandler            [WEAK]
EXPORT  UART4_IRQHandler           [WEAK]
EXPORT  UART5_IRQHandler           [WEAK]
EXPORT  TIM6_IRQHandler            [WEAK]
EXPORT  TIM7_IRQHandler            [WEAK]
EXPORT  DMA2_Channel1_IRQHandler   [WEAK]
EXPORT  DMA2_Channel2_IRQHandler   [WEAK]
EXPORT  DMA2_Channel3_IRQHandler   [WEAK]
EXPORT  DMA2_Channel4_5_IRQHandler [WEAK]
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_2_IRQHandler
USB_HP_CAN1_TX_IRQHandler
USB_LP_CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
USBWakeUp_IRQHandler
TIM8_BRK_IRQHandler
TIM8_UP_IRQHandler
TIM8_TRG_COM_IRQHandler
TIM8_CC_IRQHandler
ADC3_IRQHandler
FSMC_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_IRQHandler
TIM7_IRQHandler
DMA2_Channel1_IRQHandler
DMA2_Channel2_IRQHandler
DMA2_Channel3_IRQHandler
DMA2_Channel4_5_IRQHandler
B       .
ENDP
        ALIGN
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF      :DEF:__MICROLIB
EXPORT  __initial_sp
EXPORT  __heap_base
EXPORT  __heap_limit
         ELSE
     IMPORT  __use_two_region_memory
     EXPORT  __user_initial_stackheap
__user_initial_stackheap
LDR     R0, =  Heap_Mem
LDR     R1, =(Stack_Mem + Stack_Size)
LDR     R2, = (Heap_Mem +  Heap_Size)
LDR     R3, = Stack_Mem
BX      LR
ALIGN
     ENDIF
 END&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
4.完整项目代码
void SystemInit(void);
int main(void)
{
*(volatile unsigned int *)0x40021018 |=(1<<4);//RCC时钟使能 C
*(volatile unsigned int *)0x40021018 |=(1<<2);//RCC时钟使能 A
*(volatile unsigned int *)0x40011000 |=(1<<8);//1 对应位设置为1 但是不影响其他位
*(volatile unsigned int *)0x40011000 &=~(1<<9);//写0 目的最终配置为输出模式  推挽输出  速度10MHZ
*(volatile unsigned int *)0x4001100C |=(1<<2);//输出1
*(volatile unsigned int *)0x4001100C &=~(1<<2);//输出0
return 0;
}
void SystemInit(void)
{
}
添加进工程即可编译下载;
至此用寄存器点亮LED即可完成;

总结:本文通过点亮 LED 的实战项目,完整演示了使用寄存器操作 STM32 GPIO 的流程。回顾整个点灯步骤:首先查看原理图确认 LED 对应的引脚(本例为 PC2,低电平点亮);然后使能 GPIOC 端口时钟,通过 RCC_APB2ENR 寄存器(地址 0x40021018)的 bit4 置 1 实现;接着配置端口模式,通过 CRL 寄存器(地址 0x40011000)将 PC2 配置为输出模式、推挽输出、速度 10MHz;最后通过输出数据寄存器 ODR(地址 0x4001100C)的 bit2 写入 0 或 1 来控制灯的亮灭。关键寄存器配置可归纳为:RCC_APB2ENR 使能时钟、CRL 配置模式、ODR 输出数据。掌握这套寄存器操作思路,就能举一反三,灵活控制 STM32 的其他外设。

四、常见问题与排查

在点灯实战过程中,初学者经常会遇到编译报错、LED 不亮、引脚配置错误等问题。下面针对这些高频问题给出原因分析和解决方法,并附上调试建议。

1. 编译错误

问题现象:编译时报错,例如 lvalue required as left operand of assignmentundefined symbol

原因分析:

  • 直接对常量地址使用 0x40011000 |= ... 这类写法,在 C 语言中常量不能作为左值,无法通过编译。
  • 缺少启动文件(.s 文件)或启动文件未正确添加到工程中,导致链接阶段报 undefined symbol 错误。
  • 头文件路径配置错误,或未包含必要的寄存器定义头文件。

解决方法:

  • 将寄存器操作改写为指针解引用形式:*(volatile unsigned int *)0x40011000 |= (1 << 8);,其中 volatile 防止编译器优化掉对硬件寄存器的读写。
  • 确认已将 startup_stm32f103xe.s 启动文件添加到工程,并正确配置了芯片型号(如 STM32F103C8T6 对应 STM32F103xE 系列)。
  • 检查编译器的 Include Path 是否包含标准外设库或寄存器定义所在目录。

2. LED 不亮

问题现象:程序编译下载成功,但 LED 始终不亮。

原因分析:

  • 未使能对应端口的时钟。GPIOC 端口时钟未打开时,寄存器配置不生效,外设不工作。
  • 引脚配置错误,例如把 PC2 误配成输入模式,或 CNF 位配置成了开漏输出。
  • 输出电平与电路不匹配。本例中 LED18 是低电平点亮,若向 ODR 写入 1(高电平),灯反而不会亮。
  • 硬件连接问题,如 LED 正负极接反、限流电阻缺失或引脚虚焊。

解决方法:

  • 确认已执行 *(volatile unsigned int *)0x40021018 |= (1 << 4); 使能 GPIOC 时钟。
  • 核对 CRL 寄存器配置,确保 PC2 为输出模式(MODE=01)、推挽输出(CNF=00)。
  • 根据原理图确认点亮电平。本例为低电平点亮,应向 ODR 的 bit2 写入 0:*(volatile unsigned int *)0x4001100C &= ~(1 << 2);
  • 用万用表测量 PC2 引脚电压,检查 LED 及限流电阻是否正常,确认硬件连接无误。

3. 引脚配置错误

问题现象:配置了 PC2 但实际控制的是其他引脚,或引脚无输出。

原因分析:

  • 寄存器位操作错误,例如移位位数算错,把 bit8 写成 bit7,导致配置到了相邻引脚。
  • 使用了错误的寄存器地址,例如把 CRL(0x40011000)与 CRH(0x40011004)混淆。PC2 属于低 8 位引脚,应使用 CRL;若配置 PC8-PC15 则需使用 CRH。
  • ODR 寄存器地址写错,或操作位与引脚号不对应。

解决方法:

  • 对照数据手册逐位核对寄存器配置。PC2 对应 CRL 寄存器的 bit8-bit11(MODE1 和 CNF1),ODR 对应 bit2。
  • 确认引脚编号与寄存器位一一对应:PC0-PC7 使用 CRL,PC8-PC15 使用 CRH。
  • 建议使用调试器(如 ST-Link)在 Keil 中查看寄存器的实时值,确认配置是否写入成功。

4. 调试建议

  • 分步验证:先单独使能时钟,再配置模式,最后输出数据,每步都用调试器观察寄存器值是否符合预期。
  • 使用调试器:在 Keil MDK 中进入 Debug 模式,打开 Peripherals 窗口查看 GPIO 和 RCC 寄存器的实时状态,快速定位配置是否生效。
  • 简化电路:排查硬件问题时,可先用万用表直接测量引脚电平,排除 LED 或电阻故障的干扰。
  • 对照参考代码:将完整项目代码与本文示例逐行对比,重点检查时钟使能、CRL 配置和 ODR 输出三处关键代码。
  • 善用搜索:遇到报错时,将错误信息复制到搜索引擎或 CSDN 社区搜索,通常能找到同类问题的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值