STM32单片机外设接口实战:串口、I2C、SPI、ADC,解锁无限可能
发布时间: 2024-07-02 14:05:16 阅读量: 5 订阅数: 11 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![STM32单片机外设接口实战:串口、I2C、SPI、ADC,解锁无限可能](https://img-blog.csdnimg.cn/direct/cecb91ee4e8244b98c2cc95b6f1a686b.png)
# 1. STM32单片机外设接口概述**
STM32单片机外设接口是连接单片机与外部设备的桥梁,在嵌入式系统设计中扮演着至关重要的角色。本节将概述STM32单片机常用的外设接口,包括串口、I2C、SPI和ADC,并介绍它们的特性和应用场景。
**1.1 串口接口**
串口接口是一种异步通信接口,用于单向或双向传输数据。它具有简单易用、成本低廉等优点,广泛应用于调试、数据传输和控制等场景。
**1.2 I2C接口**
I2C接口是一种串行通信接口,用于连接多个设备。它采用主从模式,支持多主设备同时连接,具有低功耗、低成本和高可靠性等特点,常用于连接传感器、显示器和EEPROM等设备。
# 2. 串口接口
### 2.1 串口协议和通信原理
#### 2.1.1 串口通信模式和波特率
串口通信模式是指数据传输的方式,常见的有两种模式:
- **单工通信:**数据只能单向传输,即只能发送或接收。
- **半双工通信:**数据可以双向传输,但不能同时发送和接收。
- **全双工通信:**数据可以同时双向传输。
波特率是指每秒传输的比特数,单位为波特(bps)。常见的波特率有 9600、115200、921600 等。波特率需要发送方和接收方协商一致,否则无法正常通信。
#### 2.1.2 数据帧格式和校验方式
串口数据帧通常由以下部分组成:
- **起始位:**一个低电平比特,表示数据帧的开始。
- **数据位:**实际传输的数据,通常为 5、6、7 或 8 位。
- **校验位:**用于检测数据传输过程中是否发生错误,常见的有奇校验和偶校验。
- **停止位:**一个或多个高电平比特,表示数据帧的结束。
### 2.2 STM32 串口硬件配置
#### 2.2.1 GPIO 引脚复用和时钟配置
STM32 单片机上的串口引脚通常复用在 GPIO 引脚上。需要对这些引脚进行复用配置,将其设置为串口功能。同时,还需要配置串口时钟。
```c
// GPIO 引脚复用
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能 GPIOA 时钟
GPIOA->CRH |= GPIO_CRH_MODE8_0 | GPIO_CRH_MODE8_1; // PA9 和 PA10 设置为复用功能
GPIOA->CRH |= GPIO_CRH_CNF8_0 | GPIO_CRH_CNF8_1; // PA9 和 PA10 设置为复用推挽输出
// 串口时钟配置
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // 使能 USART1 时钟
```
#### 2.2.2 串口寄存器配置
串口寄存器用于配置串口参数,如波特率、数据位、校验位和停止位等。
```c
// 波特率配置
USART1->BRR = (uint16_t)(SystemCoreClock / 9600); // 设置波特率为 9600
// 数据位配置
USART1->CR1 |= USART_CR1_M; // 设置数据位为 8 位
// 校验位配置
USART1->CR1 |= USART_CR1_PCE; // 使能奇校验
// 停止位配置
USART1->CR2 |= USART_CR2_STOP_1; // 设置停止位为 1 位
```
### 2.3 串口通信编程
#### 2.3.1 中断方式通信
中断方式通信是指在串口接收或发送数据时触发中断,然后在中断服务程序中处理数据。
```c
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_RXNE) { // 接收中断
uint8_t data = USART1->DR; // 读取接收到的数据
// 处理数据
}
if (USART1->SR & USART_SR_TXE) { // 发送中断
USART1->DR = data; // 发送数据
// 数据发送完毕
}
}
```
#### 2.3.2 轮询方式通信
轮询方式通信是指在主程序中不断轮询串口状态寄存器,检查是否有数据接收或发送完毕。
```c
while (1) {
if (USART1->SR & USART_SR_RXNE) { // 接收中断
uint8_t data = USART1->DR; // 读取接收到的数据
// 处理数据
}
if (USART1->SR & USART_SR_TXE) { // 发送中断
USART1->DR = data; // 发送数据
// 数据发送完毕
}
}
```
# 3. I2C接口
### 3.1 I2C协议和通信原理
#### 3.1.1 I2C总线拓扑和寻址方式
I2C(Inter-Integrated Circuit)总线是一种串行通信协议,用于在集成电路(IC)之间进行数据传输。它采用多主从模式,允许多个主设备和多个从设备连接到同一总线上。
I2C总线采用两线制拓扑结构,包括一条数据线(SDA)和一条时钟线(SCL)。所有连接到总线上的设备共享这两条线。
每个从设备都有一个唯一的7位或10位地址,用于在总线上寻址。主设备通过发送一个包含从设备地址的起始位来启动通信。从设备收到其地址后,将发送一个应答位,表示它已准备好接收数据。
#### 3.1.2 数据传输和时序控制
I2C数据传输以字节为单位进行。主设备发送一个字节,然后从设备发送一个应答位。如果从设备没有收到正确的应答位,则主设备将重新发送该字节。
I2C总线上的时序由SCL线上的时钟信号控制。主设备生成时钟信号,从设备根据时钟信号接收和发送数据。
### 3.2 STM32 I2C硬件配置
#### 3.2.1 GPIO引脚复用和时钟配置
在STM32单片机上,I2C接口通常使用PB6和PB7引脚作为SDA和SCL线。需要对这些引脚进行复用配置,将其设置为I2C功能。
```c
// GPIO引脚复用配置
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 使能GPIOB时钟
GPIOB->CRH &= ~(GPIO_CRH_MODE6 | GPIO_CRH_MODE7); // 清除PB6和PB7模式位
GPIOB->CRH |= (GPIO_CRH_MODE6_1 | GPIO_CRH_MODE7_1); // 设置PB6和PB7为复用推挽输出
```
还需要为I2C接口配置时钟。STM32单片机通常使用APB1时钟作为I2C时钟源。
```c
// 时钟配置
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // 使能I2C1时钟
```
#### 3.2.2 I2C寄存器配置
STM32单片机上的I2C接口通过I2C寄存器进行配置。主要寄存器包括:
- I2C_CR1:控制寄存器,用于配置I2C模式、时钟频率和中断使能。
- I2C_CR2:配置寄存器,用于配置从机地址和中断优先级。
- I2C_OAR1:从机地址寄存器,用于存储从机地址。
- I2C_DR:数据寄存器,用于发送和接收数据。
- I2C_SR1:状态寄存器,用于指示I2C总线状态和中断标志。
- I2C_SR2:状态寄存器,用于指示I2C总线状态和中断标志。
### 3.3 I2C通信编程
#### 3.3.1 主机模式通信
在主机模式下,STM32单片机作为I2C总线的主设备,负责启动通信并控制数据传输。
```c
// 主机模式发送数据
void I2C_SendData(uint8_t slaveAddr, uint8_t* data, uint8_t len) {
// 发送起始位
I2C1->CR1 |= I2C_CR1_START;
// 等待起始位发送完成
while ((I2C1->SR1 & I2C_SR1_SB) == 0);
// 发送从机地址和写标志
I2C1->DR = (slaveAddr << 1) | 0;
// 等待从机地址发送完成
while ((I2C1->SR1 & I2C_SR1_ADDR) == 0);
// 发送数据
for (uint8_t i = 0; i < len; i++) {
I2C1->DR = data[i];
// 等待数据发送完成
while ((I2C1->SR1 & I2C_SR1_TXE) == 0);
}
// 发送停止位
I2C1->CR1 |= I2C_CR1_STOP;
}
```
#### 3.3.2 从机模式通信
在从机模式下,STM32单片机作为I2C总线上的从设备,负责接收数据并响应主设备的请求。
```c
// 从机模式接收数据
void I2C_ReceiveData(uint8_t* data, uint8_t len) {
// 等待主设备发送地址
while ((I2C1->SR1 & I2C_SR1_ADDR) == 0);
// 检查从机地址是否匹配
if ((I2C1->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR_MATCH) {
// 接收数据
for (uint8_t i = 0; i < len; i++) {
data[i] = I2C1->DR;
// 等待数据接收完成
while ((I2C1->SR1 & I2C_SR1_RXNE) == 0);
}
// 发送应答位
I2C1->CR1 |= I2C_CR1_ACK;
}
}
```
# 4. SPI接口
### 4.1 SPI协议和通信原理
#### 4.1.1 SPI通信模式和时钟极性
SPI(串行外设接口)是一种同步串行通信协议,它使用四根信号线:时钟(SCK)、主设备输出数据(MOSI)、从设备输入数据(MISO)和片选(CS)。SPI通信有两种模式:主从模式和多主模式。在主从模式中,一个主设备控制总线并与一个或多个从设备通信。在多主模式中,多个主设备可以共享总线,但一次只能有一个主设备处于活动状态。
SPI时钟极性定义了时钟信号的空闲状态。有两种时钟极性:CPOL=0和CPOL=1。当CPOL=0时,时钟信号在空闲状态为低电平;当CPOL=1时,时钟信号在空闲状态为高电平。
#### 4.1.2 数据传输和帧格式
SPI数据传输以帧为单位进行。一个帧由一个或多个字节组成,每个字节由8位数据位组成。数据位按最高有效位(MSB)优先的顺序传输。
SPI帧格式由以下字段组成:
- **起始位:**一个低电平信号,表示帧的开始。
- **数据位:**8位数据位,从MSB到LSB传输。
- **结束位:**一个高电平信号,表示帧的结束。
### 4.2 STM32 SPI硬件配置
#### 4.2.1 GPIO引脚复用和时钟配置
STM32单片机上的SPI外设与GPIO引脚复用。需要将相应的GPIO引脚配置为SPI功能。此外,还需要为SPI外设配置时钟。
以下代码展示了如何配置GPIO引脚和时钟:
```c
// GPIO引脚复用
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能GPIOA时钟
GPIOA->CRH &= ~(GPIO_CRH_MODE12 | GPIO_CRH_CNF12); // 复用PA6为SPI1_MOSI
GPIOA->CRH |= GPIO_CRH_MODE12_0 | GPIO_CRH_CNF12_1; // 配置PA6为推挽输出,50MHz
// 时钟配置
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // 使能SPI1时钟
SPI1->CR1 &= ~SPI_CR1_BR; // 设置波特率为fAPB2/2
SPI1->CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0; // fAPB2/4
```
#### 4.2.2 SPI寄存器配置
SPI外设的配置通过SPI寄存器进行。以下代码展示了如何配置SPI寄存器:
```c
// SPI寄存器配置
SPI1->CR1 &= ~SPI_CR1_CPHA; // 时钟极性为CPOL=0
SPI1->CR1 &= ~SPI_CR1_CPOL; // 时钟相位为CPHA=0
SPI1->CR1 |= SPI_CR1_MSTR; // 主机模式
SPI1->CR1 |= SPI_CR1_SSM; // 软件从机模式使能
SPI1->CR2 |= SPI_CR2_SSOE; // 从机输出使能
```
### 4.3 SPI通信编程
#### 4.3.1 主机模式通信
在主机模式下,STM32单片机作为SPI总线的主人,负责控制总线并与从设备通信。以下代码展示了如何进行主机模式通信:
```c
// 主机模式通信
uint8_t data = 0x55; // 要发送的数据
SPI1->DR = data; // 将数据写入数据寄存器
while (!(SPI1->SR & SPI_SR_TXE)); // 等待发送缓冲区为空
while (!(SPI1->SR & SPI_SR_RXNE)); // 等待接收缓冲区非空
uint8_t received_data = SPI1->DR; // 读取接收到的数据
```
#### 4.3.2 从机模式通信
在从机模式下,STM32单片机作为SPI总线的从设备,负责响应主设备的请求并进行数据传输。以下代码展示了如何进行从机模式通信:
```c
// 从机模式通信
while (1) {
if (SPI1->SR & SPI_SR_RXNE) { // 接收缓冲区非空
uint8_t received_data = SPI1->DR; // 读取接收到的数据
// 处理接收到的数据
}
if (SPI1->SR & SPI_SR_TXE) { // 发送缓冲区为空
SPI1->DR = 0x55; // 发送数据
}
}
```
# 5. ADC接口**
**5.1 ADC原理和采样技术**
**5.1.1 模数转换原理**
模数转换器(ADC)是一种将模拟信号(连续电压或电流)转换为数字信号(离散电压或电流)的电子器件。ADC的工作原理基于比较器和二分搜索算法。
**5.1.2 采样率和分辨率**
* **采样率:**ADC每秒钟转换模拟信号的次数,单位为赫兹(Hz)。采样率越高,ADC捕获模拟信号变化的精度就越高。
* **分辨率:**ADC转换后的数字信号的位数,单位为位(bit)。分辨率越高,ADC区分不同模拟信号的能力就越强。
**5.2 STM32 ADC硬件配置**
**5.2.1 GPIO引脚复用和时钟配置**
STM32单片机上的ADC外设需要与特定的GPIO引脚复用,以连接模拟信号源。同时,还需要配置ADC时钟。
**5.2.2 ADC寄存器配置**
ADC寄存器用于配置ADC的工作模式、采样率、分辨率等参数。主要寄存器包括:
* **ADC_CR1:**控制ADC的使能、触发源、转换模式等。
* **ADC_SQR1:**配置ADC的采样序列。
* **ADC_SMPR:**配置ADC的采样时间。
* **ADC_DR:**存储转换后的数字信号。
**5.3 ADC采样编程**
**5.3.1 单次采样**
单次采样模式下,ADC在收到触发信号后进行一次转换。
```c
// 单次采样
void ADC_SingleSample(void) {
// 1. 配置ADC寄存器
ADC_CR1 |= ADC_CR1_EOCIE; // 使能转换完成中断
ADC_CR2 |= ADC_CR2_SWSTART; // 软件触发转换
// 2. 等待转换完成中断
while (!(ADC_ISR & ADC_ISR_EOC)) {}
// 3. 读取转换结果
uint16_t adc_value = ADC_DR;
}
```
**5.3.2 连续采样**
连续采样模式下,ADC在收到触发信号后连续进行转换。
```c
// 连续采样
void ADC_ContinuousSample(void) {
// 1. 配置ADC寄存器
ADC_CR2 |= ADC_CR2_CONT; // 使能连续采样
ADC_CR2 |= ADC_CR2_SWSTART; // 软件触发转换
// 2. 循环读取转换结果
while (1) {
while (!(ADC_ISR & ADC_ISR_EOC)) {}
uint16_t adc_value = ADC_DR;
}
}
```
# 6. 实战应用
### 6.1 串口调试和数据传输
**串口调试**
* 使用串口调试STM32单片机非常方便,可以输出日志信息、诊断数据和调试信息。
* 在开发环境中,通常会使用串口调试工具,如串口终端或IDE中的调试窗口。
* 串口调试需要配置串口引脚、波特率和数据帧格式。
**数据传输**
* 串口还可以用于数据传输,例如与PC或其他设备进行通信。
* 可以通过中断或轮询方式接收和发送数据。
* 数据传输时,需要考虑数据帧格式、校验方式和数据流控制。
### 6.2 I2C连接传感器和显示器
**连接传感器**
* I2C总线可以连接各种传感器,如温度传感器、加速度计和湿度传感器。
* I2C协议提供了寻址机制,可以同时连接多个传感器。
* 需要配置I2C引脚、时钟和地址。
**连接显示器**
* I2C总线还可以连接OLED显示器或LCD显示器。
* 可以通过I2C总线发送命令和数据,控制显示器的显示内容。
* 需要配置I2C引脚、时钟和显示器地址。
### 6.3 SPI控制外围设备和存储器
**控制外围设备**
* SPI总线可以控制各种外围设备,如LED、按键和电机。
* SPI协议提供了全双工通信,可以同时发送和接收数据。
* 需要配置SPI引脚、时钟和通信模式。
**控制存储器**
* SPI总线还可以连接存储器芯片,如EEPROM和闪存。
* 可以通过SPI总线读写存储器数据。
* 需要配置SPI引脚、时钟和存储器地址。
### 6.4 ADC测量温度和电压
**测量温度**
* STM32单片机内置ADC模块,可以测量模拟信号,如温度。
* 需要配置ADC引脚、时钟和采样率。
* 可以使用内部温度传感器或外部温度传感器。
**测量电压**
* ADC模块也可以测量电压。
* 需要配置ADC引脚、时钟和采样率。
* 可以使用外部电压源或单片机内部基准电压。
0
0
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)