STM32 入门教程:从零基础到项目实战
STM32 微控制器凭借其高性能、低功耗、丰富外设以及庞大的生态系统,成为工程师和开发者的首选。对于刚接触 STM32 的新手来说,面对复杂的芯片架构和开发流程,往往会感到无从下手。本文将以通俗易懂的语言,结合实际案例,带领大家从零开始,逐步掌握 STM32 的开发技能,助力大家在嵌入式开发的道路上迈出坚实的第一步。
目录
一、STM32 基础概念
1.1 STM32 简介
1.2 ARM Cortex-M 内核
1.3 STM32 的优势
二、STM32 硬件基础
2.1 STM32 最小系统
2.2 开发板选择
三、开发环境搭建
3.1 软件工具
3.2 安装步骤
3.3 调试工具
四、STM32 编程基础
4.1 编程语言
4.2 固件库与 HAL 库
4.3 第一个 STM32 程序:点亮 LED 灯
五、STM32 外设应用
5.1 通用定时器(TIM)
5.2 串行通信接口(USART)
5.3 模拟数字转换器(ADC)
六、实战项目:简易温湿度监测系统
6.1 项目需求
6.2 硬件设计
6.3 软件设计
七、总结与展望
一、STM32 基础概念
1.1 STM32 简介
STM32 是意法半导体(ST)公司推出的基于 ARM Cortex-M 内核的 32 位微控制器。它涵盖了多个系列,如 F1、F4、H7 等,每个系列针对不同的应用场景,具有不同的性能和特性。例如,STM32F1 系列适合对成本和功耗敏感的基础控制应用;STM32F4 系列则在 F1 系列的基础上,增强了性能和外设功能,适用于对处理能力要求较高的应用,如工业控制、智能仪表等;STM32H7 系列更是以其极高的性能和丰富的外设,成为高端嵌入式应用的理想选择 。
1.2 ARM Cortex-M 内核
ARM Cortex-M 内核是 STM32 的核心,它具有高性能、低功耗和低成本的特点。不同的 Cortex-M 内核版本(如 M0、M3、M4、M7 等)在性能和功能上有所差异。例如,Cortex-M0 内核简单易用,功耗极低,适合对成本和功耗要求苛刻的简单控制场景;Cortex-M4 内核在 M0 的基础上,增加了浮点运算单元(FPU)和数字信号处理(DSP)指令集,极大地增强了芯片在数字信号处理方面的能力,广泛应用于音频处理、电机控制等地方。
1.3 STM32 的优势
与其他微控制器相比,STM32 具有明显的优势。其一,丰富的外设资源,包括通用定时器(TIM)、串行通信接口(USART、SPI、I²C 等)、模拟数字转换器(ADC)、数字模拟转换器(DAC)等,能够满足各种不同的应用需求;其二,强大的生态系统,ST 官方提供了完善的固件库和 HAL 库,降低了开发难度,同时众多开发者社区和论坛也提供了大量的开源代码和技术资料,方便开发者学习和借鉴;其三,高性价比,在提供高性能和丰富功能的同时,保持了相对较低的成本,适合大规模应用。
二、STM32 硬件基础
2.1 STM32 最小系统
STM32 最小系统是保证芯片正常运行的最基本电路,主要包括电源电路、时钟电路、复位电路和调试接口电路。
- 电源电路:STM32 通常支持多种电源供电,常见的供电电压为 3.3V。电源电路需要保证电压的稳定和纯净,一般会使用电源芯片进行电压转换,并通过滤波电容等元件去除电源噪声。
- 时钟电路:时钟是 STM32 运行的 “心脏”,为芯片内部的各个模块提供工作时钟。STM32 通常有多个时钟源,包括高速外部时钟(HSE)、低速外部时钟(LSE)、高速内部时钟(HSI)和低速内部时钟(LSI)。HSE 一般使用晶体振荡器,为系统提供高精度的时钟;HSI 则是芯片内部的 RC 振荡器,精度相对较低,但启动速度快,常用于对时钟精度要求不高的场景。
- 复位电路:复位电路用于将 STM32 的内部寄存器和外设恢复到初始状态,确保系统在异常情况下能够重新正常运行。常见的复位方式有上电复位、手动复位和软件复位。
- 调试接口电路:调试接口用于程序的下载和调试,常用的调试接口有 JTAG 和 SWD。SWD 接口由于占用引脚少、调试速度快,逐渐成为主流的调试接口。
2.2 开发板选择
对于初学者来说,选择一款合适的开发板至关重要。目前市面上比较受欢迎的 STM32 开发板有正点原子的 STM32 开发板系列、野火的 STM32 开发板系列以及 ST 官方的 Discovery 系列开发板等。
- 正点原子开发板:资料丰富,配套教程详细,适合初学者系统学习。其开发板上外设齐全,包括 LED 灯、按键、LCD 显示屏、SD 卡接口等,能够满足各种实验和项目需求。
- 野火开发板:同样具有完善的资料和教程,在电路设计和功能布局上也非常合理,而且野火社区活跃,开发者可以在社区中交流学习经验和解决遇到的问题。
- ST 官方 Discovery 系列开发板:官方开发板具有权威性,能够及时获取官方最新的资料和支持。该系列开发板集成了丰富的传感器和外设,方便开发者快速上手体验 STM32 的各种功能
三、开发环境搭建
3.1 软件工具
- 集成开发环境(IDE):常用的 IDE 有 Keil MDK 和 STM32CubeIDE。
- Keil MDK:是一款功能强大且使用广泛的嵌入式开发工具,支持 ARM Cortex-M 内核,提供了完善的代码编辑、编译、调试等功能。它拥有友好的用户界面和丰富的调试手段,能够帮助开发者快速定位和解决问题。
- STM32CubeIDE:是 ST 官方推出的集成开发环境,基于 Eclipse 框架,集成了 STM32CubeMX 配置工具。它能够通过图形化界面快速配置 STM32 的外设和时钟,自动生成初始化代码,大大提高了开发效率。
- STM32CubeMX:是一款图形化的配置工具,能够帮助开发者快速配置 STM32 的引脚、时钟、外设等参数,并自动生成初始化代码。使用 STM32CubeMX 可以避免手动编写大量复杂的初始化代码,降低开发难度,提高开发效率。
3.2 安装步骤
- Keil MDK 安装:
- 下载 Keil MDK 安装包,双击安装程序,按照安装向导提示进行安装,选择安装路径和相关组件。
- 安装完成后,需要安装 ARM 芯片支持包,以便支持 STM32 芯片的开发。在 Keil MDK 中,通过 “Pack Installer” 工具下载并安装所需的芯片支持包。
- STM32CubeIDE 安装:
- 从 ST 官方网站下载 STM32CubeIDE 安装包,运行安装程序,按照提示完成安装过程。
- 安装完成后,打开 STM32CubeIDE,它会自动下载并安装必要的组件和支持文件。
- STM32CubeMX 安装:
- 从 ST 官方网站下载 STM32CubeMX 安装包,安装过程较为简单,按照向导操作即可。
- 安装完成后,打开 STM32CubeMX,同样需要下载和安装所需的 STM32 芯片支持包。
3.3 调试工具
常用的调试工具包括 ST - Link、J - Link 等。
- ST - Link:是 ST 官方推出的调试下载工具,支持 SWD 和 JTAG 调试模式,与 STM32 芯片兼容性好,价格相对较低,是初学者常用的调试工具。
- J - Link:由 SEGGER 公司推出,具有高速、稳定的特点,支持多种 ARM 内核芯片的调试,功能强大,但价格相对较高。
将调试工具与开发板正确连接后,在 IDE 中进行相应的调试配置,即可进行程序的下载和调试。
四、STM32 编程基础
4.1 编程语言
STM32 开发常用的编程语言是 C 语言。C 语言具有高效、灵活、可移植性强等特点,能够直接操作硬件寄存器,充分发挥 STM32 的性能。在编写 STM32 程序时,需要熟悉 C 语言的基本语法,如变量定义、数据类型、控制语句(if - else、for、while 等)、函数定义和调用等。
4.2 固件库与 HAL 库
- 固件库:是 ST 官方早期推出的一套函数库,它对 STM32 芯片的寄存器操作进行了封装,开发者通过调用固件库函数来配置和使用 STM32 的外设。固件库函数功能强大,但学习成本相对较高,需要开发者对芯片的寄存器有一定的了解。
- HAL 库:即硬件抽象层库,是 ST 官方推出的新一代函数库。HAL 库在固件库的基础上,进一步提高了代码的可移植性和易用性,通过统一的接口函数来操作不同系列的 STM32 芯片。使用 HAL 库开发程序,能够减少代码的重复编写,提高开发效率,同时也更方便在不同系列的 STM32 芯片之间进行移植 。
4.3 第一个 STM32 程序:点亮 LED 灯
下面以使用 HAL 库在 STM32F103C8T6 开发板上点亮 LED 灯为例,介绍 STM32 程序的开发流程。
- 打开 STM32CubeMX:新建一个工程,选择对应的 STM32 芯片型号(如 STM32F103C8T6)。
- 配置引脚:找到连接 LED 灯的 GPIO 引脚(假设 LED 灯连接在 PA5 引脚),将其配置为输出模式。
- 配置时钟:根据开发板的晶振和需求,配置系统时钟,一般将 HSE 作为时钟源,并设置合适的分频和倍频系数,使系统时钟达到所需频率(如 72MHz)。
- 生成代码:完成配置后,点击 “Generate Code” 按钮,选择使用的 IDE(如 Keil MDK),生成初始化代码框架。
- 编写程序:在生成的 Keil MDK 工程中,找到主函数main.c,在while(1)循环之前添加初始化 LED 引脚的代码:
-
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 将PA5引脚输出低电平,点亮LED灯
- 编译下载:在 Keil MDK 中编译工程,确保没有错误和警告后,通过调试工具(如 ST - Link)将程序下载到开发板中,即可看到 LED 灯点亮。
五、STM32 外设应用
5.1 通用定时器(TIM)
通用定时器是 STM32 中非常重要的外设之一,它可以用于定时、计数、PWM 输出等功能。以定时功能为例,使用 STM32CubeMX 配置通用定时器的步骤如下:
- 在 STM32CubeMX 中打开工程,找到通用定时器(如 TIM2),将其使能。
- 配置定时器的时钟分频系数、自动重装载值等参数,以确定定时时间。例如,若系统时钟为 72MHz,设置分频系数为 72 - 1,自动重装载值为 9999,则定时时间为 (10000 * 1) / 72000000 = 0.139s 。
- 生成代码后,在主函数中开启定时器中断,并编写中断服务函数:
// 开启定时器中断HAL_TIM_Base_Start_IT(&htim2); // 定时器中断服务函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim == &htim2) { // 在这里编写定时时间到达后的处理代码,如翻转LED灯状态 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); }}
5.2 串行通信接口(USART)
USART 是 STM32 常用的串行通信接口,用于实现与其他设备的数据通信,如与电脑进行串口通信。使用 STM32CubeMX 配置 USART 的步骤如下:
- 使能 USART 外设(如 USART1),配置波特率、数据位、停止位、校验位等参数。例如,设置波特率为 115200bps,数据位为 8 位,停止位为 1 位,无校验位。
- 生成代码后,在主函数中发送和接收数据:
// 发送数据char data[] = \"Hello, STM32!\\r\\n\";HAL_UART_Transmit(&huart1, (uint8_t *)data, sizeof(data), 1000); // 接收数据uint8_t receive_data;HAL_UART_Receive(&huart1, &receive_data, 1, 1000);
5.3 模拟数字转换器(ADC)
ADC 用于将模拟信号转换为数字信号,在采集传感器数据等应用中非常重要。使用 STM32CubeMX 配置 ADC 的步骤如下:
- 使能 ADC 外设(如 ADC1),选择要转换的通道(如通道 0),配置采样时间等参数。
- 生成代码后,在主函数中启动 ADC 转换并读取转换结果:
// 启动ADC转换HAL_ADC_Start(&hadc1); // 读取转换结果uint16_t adc_value;HAL_ADC_PollForConversion(&hadc1, 1000);adc_value = HAL_ADC_GetValue(&hadc1);
六、实战项目:简易温湿度监测系统
6.1 项目需求
设计一个基于 STM32 的简易温湿度监测系统,能够实时采集环境温度和湿度数据,并通过串口将数据发送到电脑显示。
6.2 硬件设计
- 传感器选择:选用 DHT11 温湿度传感器,它采用单总线通信协议,具有价格低廉、使用方便等特点。
- 电路连接:将 DHT11 的数据引脚连接到 STM32 的一个 GPIO 引脚上(如 PB12),同时为 DHT11 提供 3.3V 电源和接地。
6.3 软件设计
- 使用 STM32CubeMX 配置系统时钟、USART(用于串口通信)和 GPIO 引脚(连接 DHT11 的引脚)。
- 编写 DHT11 驱动程序,实现数据的读取。DHT11 的数据读取需要严格按照时序进行,以下是一个简单的 DHT11 数据读取函数示例:
void DHT11_Read_Data(uint8_t *temp, uint8_t *humi){ // 主机拉低18ms以上,发起一次通讯 DHT11_DATA_OUT_LOW; HAL_Delay(20); DHT11_DATA_OUT_HIGH; HAL_Delay(30); // 等待DHT11响应 while(DHT11_DATA_IN); while(!DHT11_DATA_IN); while(DHT11_DATA_IN); // 读取数据 uint8_t data[5] = {0}; for(uint8_t i = 0; i < 5; i++) { for(uint8_t j = 0; j < 8; j++) { while(!DHT11_DATA_IN); HAL_DelayMicroseconds(30); if(DHT11_DATA_IN) { data[i] |= (1 << (7 - j)); } while(DHT11_DATA_IN); } } // 校验数据 if((data[0] + data[1] + data[2] + data[3]) == data[4]) { *humi = data[0]; *temp = data[2]; }}
- 在主函数中调用 DHT11 读取函数,获取温湿度数据,并通过 USART 将数据发送到电脑:
int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); uint8_t temperature, humidity; char send_data[50]; while (1) { DHT11_Read_Data(&temperature, &humidity); sprintf(send_data, \"Temperature: %d℃, Humidity: %d%%\\r\\n\", temperature, humidity); HAL_UART_Transmit(&huart1, (uint8_t *)send_data, strlen(send_data), 1000); HAL_Delay(2000); }}
七、总结与展望
通过本文的学习,相信大家已经对 STM32 有了一个全面的了解,掌握了从硬件基础、开发环境搭建到编程开发和外设应用的基本技能,并完成了一个简单的实战项目。但这只是 STM32 开发的入门阶段,STM32 还有更多强大的功能和复杂的应用等待我们去探索。在未来的学习和实践中,大家可以进一步深入研究 STM32 的高级功能,如 RTOS(实时操作系统)移植、图形界面开发等,不断提升自己的嵌入式开发能力。
希望本文能够对大家学习 STM32 有所帮助,如果在学习过程中遇到任何问题,欢迎在评论区留言交流,也可以加入相关的技术交流群,与更多的开发者共同学习进步。