第1章:单片机基础与开发环境搭建

各位同学,咱们今天聊聊单片机。说实话,我做了十几年嵌入式开发,单片机这东西就像老朋友一样熟悉。你想想看,从智能家电到工业控制,从无人机到医疗器械,到处都有它的影子。这一章,我们就以STM32为例,把单片机的基础知识和开发环境搭建讲透。

1.1 单片机内部结构:内核、存储器、外设

单片机说白了就是一个微型计算机。它把CPU、内存、各种外设接口都集成在一个芯片里。我刚开始学的时候,总觉得这东西很神秘,后来拆了几颗芯片,看了内部框图,才恍然大悟——原来就这么回事。

1.1.1 内核(Core)

STM32的内核基于ARM Cortex-M系列。以最常见的STM32F103为例,它用的是Cortex-M3内核。这个内核的特点我总结一下:

  • 32位RISC架构:一次能处理32位数据,效率高
  • 三级流水线:取指、译码、执行,流水线操作
  • Thumb-2指令集:16位和32位指令混编,代码密度高
  • 嵌套向量中断控制器(NVIC):支持最多240个中断,优先级可配置

核心提示:我在项目中遇到过一个问题——中断响应太慢。后来发现是NVIC优先级配置没弄对。记住,高优先级中断可以打断低优先级,但同优先级不能互相打断。这个坑我踩过,你们别重蹈覆辙。

1.1.2 存储器(Memory)

STM32的存储器分为三块:Flash、SRAM、系统存储器。我画个图给你们看:

STM32存储器结构 Flash(程序存储器) 64KB - 2MB,存放用户程序 SRAM(数据存储器) 20KB - 512KB,存放变量和堆栈 系统存储器(Bootloader) 存放出厂固件,用于ISP下载

嗯,这里要注意:Flash的擦写次数有限,一般10万次左右。我有个同事在调试时频繁下载程序,结果把Flash写坏了。所以调试阶段尽量用RAM运行,或者用仿真器在线调试。

1.1.3 外设(Peripherals)

STM32的外设非常丰富。我个人习惯把它们分成三类:

外设类别 典型外设 用途
通信接口 USART、SPI、I2C、CAN、USB 与其他设备交换数据
模拟外设 ADC、DAC、比较器 处理模拟信号
定时/控制 定时器、PWM、看门狗 产生时序、控制电机

个人经验:选型时别贪多。我见过有人选了个外设超多的芯片,结果大部分引脚都悬空。够用就好,省钱省空间。

1.2 单片机开发流程

开发一个单片机项目,流程其实挺固定的。我把它总结成6步:

  1. 需求分析:搞清楚要做什么,输入输出是什么
  2. 芯片选型:根据需求选合适的STM32型号
  3. 硬件设计:画原理图、PCB,打样焊接
  4. 软件开发:写代码、调试、烧录
  5. 系统联调:软硬件一起跑,找bug
  6. 测试验证:功能测试、可靠性测试

你想想看,这6步里哪步最容易出问题?我个人觉得是第4步——软件开发。硬件问题往往一眼就能看出来,软件bug有时候藏得很深。我曾经花了一周时间找一个定时器配置错误,最后发现是预分频系数算错了。嗯,从那以后我写代码都先画流程图。

1.3 开发环境安装与配置

开发STM32,主流工具有两个:Keil MDK和STM32CubeIDE。我两个都用过,说说我的感受。

1.3.1 Keil MDK安装

Keil是老牌工具,稳定可靠。安装步骤:

  • 去ARM官网下载MDK-ARM安装包
  • 运行安装程序,一路Next
  • 安装完成后,打开Pack Installer
  • 搜索你的芯片型号(比如STM32F103C8)并安装对应的Pack

注意:Keil的License需要购买,但可以申请评估版(32KB代码限制)。如果你只是学学,评估版够用了。我当年就是拿评估版入的门。

1.3.2 STM32CubeIDE安装

STM32CubeIDE是ST官方出的免费IDE,基于Eclipse。我个人更推荐新手用这个,因为:

  • 完全免费,没有代码限制
  • 集成了CubeMX,图形化配置外设
  • 自带编译器,不用额外装

安装很简单:去ST官网下载安装包,双击安装,选好安装路径,等几分钟就好了。我第一次用的时候,发现它自动识别了我的ST-Link调试器,省了不少事。

1.4 第一个单片机工程:点亮LED

好了,理论说完了,咱们动手。点亮LED是嵌入式界的"Hello World"。我带你走一遍流程。

1.4.1 硬件连接

假设我们用STM32F103C8T6最小系统板,LED接在PC13引脚(很多开发板板载LED就是这个引脚)。电路很简单:

  • LED正极接PC13
  • LED负极串联一个220Ω电阻到GND

1.4.2 代码实现

在STM32CubeIDE中新建工程,选好芯片型号。然后写代码:

#include "stm32f1xx_hal.h"

void LED_Init(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟
    
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  // 推挽输出
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

int main(void)
{
    HAL_Init();
    LED_Init();
    
    while(1)
    {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);  // 点亮
        HAL_Delay(500);  // 延时500ms
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // 熄灭
        HAL_Delay(500);
    }
}

关键点:记得使能时钟!STM32的外设时钟默认是关闭的。我刚开始学的时候,忘了开时钟,折腾了半天LED就是不亮。后来查手册才发现这个坑。

1.4.3 编译下载

代码写好后,点击编译按钮(锤子图标)。如果没报错,就连接ST-Link,点击下载按钮。下载成功后,你会看到LED开始闪烁。

我第一次点亮LED的时候,心里那个激动啊。虽然只是个小灯,但意味着你真正开始控制硬件了。这种感觉,嗯,很奇妙。

调试技巧:如果LED不亮,先检查硬件连接,再用万用表测引脚电压。PC13输出低电平时,电压应该是0V左右;输出高电平时,应该是3.3V。如果电压正常但灯不亮,那就是电路问题。

好了,这一章的内容就到这里。单片机开发其实不难,关键是多动手。下一章我们会深入GPIO的细节,到时候再聊。


专注资料整理