基于STM32与RS485总线的串口通信
一、硬件架构设计
1. 硬件连接示意图
STM32(F103C8T6) MAX485芯片 LabVIEW PC
- -
USART1_TX → DI → RO (MAX485)
USART1_RX ← RO → DI (MAX485)
DE/RE → GPIOA.8 → DE/RE (控制)
GND → GND
3.3V → VCC
2. 关键元器件选型
| 元件 | 型号 | 作用 |
|---|---|---|
| MCU | STM32F103C8T6 | 主控芯片 |
| RS485收发器 | MAX485 | 电平转换 |
| 终端电阻 | 120Ω | 抑制信号反射 |
二、STM32固件开发
1. USART初始化代码
// USART1配置 (9600bps, 8N1)
void USART1_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// GPIO配置
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // TX
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; // RX
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// USART配置
USART_InitStruct.USART_BaudRate = 9600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
// 使能接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
// RS485控制引脚配置
#define RS485_DE_PIN GPIO_Pin_8
#define RS485_DE_PORT GPIOA
void RS485_SetTxMode() {
GPIO_SetBits(RS485_DE_PORT, RS485_DE_PIN);
}
void RS485_SetRxMode() {
GPIO_ResetBits(RS485_DE_PORT, RS485_DE_PIN);
}
2. 数据帧结构定义
#define FRAME_HEADER 0xAA
#define FRAME_TAIL 0x55
typedef struct {
uint8_t header; // 帧头
uint8_t addr; // 设备地址
uint8_t cmd; // 命令码
uint16_t data_len; // 数据长度
uint8_t *payload; // 数据负载
uint8_t checksum; // 校验和
uint8_t tail; // 帧尾
} RS485_Frame;
3. 数据收发实现
// 发送数据函数
void RS485_SendData(uint8_t *data, uint16_t len) {
RS485_SetTxMode();
HAL_UART_Transmit(&huart1, data, len, 1000);
RS485_SetRxMode();
}
// 中断接收处理
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
uint8_t byte = USART_ReceiveData(USART1);
// 实现环形缓冲区存储
ring_buffer_write(&rx_buf, byte);
}
}
三、LabVIEW上位机开发
1. VISA串口配置
[VISA Configure Serial Port]
Resource Name: COM3
Baud Rate: 9600
Data Bits: 8
Stop Bits: 1
Parity: None
Flow Control: None
Termination Character: 0xA
2. 数据解析流程图
[While Loop]
│
├─[VISA Read] → [Bytes at Port] → [Case Structure]
│ │
│ └─[Data Parsing]
│ ├─[Check Header] → 0xAA?
│ ├─[Extract Address] → [Compare Address]
│ ├─[CRC Check] → [Compare Checksum]
│ └─[Data Processing]
│
└─[VISA Write] → [Response Frame]
3. 关键VI模块
- 串口初始化VI:配置串口参数
- 数据发送VI:构建标准数据帧
- 数据解析VI:提取有效载荷
- 状态监控VI:显示通信状态
四、通信协议设计
1. 自定义协议规范
| 字段 | 长度 | 描述 |
|---|---|---|
| Header | 1字节 | 固定为0xAA |
| Addr | 1字节 | 设备地址(0x01-0xFE) |
| Cmd | 1字节 | 命令码(如0x10=读取数据) |
| DataLen | 2字节 | 数据长度(大端格式) |
| Payload | N字节 | 有效数据 |
| Checksum | 1字节 | 前6字节累加和取低8位 |
| Tail | 1字节 | 固定为0x55 |
2. CRC校验实现
uint8_t CalculateCRC(uint8_t *data, uint16_t len) {
uint8_t crc = 0;
for(uint16_t i=0; i<len; i++) {
crc ^= data[i];
for(uint8_t j=0; j<8; j++) {
crc = (crc & 0x80) ? (crc << 1) ^ 0x31 : crc << 1;
}
}
return crc;
}
五、完整通信流程
-
初始化阶段 STM32配置USART和GPIO LabVIEW打开串口连接
-
数据发送流程
LabVIEW → 构建帧 → 发送帧 → 等待ACK → 处理响应 -
数据接收流程
STM32 → 接收数据 → 校验完整性 → 触发中断 → 存入缓冲区
参考代码 STM32+RS485串口通信,上位机是labview www.youwenfan.com/contentcnj/70326.html
六、工程文件结构
STM32_RS485_Project/
├── Src/
│ ├── main.c
│ ├── usart_driver.c
│ └── crc.c
├── Inc/
│ ├── usart_driver.h
│ └── crc.h
├── LabVIEW/
│ ├── Serial_Comm.vi
│ └── Data_Parser.vi
└── Hardware/
├── schematic.pdf
└── gerber_files/
七、扩展功能实现
-
Modbus协议封装
void Modbus_SendRequest(uint16_t addr, uint8_t func, uint16_t reg) { uint8_t frame[8] = {0xAA, addr, func, 0x00, 0x02, 0x00, reg, 0x00}; frame[6] = CalculateCRC(frame, 6); RS485_SendData(frame, 8); } -
多设备轮询
[For Loop] │ ├─[Set Address] → 0x01 → 0x02 → 0x03 ├─[Send Query] → [Read Data] └─[Store Results]
浙公网安备 33010602011771号