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

极海APM32F107V6 gpio模拟串口

一、原理部分

之前用外设都是直接用的硬件自带的库,虽然以前有学过原理和时序,但是因为工作其实也很少会有需要gpio模拟串口的情况,但总会有串口用完,但是需要一个类似打印串口的情况。今天也是开整,然后用硬件的库对比一下。

1、协议要点

①、异步通讯:

        通信双方没有共享时钟信号。依靠预先约定好的波特率 (Baud Rate) 来同步。

②、数据帧格式 (常见):

        起始位 (Start Bit): 1位,低电平 (逻辑0)。标志着数据帧的开始,用于同步接收方。

        数据位 (Data Bits): 5-9位(通常8位)。从最低有效位 (LSB) 开始发送/接收。

        校验位 (Parity Bit): 可选,1位(奇校验、偶校验或无校验)。用于简单的错误检测。

        停止位 (Stop Bit): 1位、1.5位或2位,高电平 (逻辑1)。标志数据帧的结束,并为下一帧提供缓冲空间。

        空闲状态 (Idle State): 当没有数据传输时,数据线保持高电平。

        波特率: 定义了每秒传输的符号(位)数。例如,9600 bps 表示每秒传输9600位数据。位周期 (Bit Time) 是波特率的倒数:T_bit = 1 / BaudRate。这是软件模拟时最关键的参数。

③、时间计算

例如现在波特率为9600,T_bit = 1 / 9600 ≈ 0.0001041667 秒 = 104.1667 微秒 (μs)

用我们最常见的格式,8为数据位,1位起始位,1位停止位,即10位

计算传输一个字节 (10位) 所需的总时间 (T_frame):
T_frame = 10 位 * T_bit = 10 * 104.1667 μs ≈ 1041.667 μs ≈ 1.042 ms

可以理解为 大约 1 毫秒 发送一个字节。

发送端要求:需要在 104.17 μs 的整数倍时间点精确切换GPIO电平。

接收端要求:需要在起始位下降沿后等待1.5*T_bit ≈156.25us进行第一次采样(定位到数据位中间),之后每隔104.17us 采样一次后续位

波特率115200的话即速度是 9600 波特率的 12 倍,这里就不再写那么长

2、GPIO 模拟发送 (TX) 

①、配置:

将选定的GPIO引脚配置为推挽输出模式,初始状态设置为高电平(空闲状态)。

②、发送一个字节的流程:

a. 起始位:

将GPIO引脚拉低,并保持1个完整的位周期 (T_bit)。这告诉接收方数据开始传输。

b. 数据位 (LSB First):

从要发送字节的最低位 (bit 0) 开始。

根据该位的值是0还是1,将GPIO引脚设置为低电平或高电平。

保持这个电平状态1个完整的位周期 (T_bit)。

接着发送下一位 (bit 1),重复上述电平设置和延时过程。

依此类推,直到发送完指定的数据位数 (通常是8位)。

c. 校验位 (如果启用):

计算已发送数据位的奇偶性 (奇校验或偶校验)。

根据计算结果,将GPIO引脚设置为相应的电平 (0或1)。

保持这个电平状态1个完整的位周期 (T_bit)。

d. 停止位:

将GPIO引脚拉高。

保持高电平状态1个 (或1.5/2个) 完整的位周期 (T_bit)。这标志着一帧数据的结束,并使线路恢复到空闲状态。

需要注意的点为:

精确的时序: 每个位(起始位、数据位、校验位、停止位)的电平持续时间必须严格等于位周期 (T_bit)。这是模拟成功的最核心要求。任何累积的时序误差都会导致通信失败。

位顺序: 严格遵守协议约定的位顺序(通常是LSB first)。

中断的影响这里我就先不考虑了,因为我只是回顾下原理,不是真的要用模拟gpio来实现项目需求

3、GPIO 模拟接收 (RX) 

①、配置:

将选定的GPIO引脚配置为浮空输入或上拉输入模式(确保空闲时为高电平)。

②、检测起始位:

持续轮询(或在中断中检测)GPIO引脚状态。

当检测到引脚从高电平变为低电平(下降沿)时,可能是一个起始位开始。

③、同步与采样:

检测到下降沿后,不能立即采样数据。需要避开信号边沿可能不稳定的区域。

关键延时: 等待 1.5个位周期 (1.5 * T_bit)。这个延时将采样点定位到第一个数据位 (LSB) 的中间位置。这是提高抗噪性和采样稳定性的常用技巧。

④、读取数据位:

在预期的采样点(每个数据位的中间位置),读取GPIO引脚的电平状态。

将读取到的电平值 (0或1) 存入接收字节的对应位(从LSB开始)。

每读取完一位,等待1个位周期 (T_bit) 到达下一位的采样点。

重复这个过程,读取完所有数据位 (如8位)。

⑤、读取校验位 (如果启用):

在下一个采样点(等待1个位周期后),读取GPIO引脚的电平作为校验位。

根据协议(奇/偶校验)和收到的数据位计算期望的校验位,与实际收到的校验位比较,进行错误检查(可选)。

⑥、检测停止位:

在下一个采样点(等待1个位周期后),读取GPIO引脚的电平。期望是高电平 (1)。

如果检测到高电平,说明停止位有效,一帧数据接收基本完成(可考虑校验结果)。

如果检测到低电平,说明发生了帧错误(Frame Error)

需要注意的点为:1.5 * T_bit 和后续的 1 * T_bit 延时必须非常准确。采样点定位在位的中间是最佳实践。

二、配置工程

我的板子是APM32F107VC EVAL_V1.0

因为之前看是pin to pin,我以为是完全兼容,所以用cubemx生成了工程,后来程序一直跑不了,查了一下要用极海官方的sdk才行。

在官方下载sdk和pack即可

之前都是用IAR,现在公司用keil,就用回keil

我用的是他串口中断的例程做base

APM32F107_EVAL_SDK_v1.0\Examples\USART\USART_Interrupt\Project\MDK

如上图复制到自己工程的文件夹

再将路径改一下

然后这里每个都要重新添加一下

编译成功,跑了一下程序OK

三、修改程序

1、定义的结构体和宏

用PD13做TX,PD14做RX

我这里做的波特率9600,没有做太高的

tx rx初始化,其中rx配置为中断

2、初始化

其中rx配置为外部中断

两个定时器,定时器5做帧间隔的计时,定时器6为判断数据是否结束(跟之前stm32接收不定长数据差不多STM32+Cubemx+Esp8266(一)串口接收不定长数据_stm32cubemx esp8266-CSDN博客)

2、发送部分

单个字符

字符串

发送数组

这里我是直接延时硬等,可以再加一个定时器用作发送。

3、接收部分

在接收首个低电平的时候,即为起始帧,然后打开定时器5处理后边的数据

定时器5的中断就是数据处理

这里我是1为起始位,8位数据位,1位停止位,无校验,依次处理就好,用UART_TEST_Handle.rxBitCount作判断当前在第几位。数据保存到UART_TEST_Handle.rxBuffer这个buff,

然后每收到一个字节都打开定时器6,定时器6做了11位的时间,若是定时器6中断溢出则说明这帧数据结束,标志位置1

4、主函数

检测标志位是否置1,置1则发送rx的buffer,相当于回显

实际上我这里虽然做了发送队列,但我接收buff没做,所以也是只能发一条而已。这个是之前打印其他比较多的时候做的队列

四、验证程序:

成功

然后发0x55,用逻辑分析仪看看

http://www.lryc.cn/news/626012.html

相关文章:

  • 决策树算法学习总结
  • 【Vivado TCL 教程】从零开始掌握 Xilinx Vivado TCL 脚本编程(三)
  • UML常见图例
  • 一文精通 Swagger 在 .NET 中的全方位配置与应用
  • Java NIO 核心精讲(上):Channel、Buffer、Selector 详解与 ByteBuffer 完全指南
  • 【3-3】流量控制与差错控制
  • Linux资源管理
  • JUC之CompletableFuture【上】
  • Orbbec---setBoolProperty 快捷配置设备行为
  • 设备树下的LED驱动实验
  • 从数据表到退磁:Ansys Maxwell中N48磁体磁化指南
  • 谷歌为什么要将Android的页面大小(Page Size)从传统的4KB升级至16KB
  • Go 进阶学习路线
  • 测试 Next.js 应用:工具与策略
  • 仲裁器设计(三)-- Weighted Round Robin 权重轮询调度
  • ASP4644稳压器的特性分析与系统测试方法研究
  • GPT-4.1旗舰模型:复杂任务的最佳选择及API集成实践
  • 【RustFS干货】RustFS的智能路由算法与其他分布式存储系统(如Ceph)的路由方案相比有哪些独特优势?
  • 2025杭电多校第九场 乘法逆元、阿斯蒂芬、计算几何 个人题解
  • 宿主获取插件View流程原理 - fetchViewByLayoutName
  • LWIP协议栈实现ARP协议
  • Python脚本每天爬取微博热搜-终版
  • Spring Cloud 微服务架构:Eureka 与 ZooKeeper 服务发现原理与实战指南 NO.1
  • Stream API-怎么理解流
  • Day13_【DataFrame数据组合merge连接】【案例】
  • Redis(11)如何通过命令行操作Redis?
  • 反向代理实现服务器联网
  • 人工神经网络MATLAB工具箱指南
  • Selenium自动化测试入门:cookie处理
  • electron进程间通信- 渲染进程与主进程双向通信