union和struct存放格式

union、struct所占的空间大小; union: ​ 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 联合体是一个结构; 它的所有成员相对于基地址的偏移量都为0; 此结构空间要大到足够容纳最”宽”的成员; 其对齐方式要适合其中所有的成员; ​ 下面解释这四条描述: 由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式。 例如: #include using namespace std; union A{ int a[5]; char b; double c; }; int main(){ cout **a** **b** **b** **b** **b** **c** **c** ```c++ //例如: struct B { char a; short b; int c; } //则sizeof(A)大小应该是4+4=8字节 a c c b b b b //例如: struct B { char a; char b[2]; char c[4]; } //则sizeof(A)大小应该是1+2+4=7字节 a b b c c c c ...

May 6, 2022 · 2 min · Rancho

常用脚本汇总

图片PNG文件转JPG文件; 使用方法:将该脚本放置于png文件所在的文件夹中,然后运行该脚本,即可将png文件转化为jpg文件,并放置于JPG文件夹下; import os from PIL import Image dirname_read = "./" # 源文件文件夹 dirname_write = "./JPG/" # 目标文件文件夹 names = os.listdir(dirname_read) count = 0 for name in names: portion = os.path.splitext(name) # 分离文件名和扩展名 if portion[1] == ".png": # 判断扩展名是否为png img = Image.open(dirname_read+name) # 打开该文件 name = portion[0] + ".jpg" # 重命名文件 to_save_path = dirname_write + name # 设置保存路径 img = img.convert('RGB') # RGBA意思是红色,绿色,蓝色,Alpha指透明度。而JPG不支持透明度,所以要么丢弃Alpha,要么保存为.png文件 img.save(to_save_path, quality=95) # 保存 count += 1 # 计数加一 print(to_save_path, "------conut:", count) # 输出信息 else: continue print("Count_Sum:", count) # 输出总数

April 22, 2022 · 1 min · Rancho

PID中积分饱和及其解决办法

PID控制中常出现的积分饱和概念及其解决方案; 积分饱和的概念: 这种现象往往发生在误差有大幅变化(例如大幅增加),积分器因为误差的大幅增加有很大的累计量,因为积分器的输出满足下式: 离散化形式表示为: 所以随着时间的增加,每次累积较大的误差,很容易造成积分饱和并产生较大的过冲,而且当误差变为负时,其过冲仍维持一段时间之后才恢复正常的情形。 通常会产生的输出如下图所示: 从图中我们不难发现,这里有三个过程: 因为这个过程存在 较大幅度变化的误差,因此积分器累积了较大的值,从图中可以看到,积分器的面积比较大(阴影部分); 此时积分已经饱和,产生了较大的过冲,并且在较长的一段时间内,一直处于过冲的状态; 积分脱离饱和状态,产生了积极的调节作用,消除静差,系统输出达到设定值; 如何防止积分饱和: 为了防止PID控制器出现积分饱和,需要在算法加入抗积分饱和(anti-integral windup)的算法;通常有以下几种措施; 积分分离或者称为去积分算法; 在饱和的时候将积分器的累计值初始化到一个比较理想的值; 若积分饱和因为目标值突然变化而产生,将目标值以适当斜率的斜坡变化可避免此情形; 将积分累计量限制上下限,避免积分累计量超过限制值; 如果 PID输出已经饱和,则重新计算积分累计量,使输出恰好为合理的范围; 参考: 1、一文详细解析到底什么是积分饱和;

March 10, 2022 · 1 min · Rancho

Jlink使用RTT输出调试信息(代替串口打印)

Jlink RTT调试技巧; 使用Jlink的 RTT功能 : 这个功能是不需要另外接其他引脚的,如果使用SW连接方式,仅仅两根线就可以。 RTT 是Jlink的一种实时终端的方式连接输出调试信息,网上有很多说明之间按照做就可以,我仅仅是记录一下自己的步骤. 就是下载RTT软件包,下载RTT文件: http://download.segger.com/J-Link/RTT/RTT_Implementation_140925.zip ; 添加RTT文件到自己的工程: 添加必要的头文件: 输出函数打印: 这个时候RTT在程序中就添加成功了,我们可以使用使用Jlink带的工具进行查看数据; 如打开RTT Viewer 提升连接,点击OK 不出意外的话,你就可以看到调试信息了;

February 15, 2022 · 1 min · Rancho

markdown绘制简单流程图

Markdown绘制简单流程图; Typora流程图: mermaid效果(这个可以在Typora编辑器中显示,博客中渲染失败) 输入```,然后输入mermaid即可 ·mermaid graph TD B((开始)) -->C{判断} C -- a=1 -->D[执行语句1] C -- a=2 -->E[执行语句2] C -- a=3 -->F[执行语句3] C -- a=4 -->G[执行语句4] D--> AA((结束)) E--> AA F--> AA G--> AA 如下图: 语法: 官网说明文档 Mermaid . flowchar效果(只有这个可以在博客中显示流程图) ···flow st=>start: 开始节点 in=>inputoutput: 输入 e=>end: 结束节点 op=>operation: 操作节点 cond=>condition: 条件节点 sub=>subroutine: 子例程 out=>inputoutput: 输出 st(right)->in->op->cond cond(yes,right)->out->e cond(no)->sub 实际例子1: ···flow st=>start: Start i=>inputoutput: 输入年份n cond1=>condition: n能否被4整除? cond2=>condition: n能否被100整除? cond3=>condition: n能否被400整除? o1=>inputoutput: 输出非闰年 o2=>inputoutput: 输出非闰年 o3=>inputoutput: 输出闰年 o4=>inputoutput: 输出闰年 e=>end st->i->cond1 cond1(no)->o1->e cond1(yes)->cond2 cond2(no)->o3->e cond2(yes)->cond3 cond3(yes)->o2->e cond3(no)->o4->e 实际例子2: ...

February 7, 2022 · 2 min · Rancho

LCD显示太空人画面

LCD 显示太空人动画; 这个比较简单,就是把连续的画面播放起来就行;

January 24, 2022 · 1 min · Rancho

自制Jlink-OB(带串口)

自制Jlink-ob(带串口);

January 23, 2022 · 1 min · Rancho

CRC校验原理

之前经常用CRC校验,今天解释一下其原理; 简单介绍: Cyclic Redundancy Check循环冗余检验,是基于数据计算一组效验码,用于核对数据传输过程中是否被更改或传输错误。 循环冗余校验检错方案(CRC): CRC校验原理看起来比较复杂,好难懂,因为大多数书上基本上是以二进制的多项式形式来说明的。其实很简单的问题,其根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它 要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。 【说明】:“模2除法”与“算术除法”类似,但它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可。模2加法运算为:1+1=0,0+1=1,0+0=0,无进位,也无借位;模2减法6运算为:1-1=0,0-1=1,1-0=1,0-0=0,也无进位,无借位。相当于二进制中的逻辑异或运算。也就是比较后,两者对应位相同则结果为“0”,不同则结果为“1”。如100101除以1110,结果得到商为11,余数为1,如图5-9左图所示。如11×11=101,如右图所示。 “模2除法”和“模2乘法”示例 具体来说,CRC校验原理就是以下几个步骤: 先选择(可以随机选择,也可按标准选择,具体在后面介绍)一个用于在接收端进行校验时,对接收的帧进行除法运算的除数(是二进制比较特串,通常是以多项方式表示,所以CRC又称多项式编码方法,这个多项式也称之为“生成多项式”)。 看所选定的除数二进制位数(假设为k位),然后在要发送的数据帧(假设为m位)后面加上k-1位“0”,然后以这个加了k-1个“0“的新帧(一共是m+k-1位)以“模2除法”方式除以上面这个除数,所得到的余数(也是二进制的比特串)就是该帧的CRC校验码,也称之为FCS(帧校验序列)。但要注意的是,余数的位数一定要是比除数位数只能少一位,哪怕前面位是0,甚至是全为0(附带好整除时)也都不能省略。 再把这个校验码附加在原数据帧(就是m位的帧,注意不是在后面形成的m+k-1位的帧)后面,构建一个新帧发送到接收端;最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数,如果没有余数,则表明该帧在传输过程中没出错,否则出现了差错。 通过以上介绍,大家一定可以理解CRC校验的原理,并且不再认为很复杂吧。 从上面可以看出,CRC校验中有两个关键点:一是要预先确定一个发送端和接收端都用来作为除数的二进制比特串(或多项式);二是把原始帧与上面选定的除进行二进制除法运算,计算出FCS。前者可以随机选择,也可按国际上通行的标准选择,但最高位和最低位必须均为“1”,如在IBM的SDLC(同步数据链路控制)规程中使用的CRC-16(也就是这个除数一共是17位)生成多项式g(x)= x^16 + x^15 + x^2 +1(对应二进制比特串为:11000000000000101);而在ISO HDLC(高级数据链路控制)规程、ITU的SDLC、X.25、V.34、V.41、V.42等中使用CCITT-16生成多项式g(x)= x^16+ x^15 + x^5 +1(对应二进制比特串为:11000000000100001)。 CRC校验码的计算示例 由以上分析可知,既然除数是随机,或者按标准选定的,所以CRC校验的关键是如何求出余数,也就是校验码(CRC校验码)。下面以一个例子来具体说明整个过程。现假设选择的CRC生成多项式为G(X) = X^4 + X^3 + 1,要求出二进制序列10110011的CRC校验码。下面是具体的计算过程: 首先把生成多项式转换成二进制数,由G(X) = X^4+ X^3 + 1可以知道,它一共是5位(总位数等于最高位的幂次加1,即4+1=5),然后根据多项式各项的含义(多项式只列出二进制值为1的位,也就是这个二进制的第4位、第3位、第0位的二进制均为1,其它位均为0)很快就可得到它的二进制比特串为11001。 因为生成多项式的位数为5,根据前面的介绍,得知CRC校验码的位数为4(校验码的位数比生成多项式的位数少1)。因为原数据帧10110011,在它后面再加4个0,得到101100110000,然后把这个数以“模2除法”方式除以生成多项式,得到的余数(即CRC码)为0100,如图所示。注意参考前面介绍的“模2除法”运算法则。 CRC校验码计算示例 把上步计算得到的CRC校验0100替换原始帧101100110000后面的四个“0”,得到新帧101100110100。再把这个新帧发送到接收端。 当以上新帧到达接收端后,接收端会把这个新帧再用上面选定的除数11001以“模2除法”方式去除,验证余数是否为0,如果为0,则证明该帧数据在传输过程中没有出现差错,否则出现了差错。 通过以上CRC校验原理的剖析和CRC校验码的计算示例的介绍,大家应该对这种看似很复杂的CRC校验原理和计算方法应该比较清楚了。 算法原理: 假设数据传输过程中需要发送15位的二进制信息g=101001110100001,这串二进制码可表示为代数多项式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5+ 1,其中g中第k位的值,对应g(x)中x^k 的系数。将g(x)乘以x^m,既将g后加m个0,然后除以m阶多项式h(x),得到的(m-1)阶余项r(x)对应的二进制码r就是CRC编码。 h(x)可以自由选择或者使用国际通行标准,一般按照h(x)的阶数m,将CRC算法称为CRC-m,比如CRC-32、CRC-64等。国际通行标准可以参看标准; g(x)和h(x)的除运算,可以通过g和h做xor(异或)运算。比如将11001与10101做xor运算: 明白了xor运算法则后,举一个例子使用CRC-8算法求101001110100001的效验码。CRC-8标准的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1,既h是9位的二进制串111010101。 ...

January 8, 2022 · 2 min · Rancho

LVGL开发

最近要做一个GUI界面,自己开发各种功能是极其麻烦的(对的,我之前是做过的),需要注意很多问题,而且开发起来很多功能基本上是实现不了的,所以只能想其他办法了,因为之前用LVGL做过一个很简单的GUI界面,所以这次也打算用LVGL来做,也算是再复习一下这个界面的使用。 以下是关于LVGL的简介以及特点: LVGL(Light and Versatile Graphics Library,轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。 LVGL主要特性 功能强大的构建块,例如按钮,图表,列表,滑块,图像等. 带有动画,抗锯齿,不透明,平滑滚动的高级图形. 各种输入设备,例如触摸板,鼠标,键盘,编码器等. 支持UTF-8编码的多语言. 多显示器支持,如TFT,单色显示器. 完全可定制的图形元素. 独立于任何微控制器或显示器使用的硬件. 可扩展以使用很少的内存(64 kB闪存,16 kB RAM)进行操作. 操作系统,支持外部存储器和GPU,但不是必需的. 单帧缓冲区操作,即使具有高级图形效果. 用C语言编写,以实现最大的兼容性(与C ++兼容). 模拟器可在没有嵌入式硬件的PC上进行嵌入式GUI设计. 可移植到MicroPython. 可快速上手的教程、示例、主题. 丰富的文档教程. 在MIT许可下免费和开源. LVGL硬件要求 基本上,每个现代控制器(肯定必须要能够驱动显示器)都适合运行LVGL。LVGL的最低运行要求很低: 16、32或64位微控制器或处理器. 最低 16 MHz 时钟频率. Flash/ROM::对于非常重要的组件要求 >64 kB(建议 > 180 kB). RAM 静态 RAM 使用量:~2 kB,取决于所使用的功能和对象类型. 堆栈: > 2kB(建议 > 8 kB). 动态数据(堆):> 2 KB(如果使用多个对象,则建议 > 16 kB)。由 lv_conf.h 中的 LV_MEM_SIZE 宏进行设置. 显示缓冲区:> “水平分辨率”像素(建议 > 10× “水平分辨率” ). MCU 或外部显示控制器中的一帧缓冲区. ...

January 3, 2022 · 1 min · Rancho

小一升级版来了!

小一升级版;

December 22, 2021 · 1 min · Rancho