【STM32单片机入门秘籍】:从小白到实战高手,30天掌握单片机精髓
发布时间: 2024-07-03 16:51:32 阅读量: 76 订阅数: 58
STM32单片机学习入门基础教程PPT课件(共49个).zip
5星 · 资源好评率100%
![【STM32单片机入门秘籍】:从小白到实战高手,30天掌握单片机精髓](https://img-blog.csdnimg.cn/5903670652a243edb66b0e8e6199b383.jpg)
# 1. STM32单片机简介
STM32单片机是意法半导体(STMicroelectronics)公司推出的基于ARM Cortex-M内核的32位微控制器系列。它以其高性能、低功耗和丰富的片上外设资源而著称,广泛应用于工业控制、物联网、医疗设备和消费电子等领域。
STM32单片机采用哈佛架构,具有独立的指令和数据存储器,提高了指令执行效率。它还支持多种总线接口,如AHB、APB和APB2,实现了高效的外设访问。此外,STM32单片机还集成了丰富的片上外设资源,包括GPIO接口、定时器、串口、ADC和DAC等,为开发者提供了灵活的系统设计方案。
# 2. STM32单片机硬件架构
STM32单片机基于ARM Cortex-M内核,采用哈佛架构,具有高效的处理能力和丰富的片上外设资源。其硬件架构主要包括处理器架构和外设资源两部分。
### 2.1 处理器架构
#### 2.1.1 Cortex-M内核
STM32单片机采用ARM Cortex-M系列内核,该内核专为嵌入式应用而设计,具有低功耗、高性能和易于使用的特点。Cortex-M内核包括多个寄存器组、指令集和中断控制器,为程序执行提供了高效的平台。
**寄存器组:**Cortex-M内核具有多个寄存器组,包括通用寄存器、特殊寄存器和浮点寄存器。通用寄存器用于存储数据和地址,特殊寄存器用于控制程序执行和外设访问,浮点寄存器用于浮点运算。
**指令集:**Cortex-M内核支持Thumb-2指令集,该指令集经过优化,具有较小的指令大小和较高的执行效率。Thumb-2指令集包括一系列算术、逻辑、数据传输和控制流指令,可满足嵌入式应用的各种需求。
**中断控制器:**Cortex-M内核内置中断控制器,用于管理来自外设和软件的各种中断请求。中断控制器可以优先级化中断请求,并根据优先级执行中断服务程序。
#### 2.1.2 外设总线
STM32单片机采用AMBA(高级微控制器总线架构)外设总线,该总线架构提供了高效的数据传输和外设访问。AMBA总线架构包括以下总线:
**AHB(高级高速总线):**AHB总线是高速、高带宽的总线,用于连接高性能外设,如DMA控制器、存储器控制器和高速外设。
**APB(高级外设总线):**APB总线是低速、低功耗的总线,用于连接低速外设,如GPIO接口、定时器和串口通信外设。
**APB2总线:**APB2总线是APB总线的增强版本,具有更高的时钟频率和数据传输速率,用于连接中速外设,如ADC和DAC。
### 2.2 外设资源
STM32单片机集成了丰富的片上外设资源,这些外设资源为嵌入式应用提供了广泛的功能和灵活性。主要外设资源包括:
#### 2.2.1 GPIO接口
GPIO(通用输入/输出)接口是STM32单片机最基本的输入/输出外设,用于连接外部设备和传感器。GPIO接口可以配置为输入、输出或中断模式,并支持多种功能,如数字输入/输出、模拟输入和中断触发。
**GPIO接口配置:**GPIO接口的配置主要通过寄存器操作实现。寄存器包括:
- GPIOx_MODER:模式寄存器,用于配置GPIO接口的模式(输入、输出或模拟)。
- GPIOx_OTYPER:输出类型寄存器,用于配置GPIO接口的输出类型(推挽输出或开漏输出)。
- GPIOx_PUPDR:上拉/下拉寄存器,用于配置GPIO接口的上拉/下拉电阻。
**GPIO接口中断:**GPIO接口支持中断功能,可以通过寄存器配置中断触发条件(上升沿、下降沿或电平变化)。中断触发后,会产生中断请求,并执行相应的中断服务程序。
#### 2.2.2 定时器
定时器是STM32单片机中重要的外设,用于产生精确的时间延迟和定时中断。STM32单片机集成了多个定时器,每个定时器具有不同的功能和特性。
**定时器配置:**定时器的配置主要通过寄存器操作实现。寄存器包括:
- TIMx_CR1:控制寄存器1,用于配置定时器的时钟源、计数模式和预分频器。
- TIMx_PSC:预分频器寄存器,用于设置定时器的预分频系数。
- TIMx_ARR:自动重装载寄存器,用于设置定时器的重装载值。
**定时器中断:**定时器支持中断功能,可以通过寄存器配置中断触发条件(更新中断、溢出中断或捕获中断)。中断触发后,会产生中断请求,并执行相应的中断服务程序。
#### 2.2.3 串口通信
串口通信外设是STM32单片机中重要的通信外设,用于与外部设备进行串行数据传输。STM32单片机集成了多个串口通信外设,每个外设具有不同的功能和特性。
**串口通信配置:**串口通信外设的配置主要通过寄存器操作实现。寄存器包括:
- USARTx_CR1:控制寄存器1,用于配置串口通信外设的时钟源、数据格式和波特率。
- USARTx_BRR:波特率寄存器,用于设置串口通信外设的波特率。
- USARTx_DR:数据寄存器,用于发送和接收数据。
**串口通信中断:**串口通信外设支持中断功能,可以通过寄存器配置中断触发条件(接收中断、发送中断或错误中断)。中断触发后,会产生中断请求,并执行相应的中断服务程序。
# 3.1 开发工具链
STM32单片机软件开发需要使用专门的开发工具链,它包含编译器、汇编器、链接器等工具,用于将源代码转换为可执行的固件。常用的开发工具链有:
#### 3.1.1 Keil MDK
Keil MDK(Microcontroller Development Kit)是ARM公司推出的集成开发环境(IDE),专为ARM Cortex-M内核的单片机开发而设计。它包含了编译器、调试器、仿真器等多种工具,提供了友好的用户界面和丰富的功能。
#### 3.1.2 IAR Embedded Workbench
IAR Embedded Workbench是IAR Systems公司推出的另一款集成开发环境,同样适用于ARM Cortex-M内核的单片机开发。它提供了强大的编译器、调试器和代码分析工具,支持多种编程语言和实时操作系统。
### 3.2 固件架构
STM32单片机的固件架构通常包括以下几个部分:
#### 3.2.1 启动代码
启动代码是固件执行的第一个部分,负责初始化硬件、设置堆栈和调用main函数。它通常由编译器或开发工具链自动生成。
#### 3.2.2 中断处理
中断处理程序负责处理中断请求,并执行相应的服务例程。中断请求可以由硬件外设或软件事件触发。
### 代码块示例:中断处理程序
```c
void SysTick_Handler(void)
{
// Clear the SysTick interrupt flag
SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
// Toggle the LED
GPIOA->ODR ^= GPIO_ODR_ODR_12;
}
```
**逻辑分析:**
* `SysTick_Handler`函数是SysTick中断处理程序,当SysTick中断发生时被调用。
* `SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk`清除SysTick中断标志位,表示中断已处理。
* `GPIOA->ODR ^= GPIO_ODR_ODR_12`对GPIOA的第12位进行异或操作,从而切换LED的状态。
### 表格示例:中断向量表
| 中断源 | 中断向量地址 | 中断服务例程 |
|---|---|---|
| NMI | 0x00000000 | NMI_Handler |
| HardFault | 0x00000004 | HardFault_Handler |
| MemManage | 0x00000008 | MemManage_Handler |
| BusFault | 0x0000000C | BusFault_Handler |
| UsageFault | 0x00000010 | UsageFault_Handler |
| SVC | 0x00000014 | SVC_Handler |
| Debug | 0x00000018 | DebugMon_Handler |
| PendSV | 0x0000001C | PendSV_Handler |
| SysTick | 0x00000020 | SysTick_Handler |
**说明:**
* 中断向量表是一个存储中断服务例程地址的数组。
* 当中断发生时,处理器会根据中断源查找中断向量表中的相应地址,并跳转到该地址执行中断服务例程。
# 4. STM32单片机编程基础
### 4.1 C语言基础
#### 4.1.1 数据类型
STM32单片机编程中常用的数据类型包括:
- 整数类型:`int`、`short`、`long`、`long long`
- 浮点数类型:`float`、`double`
- 字符类型:`char`、`wchar_t`
- 指针类型:`int *`、`char *`
- 数组类型:`int array[10]`
- 结构体类型:`struct my_struct { int a; char b; }`
#### 4.1.2 运算符
C语言中常用的运算符包括:
- 算术运算符:`+`、`-`、`*`、`/`、`%`
- 关系运算符:`==`、`!=`、`<`、`>`、`<=`、`>=`
- 逻辑运算符:`&&`、`||`、`!`
- 位运算符:`<<`、`>>`、`|`、`&`、`^`
- 赋值运算符:`=`、`+=`、`-=`、`*=`、`/=`
#### 4.1.3 控制语句
C语言中常用的控制语句包括:
- `if-else`语句:根据条件执行不同的代码块
- `switch-case`语句:根据多个条件执行不同的代码块
- `for`循环:重复执行代码块一定次数
- `while`循环:重复执行代码块直到条件为假
- `do-while`循环:先执行代码块,再检查条件
### 4.2 单片机编程基础
#### 4.2.1 寄存器操作
STM32单片机通过寄存器与外设交互。寄存器是存储数据的特殊内存地址。
```c
// 设置GPIOA第5位为输出模式
GPIOA->MODER &= ~(3 << (5 * 2));
GPIOA->MODER |= (1 << (5 * 2));
```
**参数说明:**
- `GPIOA`:GPIOA寄存器基地址
- `MODER`:模式寄存器
- `3 << (5 * 2)`:清除第5位模式位
- `1 << (5 * 2)`:设置第5位为输出模式
#### 4.2.2 中断处理
中断是一种硬件机制,当特定事件发生时,CPU会暂停当前任务并执行中断服务程序(ISR)。
```c
// 配置TIM2中断
void TIM2_IRQHandler(void) {
// 清除中断标志位
TIM2->SR &= ~TIM_SR_UIF;
// 执行中断处理代码
...
}
```
**代码逻辑:**
1. 清除中断标志位,表明中断已处理。
2. 执行中断处理代码,例如更新变量、控制外设等。
# 5. STM32单片机应用开发
### 5.1 LED控制
#### 5.1.1 GPIO配置
LED控制是STM32单片机最基本的应用之一,需要使用GPIO(通用输入/输出)接口来实现。GPIO接口可以配置为输入或输出模式,并通过寄存器来控制其状态。
在STM32单片机中,GPIO接口的配置可以通过以下步骤进行:
1. **使能GPIO时钟:**在使用GPIO接口之前,需要先使能其时钟。对于STM32F103系列单片机,GPIO时钟寄存器位于RCC_APB2ENR寄存器中。
2. **设置GPIO模式:**GPIO接口的模式可以通过GPIOx_MODER寄存器来设置。其中,MODER寄存器的第n位(n为0~15)对应于第n个GPIO引脚的模式。
3. **设置GPIO输出类型:**对于输出模式的GPIO引脚,还需要设置其输出类型。输出类型可以通过GPIOx_OTYPER寄存器来设置。
4. **设置GPIO拉/下拉电阻:**GPIO引脚可以配置为上拉或下拉电阻。上拉/下拉电阻可以通过GPIOx_PUPDR寄存器来设置。
#### 5.1.2 软件控制
配置好GPIO接口后,就可以通过软件来控制LED的状态。在STM32单片机中,GPIO引脚的状态可以通过GPIOx_ODR寄存器来控制。其中,ODR寄存器的第n位(n为0~15)对应于第n个GPIO引脚的状态。
```c
// 设置GPIO引脚为输出模式
GPIOx_MODER |= (1 << (pin * 2));
// 设置GPIO引脚为高电平
GPIOx_ODR |= (1 << pin);
// 设置GPIO引脚为低电平
GPIOx_ODR &= ~(1 << pin);
```
### 5.2 串口通信
#### 5.2.1 UART配置
串口通信是STM32单片机常用的通信方式之一,需要使用UART(通用异步收发器)接口来实现。UART接口可以配置为不同的波特率、数据位、停止位和校验位。
在STM32单片机中,UART接口的配置可以通过以下步骤进行:
1. **使能UART时钟:**在使用UART接口之前,需要先使能其时钟。对于STM32F103系列单片机,UART时钟寄存器位于RCC_APB1ENR寄存器中。
2. **配置UART波特率:**UART波特率可以通过UARTx_BRR寄存器来配置。其中,BRR寄存器的第n位(n为0~15)对应于第n个UART接口的波特率。
3. **配置UART数据位:**UART数据位可以通过UARTx_CR1寄存器来配置。其中,CR1寄存器的第n位(n为0~15)对应于第n个UART接口的数据位。
4. **配置UART停止位:**UART停止位可以通过UARTx_CR2寄存器来配置。其中,CR2寄存器的第n位(n为0~15)对应于第n个UART接口的停止位。
5. **配置UART校验位:**UART校验位可以通过UARTx_CR1寄存器来配置。其中,CR1寄存器的第n位(n为0~15)对应于第n个UART接口的校验位。
#### 5.2.2 数据传输
配置好UART接口后,就可以通过软件来发送和接收数据。在STM32单片机中,UART接口的数据传输可以通过UARTx_DR寄存器来进行。其中,DR寄存器的第n位(n为0~15)对应于第n个UART接口的数据传输。
```c
// 发送数据
UARTx_DR = data;
// 接收数据
data = UARTx_DR;
```
# 6. STM32单片机高级应用
### 6.1 定时器应用
#### 6.1.1 定时器配置
STM32单片机内置多个定时器,可用于产生定时中断、生成PWM信号、捕获外部事件等。定时器配置主要包括时钟源选择、预分频器设置、计数模式选择和中断使能等。
```c
// 定时器1配置为向上计数模式,时钟源为APB2时钟,预分频为8
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 1000; // 计数上限为1000
TIM_TimeBaseStructure.TIM_Prescaler = 8; // 预分频为8
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
```
#### 6.1.2 脉宽调制(PWM)
PWM(Pulse Width Modulation)是一种调制技术,通过改变脉冲宽度来控制输出信号的占空比,从而实现对模拟信号的控制。STM32单片机内置PWM功能,可通过配置定时器和输出比较寄存器实现。
```c
// 定时器1通道1配置为PWM输出,占空比为50%
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_Pulse = 500; // 脉冲宽度为500
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出极性为高电平
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
```
### 6.2 ADC应用
#### 6.2.1 ADC配置
ADC(Analog-to-Digital Converter)是一种将模拟信号转换为数字信号的器件。STM32单片机内置多通道ADC,可用于测量外部模拟信号。ADC配置主要包括时钟源选择、采样时间设置、通道选择和中断使能等。
```c
// ADC1配置为12位分辨率,时钟源为APB2时钟,采样时间为239.5周期
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; // 12位分辨率
ADC_InitStructure.ADC_ClockPrescaler = ADC_ClockPrescaler_PCLK2_Div6; // 时钟预分频为6
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单次转换模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 非连续转换模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1; // 转换通道数为1
ADC_Init(ADC1, &ADC_InitStructure);
```
#### 6.2.2 数据采集
ADC数据采集过程包括通道选择、启动转换、等待转换完成和读取转换结果等步骤。
```c
// 选择ADC1通道1
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
// 启动ADC转换
ADC_SoftwareStartConv(ADC1);
// 等待ADC转换完成
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
// 读取ADC转换结果
uint16_t adc_value = ADC_GetConversionValue(ADC1);
```
0
0