1. 寄存器基础与开发环境搭建
各位同学,欢迎来到这门实战课程。第一节课,咱们不急着写代码,先把地基打牢。
寄存器到底是什么?说白了,它就是单片机内部一个个“开关”和“数值存储格”。你往某个地址写个1,引脚就输出高电平;你改另一个寄存器的值,定时器就开始计数。我当年刚接触单片机时,总觉得寄存器很神秘,后来发现——它就是芯片设计者留给我们的“控制面板”。
1.1 寄存器的本质:你与硬件对话的窗口
每个寄存器都有固定的地址,比如STM32F103的GPIOA_ODR寄存器地址是0x4001080C。你往这个地址写数据,就能控制PA0~PA15的电平。
核心概念:寄存器 = 地址 + 位定义。你操作的是地址,影响的是硬件。
举个例子,点亮LED通常需要两步:
- 配置模式:把GPIO引脚设为推挽输出(修改CRL或CRH寄存器)
- 输出电平:往ODR寄存器写1或0
我见过不少新手直接调用库函数,出了问题根本不知道从哪查。你想想看,如果你能直接读懂寄存器手册,定位问题会快多少?
1.2 开发板选型:别贪多,够用就好
本课程选用STM32F103C8T6(蓝色 pill 板)作为主控。为什么选它?
- 价格便宜,几十块钱就能买到
- 资源丰富:72MHz主频、20KB RAM、64KB Flash
- 外设齐全:定时器、ADC、USART、SPI、I2C全都有
- 社区资料多,遇到问题好查
| 外设 | 数量 | 本课程用途 |
|---|---|---|
| GPIO | 37个 | LED控制、按键输入 |
| 定时器 | 3个通用+1个高级 | PWM输出 |
| USART | 3个 | 串口通信 |
| ADC | 2个(10通道) | 模拟量采集 |
我的建议:如果你手头有其他开发板,比如GD32、AT32,原理一样,只是寄存器地址不同。先拿手头的板子跑通,再换型号也不迟。
1.3 开发环境安装:Keil MDK 与 IAR
我个人习惯用Keil MDK,但IAR也有它的优势。咱们两个都讲,你选一个就行。
Keil MDK 安装步骤
- 从ARM官网下载MDK-Arm(5.36以上版本)
- 安装时选择默认路径,注意勾选“添加环境变量”
- 安装对应芯片的器件包(Keil.STM32F1xx_DFP)
- 破解(你懂的,但请支持正版)
IAR EWARM 安装步骤
- 下载IAR Embedded Workbench for ARM
- 安装时选择“Full Installation”
- 导入STM32F1的器件描述文件
- 配置许可证(试用版30天)
避坑指南:我曾经在Win10上装Keil 4,结果死活识别不了调试器。后来发现是驱动签名问题。建议用Keil 5.38以上版本,Win10/Win11都兼容。
1.4 第一个寄存器工程:点亮LED
咱们直接上手。新建一个Keil工程,选择STM32F103C8,然后写代码。
先看硬件连接:LED接在PC13(高电平点亮)。
// 寄存器方式点亮LED
// 文件: main.c
// 外设基地址
#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
// 寄存器偏移
#define GPIOC_CRH (*(volatile unsigned int *)(GPIOC_BASE + 0x04))
#define GPIOC_ODR (*(volatile unsigned int *)(GPIOC_BASE + 0x0C))
// RCC寄存器
#define RCC_BASE (APB2PERIPH_BASE + 0x1000 - 0x1000) // 0x40021000
#define RCC_APB2ENR (*(volatile unsigned int *)(RCC_BASE + 0x18))
int main(void)
{
// 1. 使能GPIOC时钟
RCC_APB2ENR |= (1 << 4); // 位4:IOPCEN
// 2. 配置PC13为推挽输出(CRH的位20~23)
GPIOC_CRH &= ~(0xF << 20); // 先清零
GPIOC_CRH |= (0x3 << 20); // 设置CNF=00, MODE=11(输出50MHz)
// 3. 输出高电平
GPIOC_ODR |= (1 << 13); // PC13输出1
while(1)
{
// 空循环
}
}
这段代码做了三件事:开时钟、配模式、写电平。每一步都对应一个寄存器操作。
关键点:volatile关键字不能少。它告诉编译器,这个变量的值可能被硬件修改,不要优化掉。我见过有人忘了加,结果调试了一下午。
1.5 知识结构图:寄存器操作全流程
下面这张图帮你理清思路:从芯片手册到代码实现,每一步都离不开寄存器。
1.6 调试与故障定位:从寄存器值反推问题
代码写完了,下载到板子上,灯不亮。怎么办?
我的调试步骤:
- 检查时钟:在调试器里看RCC_APB2ENR寄存器的位4是不是1
- 检查模式:看GPIOC_CRH的位20~23是不是0x3
- 检查电平:看GPIOC_ODR的位13是不是1
- 检查硬件:用万用表量PC13引脚电压
小技巧:Keil的Watch窗口可以直接输入寄存器地址查看值。比如输入 *(unsigned int*)0x40011004 就能看到CRH寄存器的值。我调试时经常这么干,比看变量方便多了。