为什么数组这么好用?(以串口上下位机协议)

乐活   2025-01-24 11:14   内蒙古  

前几天给人讲课,讲到了这个数组,然后有了更加深刻的理解。我觉得从物理和数据的组织方式上面入手是好的。

先说物理上面是怎么样的。我们先想想,假如让你设计,你咋搞?

肯定是先设计一些基本的数据单元,就好像一个1CM的小格子一样。这么多的小格子怎么放呢?

可以变成一个长条形,但是延伸到很远也不现实,那我们就在平面上面扩展,也就是表,矩阵这种的感觉。

SO?我们要考虑操作,无非就是读写,但是这是高层的操作。具体一点呢?你要指定对什么位置的数据做处理,我们很自然的使用坐标系来做定位。但是一层也不够,那就再叠起来,叠的多了就好像是书本一样,我们称这样的东西叫页。叠的页多了,我们就可以称为块(Bank)

就是上面看见的黑块子

Channel > DIMM > Rank -> Chip -> Bank -> Row/Col

当然了可以看到更加高层管理芯片,DIMM,多个内存条又叫通道。

这个是管理的结构

看一个三星的片子

这个是Bank的黑片子,里面的红色是地址

每个小块的连接

再看一个

所有文章都会抄的图

https://www.mouser.sg/pdfdocs/8GBAS4C512M16D3L.PDF

在这里

前面最重要的就是地址的管理,一个管理行,一个管理列,使用了16bit的位宽来指定地址。

上面的数据是这个内存单体的大小

说了这么多,就是想告诉你,在内存里面,也是行列管理内存单元的。每次操作都是要先知道地址在哪里,然后再这块地址上面做什么操作。

所以也引出来了和这种物理结构最像的数据结构-数组,一段相同变量放在一起,在内存上面是连续的。

它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。

我们也可以叫:线性表其顺序表示称为顺序存储结构或顺序映像,把逻辑上相邻的数据元素存储在物理上相邻的存储单元中,即逻辑上相邻,物理上也相邻。
顺序存储是用一组地址连续的存储单元依次存储线性表的元素。数组占据内存中连续的存储区域这样一个性质。

我们也可以使用上面的性质来使用指针操作,数组是一种引用类型数据,存放在内存中。

数组在内存中开辟是线性连续且递增的

指针和数组的纠缠 可以看这个。

C语言编译器要求在编译期间就需要确定数组的内存大小。

在c语言中,任何变量(基本变量,指针变量,结构体变量,数组变量)的空间都是整体开辟,但任何元素的起始地址一定是开辟字节当中最小的。


有两个核心指标,一个是索引,一个是值,前面来定位,后面来存放值。

也可以把它竖起来

数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:数组名[元素索引值].

至于初始化,我们要知道,基本的元素类型是什么?有多少。把握这两个,上面的初始化就很简单。不指定就直接数,如果数和个数不对,那就是补全0.

  1. 定义格式:元素类型 数组名[m][n],可以理解为m行n列的矩阵。

  2. 列数n必须给出,行数m可以由编译器数出。

  3. 每行一个大括号 {} ,用逗号分隔。也可以没有大括号按序排列。

  4. 如果省略则表示补零,也可以用定位初始化。

二维数组在内存里面也是连续的

看这个排列

元素之间是互相连续的,行与行之间是连续的。

初始化就是这样的

数组就是这样,有数组名,然后就是一行对应一列。

第一层是先进去读取二维数组的第一行,其实就是做定位。

第二层是对这一行的每一个元素做处理。做完以后,继续第一层转到下一行。

循环就是为了定位位置,所以说是元素级别的操作。

这个是定位的情况,先看行,再看列

看这个,规模是35

行是5,列是7

我什么写这个?因为在嵌入式系统里面,串口是一个常用的接口,我们除了知道这个物理电气,还要知道真正的数据层是如何定义的。

一般会这样设计,头尾+负载

正好我们可以搞一个数组把里面内容存好,串口的可以使用字节传输,所以这些都可以定义成几个字节的协议帧。

我们可以使用这三种方式来读取数据有没有来,就是在MCU上面执行这个代码。

数据来了,为了平衡这个数据流的速度不匹配,加了缓冲区,其实就是一个没有被使用的数组,装进去慢慢的处理:

我们把数组的数据给处理函数

  1. 根据协议解析接收到的数据包,提取命令字和数据内容。

  2. 校验数据的完整性(如通过校验和验证)。
  3. 执行相应的操作,例如控制外设、返回状态。
因为我们知道对应的位置上面是什么数据,又知道单个字长。

首先就是通过索引获得对应位置上面的数据,直接做判断。

使用了连续的增长,依次读取。
在校验码通过的情况下,开始处理里面的参数。

在MCU发送的时候,也是这样的,先把前面的标志设计好,然后把数据的长度作为一个变量,因为我们的数据帧是不固定的。
所以在内存里面,把data复制到缓存区,长度是三个字节。接着算校验码,算好继续存到缓冲区,因为是不停的增长的。接着就通过硬件发送出去。

如果我们上位机发送给下位机的时候,也是需要这样编码的

这个打包函数,就是使用了字节数组,然后就是一个字节一个字节的去打包。搞好以后返回。

发送简单

上位机也会解读来自下位机的数据帧。

Python搞这个太舒服了,无脑解读。

当然了,也会使用更近一步的接收函数

我们也要加入交互!

直接建立连接

下面就是一个死循环,现打印操作要求,后面就是执行对应的命令。

发完以后就等着

有一个叫BOSE-055的芯片

看看大厂是这么个做法

先是头,后是操作,地址,长度,数据

具体的例子

所以计算机最中最重要的是-字节!

一个字节由 8 位(bit)组成,是计算机中最小的可寻址存储单元。
位(bit)是信息的最小单位,但它只能表示两个状态(0 或 1)。
字节可以表示 28=2562^8 = 25628=256 个不同的状态,足以表示字母、数字或其他符号。无论是内存还是硬盘,数据都是按字节存储和处理的。
计算机的寄存器通常设计为 8 位、16 位、32 位或 64 位,这些都是字节的倍数。CPU 从内存中读取数据时,按字节寻址,而不是按位。为提高存储和访问效率,硬件和编译器通常要求数据按字节对齐。
https://blog.51cto.com/panyujie/3222542

云深之无迹
纵是相见,亦如不见,潇湘泪雨,执念何苦。
 最新文章