【STM32单片机入门秘籍】:零基础到精通的实战指南
发布时间: 2024-07-04 00:51:15 阅读量: 58 订阅数: 57
stm32从入门到精通
![【STM32单片机入门秘籍】:零基础到精通的实战指南](https://img-blog.csdnimg.cn/5903670652a243edb66b0e8e6199b383.jpg)
# 1. STM32单片机简介**
STM32单片机是意法半导体(STMicroelectronics)公司生产的基于ARM Cortex-M内核的32位微控制器。它以其高性能、低功耗和丰富的外设而闻名,广泛应用于嵌入式系统、工业控制、物联网等领域。
STM32单片机具有多核架构,包括Cortex-M0、M3、M4和M7内核,提供不同的性能和功耗选择。其外设丰富,包括GPIO、定时器、串口、ADC、DAC等,可以满足各种应用需求。
STM32单片机采用先进的工艺技术制造,具有低功耗、高可靠性和高抗干扰能力。其完善的开发生态系统,包括开发工具、调试器和仿真器,为开发人员提供了便捷的开发环境。
# 2. STM32单片机基础编程
### 2.1 C语言基础
#### 2.1.1 数据类型和变量
C语言中提供了丰富的变量类型,包括整数类型(如int、short、long)、浮点类型(如float、double)和字符类型(如char)。每个变量类型都有其特定的取值范围和存储空间大小。
例如:
```c
int num = 10; // 32位有符号整数,取值范围为[-2147483648, 2147483647]
float pi = 3.14; // 32位浮点数,取值范围为[-3.402823466e+38, 3.402823466e+38]
char letter = 'A'; // 8位字符,取值范围为[0, 255]
```
变量通过关键字`var`声明,并指定其类型和名称。
#### 2.1.2 运算符和表达式
C语言提供了丰富的运算符,包括算术运算符(如+、-、*、/)、关系运算符(如==、!=、<、>)、逻辑运算符(如&&、||、!)和位运算符(如&、|、^)。
表达式是运算符和操作数的组合,用于计算结果。例如:
```c
int sum = 10 + 20; // 算术表达式,计算10和20的和
int is_equal = (num == 10); // 关系表达式,比较num是否等于10
int is_true = (num > 0 && letter == 'A'); // 逻辑表达式,判断num是否大于0且letter是否等于'A'
```
### 2.2 STM32单片机架构
#### 2.2.1 内核和外设
STM32单片机采用ARM Cortex-M系列内核,具有高性能和低功耗的特点。外设包括GPIO、定时器、串口、ADC、DAC等,提供丰富的功能扩展。
#### 2.2.2 时钟和复位
STM32单片机有多个时钟源,包括内部时钟(如HSI、LSI)和外部时钟(如HSE、LSE)。复位电路用于在单片机启动或异常时将系统复位到初始状态。
### 2.3 STM32单片机编程环境
#### 2.3.1 开发工具和编译器
STM32单片机的开发工具包括IDE(如Keil uVision、IAR Embedded Workbench)和编译器(如ARM Compiler、GCC)。
#### 2.3.2 调试和仿真
调试和仿真工具用于在开发过程中查找和修复错误。常用的调试工具包括JTAG、SWD和串口调试。仿真工具则可以模拟单片机的运行过程,方便调试和优化代码。
**流程图:STM32单片机编程环境**
```mermaid
graph LR
subgraph 开发工具
Keil uVision --> ARM Compiler
IAR Embedded Workbench --> GCC
end
subgraph 调试和仿真
JTAG --> 单片机
SWD --> 单片机
串口调试 --> 单片机
仿真工具 --> 单片机
end
```
**表格:STM32单片机编程环境对比**
| 特性 | Keil uVision | IAR Embedded Workbench |
|---|---|---|
| IDE | 收费 | 收费 |
| 编译器 | ARM Compiler | GCC |
| 调试 | 支持JTAG、SWD、串口 | 支持JTAG、SWD、串口 |
| 仿真 | 支持 | 支持 |
# 3.1 GPIO编程
#### 3.1.1 GPIO配置和控制
**GPIO简介**
GPIO(通用输入输出端口)是STM32单片机中重要的外设,它允许与外部设备进行交互。GPIO引脚可以配置为输入、输出或模拟输入/输出。
**GPIO配置**
```c
// 定义GPIO引脚
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;
// 使能GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
// 设置GPIO引脚模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOx, &GPIO_InitStructure);
```
**参数说明:**
* `GPIOx`:GPIO端口,如GPIOA、GPIOB等。
* `GPIO_Pin`:GPIO引脚,如GPIO_Pin_0、GPIO_Pin_1等。
* `RCC_APB2Periph_GPIOx`:GPIO时钟使能宏,如RCC_APB2Periph_GPIOA、RCC_APB2Periph_GPIOB等。
* `GPIO_Mode_Out_PP`:输出推挽模式。
* `GPIO_Speed_50MHz`:引脚速度,50MHz。
**GPIO控制**
```c
// 设置GPIO引脚输出高电平
GPIO_SetBits(GPIOx, GPIO_Pin);
// 设置GPIO引脚输出低电平
GPIO_ResetBits(GPIOx, GPIO_Pin);
// 读取GPIO引脚电平
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
```
**参数说明:**
* `GPIO_SetBits`:设置GPIO引脚高电平。
* `GPIO_ResetBits`:设置GPIO引脚低电平。
* `GPIO_ReadInputDataBit`:读取GPIO引脚电平。
#### 3.1.2 中断和事件
**GPIO中断**
GPIO中断允许在GPIO引脚状态发生变化时触发中断服务函数。
```c
// 配置GPIO中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTIx_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能GPIO中断
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Linex;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
```
**参数说明:**
* `EXTIx_IRQn`:GPIO中断向量号,如EXTI0_IRQn、EXTI1_IRQn等。
* `EXTI_Linex`:GPIO引脚中断线,如EXTI_Line0、EXTI_Line1等。
* `EXTI_Mode_Interrupt`:中断模式。
* `EXTI_Trigger_Rising`:上升沿触发。
**GPIO事件**
GPIO事件允许在GPIO引脚状态发生变化时触发事件。
```c
// 配置GPIO事件
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Linex;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
```
**参数说明:**
* `EXTI_Mode_Event`:事件模式。
# 4. STM32单片机高级应用**
**4.1 中断系统**
**4.1.1 中断向量表和优先级**
STM32单片机的中断向量表是一个包含所有中断服务函数地址的数组。当发生中断时,处理器会根据中断号从中断向量表中读取中断服务函数的地址,然后跳转到该地址执行中断服务函数。
中断优先级用于确定当多个中断同时发生时,哪个中断会被优先处理。STM32单片机支持多达32个中断优先级,其中0级优先级最高,31级优先级最低。
**4.1.2 中断服务函数**
中断服务函数(ISR)是响应中断而执行的代码段。每个中断都有一个对应的ISR,ISR负责处理中断事件,例如更新变量、清除中断标志位或执行其他必要的操作。
**4.2 DMA编程**
**4.2.1 DMA配置和使用**
DMA(直接内存访问)是一种允许外设直接与内存进行数据传输的机制,无需CPU干预。这可以大大提高数据传输效率,特别是在需要传输大量数据时。
要使用DMA,需要配置DMA通道,包括源地址、目标地址、传输长度和传输模式。然后,启动DMA传输,DMA控制器将自动处理数据传输。
**4.2.2 数据传输和中断**
DMA传输完成后,DMA控制器会触发一个中断。在中断服务函数中,可以检查DMA传输状态,并执行必要的后续操作,例如更新指针或释放资源。
**4.3 实时操作系统**
**4.3.1 RTOS简介和选择**
实时操作系统(RTOS)是一种专门设计用于嵌入式系统的操作系统。RTOS提供了任务调度、同步和通信等功能,使开发人员能够创建复杂的多任务应用程序。
有多种不同的RTOS可供选择,每个RTOS都有其自己的优点和缺点。在选择RTOS时,需要考虑应用程序的特定需求,例如任务数量、实时性要求和资源约束。
**4.3.2 任务调度和同步**
任务调度是RTOS的核心功能之一。RTOS负责调度任务,确保每个任务都能获得执行时间。RTOS还提供同步机制,例如信号量和互斥量,以防止任务冲突和数据竞争。
**代码块:**
```c
// 中断服务函数
void SysTick_Handler(void)
{
// 更新系统时钟
SystemCoreClockUpdate();
// 清除中断标志位
SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
}
```
**逻辑分析:**
此代码块定义了SysTick中断服务函数,当SysTick中断发生时,此函数将被调用。函数首先更新系统时钟,然后清除中断标志位,以表示中断已处理。
**表格:STM32单片机中断优先级**
| 优先级 | 中断源 |
|---|---|
| 0 | NMI |
| 1 | 硬故障 |
| 2 | 内存管理 |
| 3 | 总线故障 |
| 4 | 使用故障 |
| 5 | SVCall |
| 6 | PendSV |
| 7 | SysTick |
| ... | ... |
**Mermaid格式流程图:**
```mermaid
sequenceDiagram
participant User
participant STM32
User->STM32: Send interrupt request
STM32->STM32: Check interrupt priority
STM32->STM32: Execute interrupt service function
STM32->User: Interrupt handling completed
```
# 5.1 LED闪烁
### 5.1.1 硬件连接和代码编写
**硬件连接:**
* 将 LED 的阳极连接到 STM32 单片机的 GPIO 引脚(例如,PA0)。
* 将 LED 的阴极连接到地线(GND)。
**代码编写:**
```c
#include "stm32f10x.h"
int main() {
// 初始化 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置 GPIOA0 为输出模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1) {
// 打开 LED
GPIO_SetBits(GPIOA, GPIO_Pin_0);
// 延时 500ms
for (int i = 0; i < 500000; i++) {}
// 关闭 LED
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
// 延时 500ms
for (int i = 0; i < 500000; i++) {}
}
}
```
### 5.1.2 调试和验证
* 将代码下载到 STM32 单片机。
* 观察 LED 是否按照预期闪烁(每秒闪烁一次)。
* 如果 LED 不闪烁,请检查硬件连接和代码配置。
0
0