串行通信协议小结(Serial Protocols)(1)

2023-05-16

通信关键点

  • 同步通信(例如SPI)-双方之间的数据传输使用公共时钟信号进行同步,数据以稳定的流传输。不需要额外的比特来标记传输的每个数据块的开始/结束,因此速度更快。
  • 异步通信(例如UART)-数据以不规则的间隔传输,设备的内部时钟不同步,但速度(波特)必须事先达成一致。需要额外的比特来标记传输的每个数据块的开始/结束,因此速度较慢。
  • 波特率-线路每秒可以改变状态的最大次数,即多久发一次1或0,常见的有4800、9600、12500。若波特率是9600那么它传输一位0或1的时间就是1/9600秒,理论上波特率越高,出错概率越大。

通信模式-允许双方交换数据的设置。 

  • 单工-只能在一个方向上传输
  • 半双工-一次可以在一个方向上传输,但方向可以来回切换。
  • 全双工-数据可以同时在两个方向上传输。

UART

通用异步收发器(UART)-用于将处理器的并行数据总线转换为串行通信的接口。                      特点

  • 硬件流量控制-检测接收器/传输FIFO上的数据溢出
  • 接收机/发射机握手
  • 传输速率为115 Kbps(标准UART,存在高速变体)

串行字节的解剖-可以使用硬件(例如UART设备)支持的标准(例如RS-232)进行传输:

  • 1个起始位
  • 5-8个数据位
  • 1个奇偶校验位(可选)。

如果1的数量是奇数,则偶数奇偶校验设置该位,否则该位保持为零。如果1的数量是偶数,则奇数奇偶校验设置该位,否则该位保持为零。Received知道您使用的是偶数还是奇数,并进行相应的检查。回调奇偶校验位只能检测奇数个错误,因此多个错误看起来可能是有效数据。

  • 1-2个停止位

示例:8E2表示1个起始位(始终)、8个数据位、偶数奇偶校验位、2个停止位。
示例:7N1表示1个起始位(始终)、7个数据位、无奇偶校验位、1个停止位。

UART通讯使用两根信号线进行数据传输:一根为数据线(TXD),负责发送数据;另一根为接收线(RXD),负责接收数据。发送方需要将发送的数据按照约定的通讯参数进行编码,然后通过TXD线发送出去,接收方则需要通过RXD线接收数据,并将接收到的数据进行解码。通信的过程中,发送方和接收方需要保持相同的波特率、数据位数、停止位数和校验方式等参数,才能正常进行数据传输。

UART通讯的数据传输是异步的,即发送方和接收方没有时钟信号进行同步。因此,在发送数据之前,发送方需要发送一个起始位(Start Bit)来告诉接收方数据的传输开始了;在数据传输完成后,发送方需要发送一个或多个停止位(Stop Bit)来告诉接收方数据的传输已经结束了。停止位的数量可以根据通讯参数进行配置,通常为1或2个。

UART通讯也可以使用校验位来检测数据传输是否出错。校验位是由发送方在数据包中添加的一位或多位数据,用于检测数据传输是否出错。接收方在接收到数据后,会对数据进行校验,并与校验位进行比对。如果接收到的数据与校验位不匹配,则说明数据传输出错,接收方会请求发送方重新发送数据。 总之,UART通讯是一种基于时序的异步串行通讯方式,通讯的双方需要事先约定好通讯参数,包括波特率、数据位数、停止位数和校验方式等。发送方需要将发送的数据按照约定的通讯参数进行编码,然后通过TXD线发送出去,接收方则需要通过RXD线接收数据,并将接收到的数据进行解码。在数据传输过程中,需要发送起始位和停止位来标识数据的开始和结束,也可以使用校验位来检测数据传输是否出错。

软件实现

1.确定通讯参数

        在使用UART通讯前,需要确定通讯参数,包括波特率、数据位数、停止位数和校验方式等。通常情况下,这些参数需要与外设或其他通讯方事先约定好,才能确保通讯的正确性。以STM32为例,可以在代码中通过以下方式配置UART通讯参数:

UART_HandleTypeDef uart;
uart.Instance = USART2;
uart.Init.BaudRate = 115200;
uart.Init.WordLength = UART_WORDLENGTH_8B;
uart.Init.StopBits = UART_STOPBITS_1;
uart.Init.Parity = UART_PARITY_NONE;
uart.Init.Mode = UART_MODE_TX_RX;
uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&uart);

代码中,将波特率设置为115200bps,数据位数设置为8位,停止位数设置为1位,校验方式设置为无校验。

2. 发送数据

       在确定好通讯参数后,可以通过UART发送数据。以STM32为例,可以通过以下方式发送数据:

uint8_t data[] = "Hello, world!";
HAL_UART_Transmit(&uart, data, sizeof(data), 1000);

      这段代码中,将字符串"Hello, world!"发送出去,使用的是HAL库中的HAL_UART_Transmit函数。该函数的第一个参数为UART句柄,第二个参数为发送的数据缓冲区,第三个参数为发送数据的长度,第四个参数为超时时间。

3. 接收数据

接收UART数据的方式与发送类似,也需要使用特定的函数。以STM32为例,可以通过以下方式接收数据:

uint8_t buffer[100];
HAL_UART_Receive(&uart, buffer, sizeof(buffer), 1000);

这段代码中,接收数据的缓冲区为buffer,使用的是HAL库中的HAL_UART_Receive函数。该函数的第一个参数为UART句柄,第二个参数为接收数据的缓冲区,第三个参数为接收数据的长度,第四个参数为超时时间。

4. 其他常用函数

在UART通讯中,还有一些常用的函数,比如清除UART接收缓冲区、获取UART接收缓冲区中的数据长度等。以STM32为例,可以通过以下方式进行操作:

HAL_UART_ClearRxBuffer(&uart);
uint32_t len = __HAL_UART_GET_RX_DATA_LENGTH(&uart);

这段代码中,清除UART接收缓冲区使用的是HAL库中的HAL_UART_ClearRxBuffer函数;获取UART接收缓冲区中的数据长度使用的是HAL库中的__HAL_UART_GET_RX_DATA_LENGTH宏定义。

以上就是UART通讯的基本使用方法。需要注意的是,在使用UART通讯时,需要确保发送方和接收方的通讯参数相同,否则可能会导致数据传输错误。同时,也需要注意数据的编码和解码方式,以确保数据传输的正确性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

串行通信协议小结(Serial Protocols)(1) 的相关文章

  • 我应该使用什么协议来进行快速命令/响应交互?

    我需要建立一个用于快速命令 响应交互的协议 我的直觉告诉我只需将一个简单的协议与 CRLF 分隔的 ascii 字符串拼凑在一起 就像 SMTP 或 POP3 的工作方式一样 如果我需要保护它 则可以通过 SSH SSL 对其进行隧道传输
  • 在类型化数组中存储符合泛型协议的对象

    我有一个协议 protocol Adjustable Equatable associatedtype T var id String get set var value T get set init id String value T 以
  • 在 Python 中循环 Protocol Buffers 属性

    我想要帮助递归地循环协议缓冲区消息中包含的所有属性 子对象 假设我们不知道它们的名称 或者有多少个 作为示例 请从 google 网站上的教程中获取以下 proto 文件 message Person required string nam
  • 什么是 text/ping?这是一个新标准吗?它依赖于浏览器吗?

    我正在对 Google 上的某些问题进行故障排除 并看到从浏览器到 Google 服务器的此请求 它是非阻塞的 这是新事物吗 它的文档在哪里 Chrome 是否不等待响应 Request URL https www google com u
  • Clojure 协议与 Scala 结构类型

    看完后里奇 希基的采访 http www infoq com interviews hickey clojure protocols on 协议 http clojure org protocols在 Clojure 1 2 中 对 Clo
  • shouldStartLoadWithRequest 永远不会被调用

    我研究了又研究 仍然不明白为什么 shouldStartLoadWithRequest 从未被调用 我的页面加载良好 并且调用了一些 UIWebview 委托协议方法 请从下面的我的代码中找到相关片段 在我的 m 中综合我的 webview
  • .Net lib来控制远程GDB [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 Objective-C 中定义协议类别?

    在 Objective C 中 我可以使用类别向现有类添加方法 例如 interface NSString MyCategory BOOL startsWith NSString prefix end 是否也可以使用协议来做到这一点 即如果
  • 使用泛型和协议作为类型参数之间的区别,在函数中实现它们的优缺点是什么

    由于 Swift 允许我们在函数中使用 Protocol 和 Generic 作为参数类型 所以我想到了下面的场景 protocol AProtocol var name String get class ClassA AProtocol
  • 协议与自身的行为

    我最近在读Swift 中的协议 通用类型约束和数组 http letvargo mooo com protocols generic type constraints and arrays in swift 我的问题涉及博客中的以下两个示例
  • 无状态协议是否比有状态协议更适合使用?

    我可以看到 有状态的协议可以减少像 cookie 这样的 模拟状态 但是测试变得更加困难 以确保您的实现正确并重新连接 并且会话继续可能很难处理 始终使用无状态协议是否被认为是更好的做法 或者它确实是特定于领域的 我认为在处理有状态协议时身
  • 旨在打开资源管理器的自定义 URI 协议

    我们有一个为 google chrome 设计的应用程序 我们需要在其中添加网络文件共享的链接 不幸的是 Chrome 否认file protocol出于安全目的 我们想要设置一个自定义协议来允许此功能 我认为做到这一点的一个好方法是调用资
  • 移动提供商无法进行 UDP 打洞

    实际上 我正在编写一个 Android 应用程序 该应用程序接收连接到 PC 的网络摄像头的图片 为了获得更多的 fps 我使用 udp 协议而不是 tcp 这个想法是 电脑将图片发送到手机的 IP 和端口 但电话提供商有不同的公共端口 所
  • 种子中的 DHT

    我正在编写一个 P2P 实现 我希望将其去中心化 然而我在掌握如何做时遇到了一些困难DHT https en wikipedia org wiki Distributed hash table在像 BitTorrent 这样的协议中是有效的
  • 如何遵守自制协议?

    我有一个带有委托属性的类 任何想成为代表的人都必须遵守协议 我这样定义一切 import
  • 在 Objective-c 问题中访问委托静态方法

    我在 Objective c 中遇到了一个奇怪的问题 这是代码 STViewController h import
  • Swift Struct 不符合 Equatable 协议?

    如何使结构符合 Equatable 协议 我正在使用 Xcode 7 3 1 struct MyStruct var id Int var value String init id Int value String self id id s
  • iOS-示例中的协议和委托

    好吧 我正在寻找 但没有任何方法对我有用 以下代码基于许多教程和苹果文档 但我无法让它工作 有人可以帮忙吗 代码崩溃于 obj delegatee self 在 B h 类中 respondsToSelector 和 PerformSele
  • 如何区分类实现中两个协议的相同方法名称?

    我有两个协议 protocol P1 void printP1 void printCommon end protocol P2 void printP2 void printCommon end 现在 我在一个类中实现这两个协议 inte
  • 如何声明具有类型并实现协议的变量?

    我的应用程序有一个详细视图控制器协议 声明它们必须有一个viewModel财产 protocol DetailViewController class var viewModel ViewModel get set 我还有一些实现该协议的不

随机推荐