当前位置: 首页 > news >正文

STM32 串口通信

引言

在嵌入式系统开发中,串口通信是最基础且重要的通信方式之一。无论是设备调试、模块对接还是远程通信,串口都扮演着关键角色。本文将从通信协议原理出发,结合STM32F4系列MCU,深入讲解串口通信的硬件实现和软件配置,并通过实战案例展示其应用。

一、串口通信协议深度解析

1.1 串口通信核心概念

串行接口(Serial Port)采用逐位顺序传输方式,其优势在于:

  • 硬件成本低(仅需2根信号线)
  • 传输距离远(RS485可达千米级)
  • 抗干扰能力强
  • 协议简单易实现

常见串口类型对比:

类型电平标准传输距离通信方式
TTL0-3.3V/5V<3m全双工
RS232±3-15V15m全双工
RS485±1.5-6V1200m半双工

1.2 通信协议分层模型

物理层规范

  • 接口类型:DB9、RJ45、端子排
  • 电平标准:RS232使用负逻辑(逻辑1=-3-15V,逻辑0=+3+15V)
  • 连接拓扑:点对点、总线型

协议层规范

  • 数据帧格式
  • 波特率精度(误差<2%)
  • 校验机制
  • 流控协议(硬件RTS/CTS,软件XON/XOFF)

1.3 数据帧结构详解

标准异步串行数据帧构成:

[Start Bit][Data Bits][Parity Bit][Stop Bits]

典型参数配置示例:

c

Copy

/* 8位数据位,无校验,1位停止位 */
UART_InitStructure.WordLength = UART_WORDLENGTH_8B;
UART_InitStructure.StopBits = UART_STOPBITS_1;
UART_InitStructure.Parity = UART_PARITY_NONE;

校验方式性能对比:

校验类型错误检测能力数据开销
奇校验单比特错误+1 bit
偶校验单比特错误+1 bit
CRC校验多比特错误+1-4字节

二、STM32F4串口硬件架构剖析

2.1 USART功能框图

https://example.com/stm32-usart-block-diagram.png

关键功能模块:

  1. 波特率发生器:BRR寄存器实现分数波特率生成
  2. 数据寄存器(TDR/RDR)
  3. 校验控制单元
  4. 中断控制器
  5. DMA接口

2.2 时钟系统配置

时钟树路径:
APBx总线时钟 → USARTDIV分频器 → 生成比特周期

波特率计算公式:

波特率 = fCK / (16 * USARTDIV)

其中USARTDIV为16位浮点数(高12位整数,低4位小数)

配置示例(72MHz时钟,115200波特率):

c

Copy

// USARTDIV = 72000000/(16 * 115200) = 39.0625
USART1->BRR = (39 << 4) | 0x1; // 0x271

2.3 GPIO映射配置

STM32F407 USART1引脚映射:

功能引脚复用功能
TXPA9AF7
RXPA10AF7
CTSPA11AF7
RTSPA12AF7

配置代码示例:

c

Copy

GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

三、STM32串口编程实战

3.1 基础通信实现

初始化流程:

c

Copy

UART_HandleTypeDef huart1;void USART1_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;HAL_UART_Init(&huart1);
}

数据收发函数:

c

Copy

// 阻塞式发送
HAL_UART_Transmit(&huart1, (uint8_t*)"Hello", 5, 1000);// 中断接收
HAL_UART_Receive_IT(&huart1, &rx_data, 1);

3.2 中断处理机制

中断服务函数示例:

c

Copy

void USART1_IRQHandler(void)
{HAL_UART_IRQHandler(&huart1);
}// 回调函数实现
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){// 处理接收数据process_data(rx_data);// 重新使能接收HAL_UART_Receive_IT(huart, &rx_data, 1);}
}

3.3 DMA高效传输

DMA配置示例:

c

Copy

// 发送DMA配置
hdma_usart1_tx.Instance = DMA2_Stream7;
hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart_tx.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&hdma_usart_tx);// 启动DMA传输
HAL_UART_Transmit_DMA(&huart1, tx_buffer, BUFFER_SIZE);

四、典型应用案例

4.1 串口调试终端实现

重定向printf函数:

c

Copy

int __io_putchar(int ch)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 1000);return ch;
}

使用示例:

c

Copy

printf("System Clock: %ld Hz\r\n", HAL_RCC_GetSysClockFreq());

4.2 MODBUS协议实现

协议帧结构:

[地址][功能码][数据][CRC校验]

CRC16校验实现:

c

Copy

uint16_t CRC16(uint8_t *buf, int len)
{uint16_t crc = 0xFFFF;for(int pos=0; pos<len; pos++){crc ^= (uint16_t)buf[pos];for(int i=8; i!=0; i--){if((crc & 0x0001) != 0){crc >>= 1;crc ^= 0xA001;}elsecrc >>= 1;}}return crc;
}

五、调试技巧与常见问题

5.1 故障排查指南

  1. 无数据收发
    • 检查物理连接
    • 验证波特率设置
    • 确认GPIO复用配置
  2. 数据错乱
    • 校验时钟精度
    • 检查电磁干扰
    • 验证电平匹配
  3. 接收数据不完整
    • 调整缓冲区大小
    • 优化中断优先级
    • 启用硬件流控

5.2 性能优化建议

  • 使用DMA进行大数据传输
  • 合理设置FIFO阈值
  • 采用环形缓冲区管理
  • 启用硬件校验功能

结语

通过本文的系统讲解,我们不仅深入理解了串口通信的协议原理,还掌握了STM32平台下的硬件配置和软件开发技巧。在实际项目中,建议根据具体需求选择合适的通信模式(轮询/中断/DMA),并注意做好电磁兼容设计。随着对串口技术的深入掌握,开发者可以更高效地实现各种工业通信需求。

相关文章:

  • Git 详细使用说明文档(适合小白)
  • MVCC详解
  • maven工程中引入外部jar
  • 信息系统项目管理工程师备考计算类真题讲解八
  • 拥抱健康生活,解锁养生之道
  • Trae或者VsCode无法识别相对路径(不自动切换工作目录)
  • VSCode如何修改默认扩展路径和用户文件夹目录到其他盘以及微信开发工具如何修改扩展路径到其他盘
  • C# 音频分离(MP3伴奏)
  • WHAT - 区分 Git PR 和 MR
  • 使用setGraphicsEffect重新设置阴影导致程序崩溃的问题
  • IP的基础知识以及相关机制
  • QTcpSocket 和 QUdpSocket 来实现基于 TCP 和 UDP 的网络通信
  • 爬虫学习——使用HTTP服务代理、redis使用、通过Scrapy实现分布式爬取
  • kubernetes》》k8s》》Dashboard
  • 2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
  • idea连接远程服务器kafka
  • MySQL:数据库设计
  • 主流操作系统对比分析(macOS、Linux、Windows、Unix)
  • GitHub万星项目维护者分享:开源协作的避坑指南
  • 【技术派后端篇】技术派中 Session/Cookie 与 JWT 身份验证技术的应用及实现解析
  • 限时离境、关闭领空、暂停贸易,巴基斯坦宣布一系列对印反制措施
  • 岭南非遗大IP来上海了,舞剧《英歌》在文化广场连演两场
  • 民生访谈|马拉松中签率低何解?预付费监管落实得如何?市体育局回应
  • 全国双拥模范城(县)名单
  • 外卖江湖战火重燃,骑手、商家、消费者在“摇摆”什么?
  • 专访|前伊核谈判顾问:伊朗不信任美国,任何核协议都会有中俄参与