STM32单片机串口通信:10个实用技巧,让你的通信更流畅
发布时间: 2024-07-03 22:14:49 阅读量: 9 订阅数: 8 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![STM32单片机串口通信:10个实用技巧,让你的通信更流畅](https://img-blog.csdnimg.cn/2d1592caa84e4d12bf5cce263372b503.png)
# 1. STM32单片机串口通信简介
串口通信是嵌入式系统中常用的通信方式,它是一种异步通信方式,使用单根信号线进行数据传输。STM32单片机内置了丰富的串口资源,支持多种串口通信协议,可以广泛应用于各种嵌入式系统中。
本篇文章将详细介绍STM32单片机的串口通信,包括串口通信的原理、协议、硬件接口、编程实战、常见问题及解决方法、高级应用和案例分析等内容。通过学习本篇文章,读者可以全面掌握STM32单片机的串口通信技术,并能够熟练应用串口通信技术进行嵌入式系统开发。
# 2. 串口通信的理论基础
### 2.1 串口通信原理
串口通信是一种异步通信方式,数据以串行的方式逐位发送和接收。在串口通信中,数据被分解成一个个比特位,并通过一根或多根信号线传输。
串口通信的原理如下:
1. **数据发送:**发送端将数据分解成比特位,并通过发送线发送出去。每个比特位对应一个时间单位,称为比特时间。
2. **数据接收:**接收端通过接收线接收比特位,并将其重新组装成数据。接收端使用一个时钟信号来同步接收比特位。
### 2.2 串口通信协议
串口通信协议定义了数据传输的规则,包括:
- **波特率:**数据传输速率,单位为比特/秒。
- **数据位:**每个字符的比特数,通常为 5、6、7 或 8 位。
- **停止位:**字符末尾的停止位数,通常为 1 或 2 位。
- **奇偶校验:**用于检测数据传输错误的校验机制。
### 2.3 串口通信硬件接口
串口通信需要使用专门的硬件接口,称为串口控制器(UART)。UART 负责数据的发送和接收,以及协议的实现。
UART 通常具有以下引脚:
- **TXD:**发送数据引脚
- **RXD:**接收数据引脚
- **CTS:**清除发送(可选)
- **RTS:**请求发送(可选)
**代码块:**
```python
# UART 初始化代码
# 波特率:115200
# 数据位:8 位
# 停止位:1 位
# 奇偶校验:无
uart = UART(1, 115200, 8, 1, UART.PARITY_NONE)
```
**逻辑分析:**
该代码初始化了一个 UART 对象,并设置了波特率、数据位、停止位和奇偶校验等参数。
**参数说明:**
- `uart`:UART 对象
- `1`:UART 编号
- `115200`:波特率
- `8`:数据位
- `1`:停止位
- `UART.PARITY_NONE`:奇偶校验模式,无奇偶校验
# 3.1 串口初始化和配置
### 3.1.1 串口初始化
STM32单片机的串口初始化主要包括以下步骤:
1. **使能串口时钟:**在RCC寄存器中使能对应串口的时钟。
2. **配置串口引脚:**配置串口发送和接收引脚为复用功能,并连接到相应的GPIO端口。
3. **配置波特率:**设置串口波特率,通常使用USART_BRR寄存器。
4. **配置数据格式:**设置数据位、停止位、校验位等数据格式,通常使用USART_CR1寄存器。
5. **配置中断:**根据需要配置串口中断,通常使用USART_CR1和USART_CR2寄存器。
**代码块:**
```c
// 使能串口1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置串口1引脚
GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1;
// 配置串口1波特率为9600
USART1->BRR = 0x341;
// 配置串口1数据格式为8位数据位、1位停止位、无校验位
USART1->CR1 &= ~(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS);
USART1->CR1 |= USART_CR1_TE | USART_CR1_RE;
// 使能串口1接收中断
USART1->CR1 |= USART_CR1_RXNEIE;
```
**逻辑分析:**
* RCC->APB2ENR |= RCC_APB2ENR_USART1EN;:使能串口1时钟。
* GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);:清除GPIOA引脚9的模式和配置位。
* GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1;:配置GPIOA引脚9为复用功能,连接到串口1。
* USART1->BRR = 0x341;:设置串口1波特率为9600。
* USART1->CR1 &= ~(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS);:清除数据位、校验位和停止位配置。
* USART1->CR1 |= USART_CR1_TE | USART_CR1_RE;:使能串口1发送和接收。
* USART1->CR1 |= USART_CR1_RXNEIE;:使能串口1接收中断。
### 3.1.2 串口配置
串口初始化后,还可以根据需要进行以下配置:
* **配置流控:**使用USART_CR3寄存器配置硬件流控或软件流控。
* **配置超时:**使用USART_CR2寄存器配置发送和接收超时。
* **配置唤醒:**使用USART_CR1寄存器配置串口唤醒模式。
* **配置DMA:**使用USART_CR3寄存器配置串口与DMA的连接。
**代码块:**
```c
// 配置串口1硬件流控
USART1->CR3 |= USART_CR3_RTSE | USART_CR3_CTSE;
// 配置串口1发送超时为100ms
USART1->CR2 |= USART_CR2_TXTOEN;
USART1->CR2 &= ~USART_CR2_TXTO;
USART1->CR2 |= 0x64;
// 配置串口1唤醒模式为IDLE线检测
USART1->CR1 |= USART_CR1_WFE | USART_CR1_IDLEIE;
// 配置串口1与DMA1通道2连接
USART1->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR;
```
**逻辑分析:**
* USART1->CR3 |= USART_CR3_RTSE | USART_CR3_CTSE;:使能串口1硬件流控。
* USART1->CR2 |= USART_CR2_TXTOEN;:使能串口1发送超时。
* USART1->CR2 &= ~USART_CR2_TXTO;:清除发送超时值。
* USART1->CR2 |= 0x64;:设置发送超时值为100ms。
* USART1->CR1 |= USART_CR1_WFE | USART_CR1_IDLEIE;:使能串口1唤醒模式为IDLE线检测。
* USART1->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR;:配置串口1与DMA1通道2连接。
# 4. 串口通信常见问题及解决方法
### 4.1 串口通信无法建立
**问题描述:**
串口通信无法建立,发送和接收数据时没有响应。
**可能原因:**
* **硬件连接错误:**检查串口线缆连接是否正确,确保发送器和接收器之间的连接正确。
* **波特率不匹配:**发送器和接收器的波特率必须匹配,否则无法建立通信。
* **数据位、停止位、校验位不匹配:**发送器和接收器的串口参数必须一致,包括数据位、停止位和校验位。
* **串口引脚配置错误:**检查串口引脚是否正确配置为串口功能。
* **供电问题:**确保串口设备有足够的供电。
**解决方法:**
* 检查并重新连接串口线缆。
* 确保发送器和接收器的波特率匹配。
* 检查并配置串口参数,包括数据位、停止位和校验位。
* 检查串口引脚是否正确配置。
* 检查并确保串口设备有足够的供电。
### 4.2 串口通信数据传输错误
**问题描述:**
串口通信数据传输错误,接收到的数据与发送的数据不一致。
**可能原因:**
* **噪声干扰:**串口通信线路可能受到噪声干扰,导致数据传输错误。
* **数据帧错误:**数据帧可能损坏,导致接收器无法正确解析数据。
* **校验错误:**如果使用校验位,则校验错误可能导致数据传输错误。
* **缓冲区溢出:**接收器缓冲区可能溢出,导致数据丢失。
**解决方法:**
* 减少噪声干扰,例如使用屏蔽线缆或隔离器。
* 检查并修复数据帧错误。
* 检查并修复校验错误。
* 增加接收器缓冲区大小。
### 4.3 串口通信中断处理异常
**问题描述:**
串口通信中断处理异常,中断无法正常触发或处理。
**可能原因:**
* **中断配置错误:**中断向量表或中断优先级配置错误。
* **中断服务程序异常:**中断服务程序中可能存在异常,导致中断处理失败。
* **硬件故障:**串口硬件可能故障,导致中断无法正常触发。
**解决方法:**
* 检查并修复中断配置错误。
* 检查并修复中断服务程序异常。
* 检查并修复串口硬件故障。
# 5. STM32单片机串口通信高级应用
### 5.1 串口通信与DMA结合使用
DMA(Direct Memory Access,直接存储器访问)是一种数据传输技术,它允许外设直接与存储器进行数据交换,而无需CPU的干预。在串口通信中,使用DMA可以大大提高数据传输效率。
**操作步骤:**
1. **配置DMA通道:**选择一个DMA通道,并配置其源地址(串口接收/发送缓冲区)、目的地址(存储器地址)、传输大小、传输方向等参数。
2. **配置串口:**使能串口DMA请求,并选择相应的DMA通道。
3. **启动DMA传输:**启动DMA通道,DMA控制器将自动进行数据传输。
**代码示例:**
```c
// DMA初始化
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.Channel = DMA_Channel_4;
DMA_InitStruct.Direction = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.PeriphInc = DMA_PINC_Disable;
DMA_InitStruct.MemInc = DMA_MINC_Enable;
DMA_InitStruct.PeriphDataAlignment = DMA_PDATAALIGN_Byte;
DMA_InitStruct.MemDataAlignment = DMA_MDATAALIGN_Byte;
DMA_InitStruct.Mode = DMA_Mode_Normal;
DMA_InitStruct.Priority = DMA_Priority_High;
DMA_InitStruct.FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStruct.MemBurst = DMA_MBURST_Single;
DMA_InitStruct.PeriphBurst = DMA_PBURST_Single;
HAL_DMA_Init(&DMA_Handle, &DMA_InitStruct);
// 串口DMA使能
LL_USART_EnableDMAReq_RX(USART1);
```
**逻辑分析:**
* DMA初始化:配置DMA通道的参数,包括传输方向、数据对齐方式、传输模式等。
* 串口DMA使能:使能串口DMA请求,选择DMA通道。
* DMA传输启动:启动DMA通道,DMA控制器将自动进行数据传输。
### 5.2 串口通信与定时器结合使用
定时器是一种用于产生定时中断或脉冲输出的外设。在串口通信中,定时器可以用于:
* **波特率生成:**定时器可以产生波特率时钟,用于串口通信的时序控制。
* **数据帧定时:**定时器可以用于检测串口数据帧的开始位、停止位和数据位,并产生相应的中断。
**操作步骤:**
1. **配置定时器:**选择一个定时器,并配置其时钟源、分频系数、计数模式等参数。
2. **配置串口:**使能串口定时器模式,并选择相应的定时器。
3. **启动定时器:**启动定时器,定时器将产生定时中断或脉冲输出。
**代码示例:**
```c
// 定时器初始化
TIM_HandleTypeDef htim1;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 84-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1000-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim1);
// 串口定时器模式使能
LL_USART_EnableIT_RXNE(USART1);
LL_USART_EnableIT_TC(USART1);
```
**逻辑分析:**
* 定时器初始化:配置定时器的时钟源、分频系数、计数模式等参数。
* 串口定时器模式使能:使能串口定时器模式,选择TIM1定时器。
* 定时器启动:启动TIM1定时器,定时器将产生定时中断。
### 5.3 串口通信与协议栈结合使用
协议栈是一组用于实现特定通信协议的软件模块。在串口通信中,协议栈可以用于:
* **解析串口数据帧:**协议栈可以解析串口数据帧,提取出数据、校验和等信息。
* **生成串口数据帧:**协议栈可以根据数据生成串口数据帧,并添加校验和等信息。
* **处理通信协议:**协议栈可以处理通信协议,如Modbus、CAN等,实现特定通信功能。
**操作步骤:**
1. **选择协议栈:**选择一个合适的协议栈,并将其集成到应用程序中。
2. **配置协议栈:**配置协议栈的参数,如波特率、校验方式等。
3. **使用协议栈:**使用协议栈提供的函数解析数据帧、生成数据帧、处理通信协议。
**代码示例:**
```c
// Modbus协议栈初始化
modbus_t *mb;
mb = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_set_debug(mb, TRUE);
// 读取寄存器值
uint16_t reg_value;
int rc = modbus_read_registers(mb, 0, 1, ®_value);
```
**逻辑分析:**
* Modbus协议栈初始化:创建Modbus协议栈对象,并配置串口参数。
* 读取寄存器值:使用Modbus协议栈提供的函数读取寄存器值。
# 6. STM32单片机串口通信案例分析
### 6.1 串口通信与上位机交互
**应用场景:**
STM32单片机与上位机(如PC机)通过串口进行数据交互,实现远程控制、数据采集等功能。
**实现步骤:**
1. **上位机软件开发:**
- 使用C#、Python等语言开发上位机软件,建立串口连接,发送和接收数据。
- 设计图形界面,实现数据显示、控制命令发送等功能。
2. **STM32单片机程序开发:**
- 初始化串口,配置波特率、数据位、停止位等参数。
- 实现数据接收和发送函数,处理上位机发送的命令,并返回相应的数据。
3. **串口连接:**
- 使用RS232或USB转串口模块,将STM32单片机与上位机连接。
- 确保两端的串口参数(波特率、数据位等)一致。
**示例代码:**
```c
// STM32单片机代码
#include "stm32f10x.h"
// 串口初始化
void USART_Init(void) {
// ...
}
// 串口数据接收
void USART_Receive(uint8_t *data) {
// ...
}
// 串口数据发送
void USART_Send(uint8_t *data) {
// ...
}
// ...
```
```c#
// 上位机软件代码
using System;
using System.IO.Ports;
namespace SerialCommunication {
class Program {
static void Main(string[] args) {
// 串口连接
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
serialPort.Open();
// 数据交互
while (true) {
// 从上位机接收数据
string data = serialPort.ReadLine();
Console.WriteLine("Received data: " + data);
// 向单片机发送数据
serialPort.WriteLine("Hello from PC");
}
}
}
}
```
### 6.2 串口通信与传感器通信
**应用场景:**
STM32单片机与传感器(如温湿度传感器、光照传感器)通过串口进行数据交互,采集环境数据。
**实现步骤:**
1. **传感器选择:**
- 根据测量需求选择合适的传感器,确保其支持串口通信。
2. **STM32单片机程序开发:**
- 初始化串口,配置波特率、数据位、停止位等参数。
- 实现数据接收函数,解析传感器发送的数据,提取测量值。
3. **传感器连接:**
- 使用RS232或TTL电平转换模块,将传感器与STM32单片机连接。
- 确保两端的串口参数(波特率、数据位等)一致。
**示例代码:**
```c
// STM32单片机代码
#include "stm32f10x.h"
// 串口初始化
void USART_Init(void) {
// ...
}
// 串口数据接收
void USART_Receive(uint8_t *data) {
// ...
}
// 温湿度传感器数据解析
void ParseTemperatureHumidityData(uint8_t *data) {
// ...
}
// ...
```
```c#
// 上位机软件代码
using System;
using System.IO.Ports;
namespace SensorCommunication {
class Program {
static void Main(string[] args) {
// 串口连接
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
serialPort.Open();
// 数据交互
while (true) {
// 从传感器接收数据
string data = serialPort.ReadLine();
Console.WriteLine("Received data: " + data);
// 解析温湿度数据
double temperature = ParseTemperature(data);
double humidity = ParseHumidity(data);
// 显示测量值
Console.WriteLine("Temperature: " + temperature + "°C");
Console.WriteLine("Humidity: " + humidity + "%");
}
}
}
}
```
### 6.3 串口通信与无线通信模块通信
**应用场景:**
STM32单片机与无线通信模块(如ZigBee、LoRa)通过串口进行数据交互,实现无线数据传输。
**实现步骤:**
1. **无线通信模块选择:**
- 根据通信距离、速率、功耗等需求选择合适的无线通信模块。
2. **STM32单片机程序开发:**
- 初始化串口,配置波特率、数据位、停止位等参数。
- 实现数据发送和接收函数,与无线通信模块进行数据交互。
3. **无线通信模块连接:**
- 使用RS232或TTL电平转换模块,将无线通信模块与STM32单片机连接。
- 确保两端的串口参数(波特率、数据位等)一致。
**示例代码:**
```c
// STM32单片机代码
#include "stm32f10x.h"
// 串口初始化
void USART_Init(void) {
// ...
}
// 串口数据发送
void USART_Send(uint8_t *data) {
// ...
}
// 串口数据接收
void USART_Receive(uint8_t *data) {
// ...
}
// ZigBee数据发送
void ZigBee_SendData(uint8_t *data) {
USART_Send(data);
}
// ...
```
```c#
// 上位机软件代码
using System;
using System.IO.Ports;
namespace WirelessCommunication {
class Program {
static void Main(string[] args) {
// 串口连接
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
serialPort.Open();
// 数据交互
while (true) {
// 从上位机接收数据
string data = serialPort.ReadLine();
Console.WriteLine("Received data: " + data);
// 向无线通信模块发送数据
serialPort.WriteLine("Hello from PC");
}
}
}
}
```
0
0
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://img-home.csdnimg.cn/images/20210720083646.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)