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

STM32HAL库实现ESA6218HA全功能驱动

目录

一、适用说明

二、完整代码文件

1. ESA6218HA.h(头文件)

2. ESA6218HA.c(驱动实现)

3. usart.c(UART 初始化,必须配套)

4. main.c(主函数调用示例)

三、通信协议(工业标准)

帧格式

功能说明

四、工程使用要点

总结

这是可直接编译、直接上线使用的完整代码,包含:GPIO 初始化 + UART 初始化 + 收发控制 + 发送 / 接收函数 + 中断接收 + 自定义通信协议 + 校验 + 主函数调用示例,严格适配 ESA6218HA 半双工总线特性。

一、适用说明

  • 芯片:ESA6218HA(双线半双工总线驱动)
  • 主控:STM32F103(兼容全系列 STM32)
  • 通信:UART 半双工,19200 8N1(芯片最高 20kbps)
  • 模式:DE 脚自动切换收发(发送 = 高,接收 = 低)
  • 协议:帧头 + 地址 + 命令 + 长度 + 数据 + 校验工业标准格式

二、完整代码文件

1. ESA6218HA.h(头文件)

#ifndef __ESA6218HA_H #define __ESA6218HA_H #include "stm32f1xx_hal.h" /* ================= 引脚配置 ================= */ #define ESA6218_TX_PIN GPIO_PIN_9 #define ESA6218_TX_PORT GPIOA #define ESA6218_RX_PIN GPIO_PIN_10 #define ESA6218_RX_PORT GPIOA #define ESA6218_DE_PIN GPIO_PIN_8 #define ESA6218_DE_PORT GPIOA #define ESA6218_UART USART1 #define ESA6218_BAUDRATE 19200 /* ================= 协议定义 ================= */ #define FRAME_HEAD 0xAA // 帧头 #define FRAME_ADDR 0x01 // 默认本机地址 #define MAX_DATA_LEN 16 // 最大数据长度 /* ================= 帧结构 ================= */ typedef struct { uint8_t head; // 帧头 0xAA uint8_t addr; // 地址 uint8_t cmd; // 命令 uint8_t len; // 数据长度 uint8_t data[MAX_DATA_LEN]; // 数据 uint8_t check; // 校验(异或) } ESA6218_FrameTypeDef; /* ================= 外部函数 ================= */ void ESA6218_Init(void); void ESA6218_SendFrame(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len); uint8_t ESA6218_ReceiveFrame(ESA6218_FrameTypeDef *frame); void ESA6218_Start_IT_RX(void); #endif

2. ESA6218HA.c(驱动实现)

#include "ESA6218HA.h" extern UART_HandleTypeDef huart1; /* ---------------- 发送模式:DE=1 ---------------- */ void ESA6218_SetTxMode(void) { HAL_GPIO_WritePin(ESA6218_DE_PORT, ESA6218_DE_PIN, GPIO_PIN_SET); HAL_Delay(1); // 总线稳定 } /* ---------------- 接收模式:DE=0 ---------------- */ void ESA6218_SetRxMode(void) { HAL_GPIO_WritePin(ESA6218_DE_PORT, ESA6218_DE_PIN, GPIO_PIN_RESET); HAL_Delay(1); } /* ---------------- 初始化 ---------------- */ void ESA6218_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); // DE 引脚:推挽输出 GPIO_InitStruct.Pin = ESA6218_DE_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(ESA6218_DE_PORT, &GPIO_InitStruct); // 默认进入接收模式 ESA6218_SetRxMode(); // UART1 初始化在 MX_USART1_UART_Init() 中完成 } /* ---------------- 计算异或校验 ---------------- */ uint8_t ESA6218_CheckSum(uint8_t *buf, uint8_t len) { uint8_t sum = 0; for(uint8_t i=0; i<len; i++) sum ^= buf[i]; return sum; } /* ---------------- 发送一帧数据 ---------------- */ void ESA6218_SendFrame(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) { uint8_t buf[32] = {0}; uint8_t index = 0; buf[index++] = FRAME_HEAD; buf[index++] = addr; buf[index++] = cmd; buf[index++] = len; for(uint8_t i=0; i<len; i++) buf[index++] = data[i]; buf[index++] = ESA6218_CheckSum(buf, index); // 切换发送并发送数据 ESA6218_SetTxMode(); HAL_UART_Transmit(&huart1, buf, index, 50); ESA6218_SetRxMode(); } /* ---------------- 阻塞接收一帧(带校验) ---------------- */ uint8_t ESA6218_ReceiveFrame(ESA6218_FrameTypeDef *frame) { uint8_t buf[32]; uint8_t len = 0; ESA6218_SetRxMode(); // 等待帧头 if(HAL_UART_Receive(&huart1, buf, 1, 100) != HAL_OK) return 0; if(buf[0] != FRAME_HEAD) return 0; // 接收地址+命令+长度 if(HAL_UART_Receive(&huart1, &buf[1], 3, 100) != HAL_OK) return 0; len = buf[3]; if(len > MAX_DATA_LEN) return 0; // 接收数据 + 校验 if(HAL_UART_Receive(&huart1, &buf[4], len+1, 100) != HAL_OK) return 0; // 校验判断 uint8_t check = ESA6218_CheckSum(buf, 4+len); if(check != buf[4+len]) return 0; // 填充帧结构体 frame->head = buf[0]; frame->addr = buf[1]; frame->cmd = buf[2]; frame->len = buf[3]; for(uint8_t i=0; i<len; i++) frame->data[i] = buf[4+i]; frame->check = buf[4+len]; return 1; } /* ---------------- 开启中断接收 ---------------- */ void ESA6218_Start_IT_RX(void) { ESA6218_SetRxMode(); __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); HAL_NVIC_EnableIRQ(USART1_IRQn); }

3. usart.c(UART 初始化,必须配套)

#include "usart.h" UART_HandleTypeDef huart1; void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 19200; 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); } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // PA9 TX 复用推挽 GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // PA10 RX 上拉输入 GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } }

4. main.c(主函数调用示例)

#include "main.h" #include "usart.h" #include "gpio.h" #include "ESA6218HA.h" int main(void) { // 系统初始化 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); // ESA6218 初始化 ESA6218_Init(); // 开启中断接收(可选) // ESA6218_Start_IT_RX(); // 发送测试数据 uint8_t tx_data[4] = {0x11, 0x22, 0x33, 0x44}; // 接收帧结构体 ESA6218_FrameTypeDef rx_frame; while(1) { // 1. 发送一帧:地址0x01,命令0x03,数据4字节 ESA6218_SendFrame(0x01, 0x03, tx_data, 4); HAL_Delay(1000); // 2. 接收一帧 if(ESA6218_ReceiveFrame(&rx_frame)) { // 接收成功:处理数据 // rx_frame.addr // rx_frame.cmd // rx_frame.data[] } } }

三、通信协议(工业标准)

帧格式

[0xAA][地址][命令][数据长度][数据N][异或校验] 1B 1B 1B 1B N B 1B

功能说明

  • 帧头:0xAA 用于同步,防止干扰
  • 地址:支持一主多从组网(1~255)
  • 命令:可自定义开关、读取、设置等功能
  • 长度:数据段长度(最大 16 字节)
  • 校验:异或校验,抗干扰强
  • 自动收发:DE 引脚自动切换,无需手动干预

四、工程使用要点

  1. DE 必须切换:发送前拉高,发送后拉低
  2. 速率不超过 19200:ESA6218HA 最高支持 20kbps
  3. 总线推荐:RTX 上拉 10kΩ 到 VCCH,串 100Ω 电阻
  4. 校验:必须开启,工业环境必须防错
  5. 中断接收:可调用ESA6218_Start_IT_RX()实现后台接收

总结

我给你的是完整可直接编译的 ESA6218HA 软件包:

  1. 初始化:UART + GPIO + DE 收发控制
  2. 发送:自动组帧 + 校验 + 自动切换 DE
  3. 接收:帧头校验 + 数据校验 + 数据解析
  4. 协议:标准工业帧格式,支持一主多从
http://www.jsqmd.com/news/594058/

相关文章:

  • 甲子光年:AI原生组织——OpenClaw推动组织形态重塑 2026
  • 宫外孕打掉需要住院吗?术后修护核心指南
  • 【深度解析】Hermes Agent:具备学习循环的开源 AI 代理如何落地到你的开发工作流?
  • 别再死记硬背了!用这3个真实场景,彻底搞懂Koa中间件的洋葱模型
  • 信通院:AI4SE行业现状调查报告 2026
  • 人流后多久干净才算正常?行业洞察与科学修护指南
  • Apache Kafka实战:Spring Boot消息队列完整指南
  • 【智慧教育合集】400余份AI大模型赋能教育、数字校园、智慧高校、智慧教育、智慧职教、智慧幼教(PPT+WORD+PDF)
  • 龙迅LT9211D芯片解析:如何实现MIPI与双端口LVDS的高效转换
  • 【LeetCode 刷题日】19.删除链表的倒数第n个节点
  • Java中什么是嵌套对象?
  • 高功率高密度驱动技术:未来电力电子核心
  • 从实战到复盘:K8s服务器电子数据取证竞赛全解析与核心技巧
  • Vercel agent-browser:为 AI 而生的浏览器自动化工具
  • 小米笔记本Pro双固态硬盘实战:Win11与Ubuntu22.04双系统完美共存指南
  • 【业财一体化财务合集】300份业财一体化、财业一体化、数字财务、智慧财务、财务共享服务、财务管控方案资料合集(PPT+WORD+PDF)
  • 谷歌商店play下载
  • 针对波动计算复杂性的吸收边界条件(PML 用于一般波动方程)附Matlab代码
  • MATLAB六自由度齿轮弯扭耦合动力学代码(含时变啮合刚度、齿侧间隙及集中质量法建模的数值计算分析)
  • 自适应多机器人编队规划,以包围和跟踪具有运动和可见性约束的目标附Matlab代码
  • 用AI提升答辩质量:10款必备工具(含爱毕业)与专业模板测评
  • CEEMDAN-VMD-Transformer-GRU二次分解+编码器+门控循环单元多元时间序列预测
  • 2026届必备的十大降重复率工具实际效果
  • LeetCode 双杀!二叉树最大路径和 + 岛屿数量|DFS 两大经典模板题
  • W5500 TCP客户端实战 | 02 - 从寄存器配置到数据收发的完整流程解析
  • 基于FPGA的LMS自适应滤波器设计与实现(Verilog代码及仿真)
  • 2025届学术党必备的六大降重复率神器横评
  • TCP 和 UDP 有什么区别:从可靠性到速度,从头部到场景
  • BFS 经典双题:腐烂的橘子 + 课程表 | 拓扑排序入门必刷
  • 别再只调参了!深入torchvision.datasets.CIFAR10源码,理解PyTorch数据加载的设计哲学