活动介绍
file-type

如何通过字节存储实现四个字节整数的串口传输

RAR文件

下载需积分: 9 | 4KB | 更新于2025-05-10 | 81 浏览量 | 13 下载量 举报 收藏
download 立即下载
在计算机编程中,整数的存储是基础且重要的知识点。整数可以是任意大小的数值,而它们在内存中以二进制的形式存储。当需要通过串口或socket控件进行数据传输时,整数必须被分解成字节序列,这样才能在设备之间进行有效的数据交换。 首先,我们需要明确什么是字节。字节(Byte)是计算机存储和处理数据的基本单位之一。一个字节由八个比特(bit)组成,每个比特是0或1的二进制数字。在大多数现代计算机体系结构中,一个字节可以表示的整数值范围是0到255(8位二进制数)。 串口(Serial Port),是指计算机上用来进行串行通信的接口。在串行通信中,数据是一位接一位地顺序发送和接收的。由于串口通信涉及字节的发送和接收,因此需要了解如何将整数转换为字节序列,以及如何将这些字节序列组合回整数。 接下来,以一个四字节整数为例,来说明如何存储和转换。在计算机中,整数可以按照字节序(Byte Order)存储,主要有两种字节序:大端字节序(Big-endian)和小端字节序(Little-endian)。 大端字节序意味着数据的高位字节存储在内存的低地址处,而小端字节序则是将数据的低位字节存储在低地址处。不同的系统平台可能采用不同的字节序,因此在进行字节操作时要特别注意字节序的一致性。 以一个32位(四字节)整数为例,其值为16777216,二进制表示为0x01000000。若系统采用大端字节序,则其字节序列的排列为: - 第一个字节:0x01 - 第二个字节:0x00 - 第三个字节:0x00 - 第四个字节:0x00 若系统采用小端字节序,则字节序列的排列为: - 第一个字节:0x00 - 第二个字节:0x00 - 第三个字节:0x00 - 第四个字节:0x01 了解了这些基础知识后,我们可以探讨如何在编程中实现整数到字节序列的转换,以及反向操作。 以C语言为例,可以使用类型转换和指针操作来实现: ```c #include <stdint.h> uint32_t num = 16777216; // 32位整数 uint8_t bytes[4]; // 字节数组用于存储字节序列 // 将整数转换为字节序列 bytes[0] = (num >> 24) & 0xFF; bytes[1] = (num >> 16) & 0xFF; bytes[2] = (num >> 8) & 0xFF; bytes[3] = num & 0xFF; // 假设通过socket发送这些字节 // ... // 接收完毕,现在需要将这些字节转换回整数 uint32_t received_num = 0; received_num = bytes[0]; received_num = (received_num << 8) | bytes[1]; received_num = (received_num << 8) | bytes[2]; received_num = (received_num << 8) | bytes[3]; ``` 在这个例子中,通过位移和按位或操作将整数分解成字节序列,再通过位移和按位或操作将字节序列重新组合成整数。需要注意的是,在发送和接收字节时,发送端和接收端的字节序需要保持一致,否则会导致数据解析错误。 除了C语言,其他高级语言如Python、Java等也都提供了相应的API或类库来处理整数和字节序列之间的转换。 在实际开发中,还可能遇到字节序转换问题,即当发送方和接收方使用不同字节序时,需要在传输前将数据转换为网络字节序(一般为大端字节序),在接收后根据需要转换回主机字节序。 总结以上知识点,我们可以看出整数在计算机中的存储,尤其是通过串口或socket控件进行传输时,涉及到字节序、类型转换和位操作等重要概念。理解并能够正确运用这些知识是进行有效数据通信的关键。

相关推荐

filetype

STM32专栏收录该内容18 篇文章订阅专栏 DHT11是一款数字温湿度传感器,适用于环境监测。它采用单总线协议,能同时测量温度和湿度,适用于5V电源,具有简单的接线和低功耗特性。传感器内置8位单片机,数据传输包括湿度和温度的整数及小数部分,以及校验和,确保数据准确性。操作时序严格,需要精确的时序控制来读取数据。51和STM32的例程展示了如何与DHT11通信,实现数据的读取和处理。摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >展开 DHT11文章目录DHT11DHT11一、DHT11基础储备二、接口说明1. 接线图2. 电源引脚3. 串行接口(单线双向)三、协议及数据格式四、操作时序4.1 主机发送复位信号4.2 DHT11 发送响应信号4.3 数据传输4.4 区分数据0/1的巧法五、51及STM32例程5.1 51对应的dht11.h5.2 STM32对应的dht11.hdht11.cmain.c实物图百度网盘资源DHT11导读:DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。一、DHT11基础储备DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,内部由一个 8 位单片机控制一个电阻式感湿元件和一个 NTC 测温元件。DHT11 虽然也是采用单总线协议,但是该协议与 DS18B20 的单总线协议稍微有些不同之处。相比于 DS18B20 只能测量温度,DHT11 既能检测温度又能检测湿度,不过 DHT11 的精度和测量范围都要低于 DS18B20,其温度测量范围为 0~50℃,误差在±2℃;湿度的测量范围为 20%~90%RH(Relative Humidity 相对湿度—指空气中水汽压与饱和水汽压的百分比),误差在±5%RH。DHT11 电路很简单,只需要将 DATA 引脚连接单片机的一个 I/O 即可,不过该引脚需要上拉一个 5K 的电阻,DHT11 的供电电压为 3~5.5V。二、接口说明1. 接线图DHT11引脚说明Pin 名称 注释1 VDD 供电 3-5.5V2 GND 接地,电源负极3 DATA 串行数据,单总线4 NC 空脚,请悬空2. 电源引脚DHT11的供电电压为3~5.5 V。传感器上电后,要等待 1s 以越过不稳定状态,在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。3. 串行接口(单线双向)DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分三、协议及数据格式DHT11 采用单总线协议与单片机通信,单片机发送一次复位信号后,DHT11 从低功耗模式转换到高速模式,等待主机复位结束后,DHT11 发送响应信号,并拉高总线准备传输数据。一次完整的数据为 40bit,按照高位在前,低位在后的顺序传输。数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。由于 DHT11 分辨率只能精确到个位,所以小数部分是数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。注意:由于 DHT11 时序要求非常严格,所以在操作时序的时候,为了防止中断干扰总线时序,先关闭总中断,操作完毕后再打开总中断。四、操作时序4.1 主机发送复位信号DHT11 的初始化过程同样分为复位信号和响应信号。

filetype

uint8_t USARTx_Receive_DMA_Buffer[50] = {0}; // 用于储存串口DMA接收的数据 uint8_t USARTx_Processing_Buffer[49] = {0}; // 串口接收到的数组缓冲区 uint8_t FDCANx_Receive_Buffer[64]; // CAN直接写入的缓冲区 uint8_t FDCANx_Processing_Buffer[5][57]; // CAN直接写入的缓冲区 uint8_t Receive_Count = 0; // 储存接收次数 uint8_t USARTx_Transmit_DMA_Buffer[340] = {0}; // 串口发送数据缓冲区 FDCAN_RxHeaderTypeDef RxHeader; //储存FDCAN接收配置 FDCAN_FilterTypeDef CanRxFilterConfig; // 储存FDCAN滤波器配置 volatile bool isTransmitting = false; // 发送状态标志 uint8_t pcf8574_state = 0xBF; // PCF8574初始状态(0xBF = 10111111b) uint8_t tempRawCanData[5][252]; // 临时存储原始CAN数据(每包252字节)void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) // 如果是FIFO新消息中断 { HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, FDCANx_Receive_Buffer); // 读取数据 if (RxHeader.DataLength != FDCAN_DLC_BYTES_64) return; switch (FDCANx_Receive_Buffer[0]) { case 0x00: memcpy(&tempRawCanData[Receive_Count][0], &FDCANx_Receive_Buffer[1], 63); break; case 0x01: memcpy(&tempRawCanData[Receive_Count][63], &FDCANx_Receive_Buffer[1], 63); break; case 0x02: memcpy(&tempRawCanData[Receive_Count][126], &FDCANx_Receive_Buffer[1], 63); break; case 0x03: memcpy(&tempRawCanData[Receive_Count][189], &FDCANx_Receive_Buffer[1], 63); // 确保有足够的空间存储处理后的数据 if (Receive_Count < 5) { uint8_t *src = tempRawCanData[Receive_Count]; uint8_t *dst = FDCANx_Processing_Buffer[Receive_Count]; // 提取有效数据 (1+4+4+48 = 57字节) dst[0] = src[1]; // SF memcpy(&dst[1], &src[2], 4); // ST memcpy(&dst[5], &src[11], 4); // NOST memcpy(&dst[9], &src[77], 48); // 12类传感器数据 } Receive_Count++; if (Receive_Count >= 5) // 收到5包CANFD数据 { Receive_Count = 0; // uint16_t packet_index = 0; // 1. 帧头 (2字节) USARTx_Transmit_DMA_Buffer[packet_index++] = 0xAA; USARTx_Transmit_DMA_Buffer[packet_index++] = 0x55; // 2. 数据长度 (2字节) - 333 = 0x014D USARTx_Transmit_DMA_Buffer[packet_index++] = 0x4D; // 低字节 USARTx_Transmit_DMA_Buffer[packet_index++] = 0x01; // 高字节 // 3.组合数据: 主惯导(47字节) - 从USART1数据中复制有效部分 memcpy(&USARTx_Transmit_DMA_Buffer[packet_index], &USARTx_Processing_Buffer[2], 47); packet_index += 47; // 4. 5组子惯导数据 (5*57=285字节) for (int i = 0; i < 5; i++) { if (i < 5) { // 安全检查 memcpy(&USARTx_Transmit_DMA_Buffer[packet_index], FDCANx_Processing_Buffer[i], 57); packet_index += 57; } } // 5. 计算校验和 (从数据长度开始到子惯导数据结束) uint8_t totalChecksum = 0; for (int i = 4; i < packet_index; i++) { // 从数据长度后的第一个字节开始 totalChecksum += USARTx_Transmit_DMA_Buffer[i]; } USARTx_Transmit_DMA_Buffer[packet_index++] = totalChecksum; // 总包长度: 2(帧头) + 2(数据长度) + 47(主惯导) + 285(子惯导) + 1(校验和) = 337字节 // 6. 发送337字节协议包 if (!isTransmitting) { isTransmitting = true; HAL_UART_Transmit_DMA(&huart2, USARTx_Transmit_DMA_Buffer, 337); // 发送数据 } } break; } HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); //重新开始接收 }这是函数主要处理过程,有没有什么问题,为什么接受的数据并不总是337个字节

walkalone_bj
  • 粉丝: 12
上传资源 快速赚钱