RM机器人开发之C语言(二)

网友投稿 2018-03-11 15:40

各位大佬,还记得上周的那几个关键字么?其实,受性能限制,这里的内容在使用8051内核的MCU中用到的较少,而在对16/32位MCU编程时用到的较多。所以对于正在学习的8051MCU的同学来说,这些内容作为认知,看到知道它是什么意思即可。

先来回答上篇留下的结构体储存时的对齐问题。这里我用两个问题来引导。

1,结构体存储为什么要对齐?

Answer:对齐的形式更加有利于计算机进行快速的处理,在可接受的空间浪费的前提下,对齐使计算机处理需要的的时间尽可能的少。

2,结构体是如何对齐的?

Answer:这个问题其实解释起来是比较复杂(对于我而言),而且在不容的平台结果可能不一样。可以参阅博主“tsw123”的解释文章“解析C语言结构体对齐(内存对齐问题)”(阅读原文即可查看)。然后,下面这个结构体就好解释了。首先它的成员中最大字长是4,这样这个结构体占用的字节数将为4的倍数。然后a占用4字节,b[0],b[1]占用4字节,下面重点来了,b[2],c占用4字节,其中,前三个字节是真实数据,最后一个字节是无效数据。我能解释的,只有这么多了。

https://cdn.china-scratch.com/timg/180313/1540405136-0.jpg

3,结构体何时才会考虑对齐问题?

Answer:拿正点原子的一个例子来说,在使用电阻屏时,计算触摸点需要记录四个参数xy方向的零点偏移,电阻率,它使用了一个结构体,专门保存触摸屏的函数、标志位、触摸点计算数据等等数据,这些数据是需要部分保存的EEPORM中的,上电时读取出来。这个时候就要考虑你的结构体占用多大空间。需要从基地址读取多少字节数据。

结构体struct:

https://cdn.china-scratch.com/timg/180313/1540402591-1.jpg

https://cdn.china-scratch.com/timg/180313/1540406246-2.jpg

结构体较多的用在库函数中,当我们初始化MCU的外设时,就是使用结构体将参数赋给结构体成员,然后调用初始化函数将数据写到寄存器。以上面的结构体为例。这里后面的GPIO_InitTypedef就是一个结构体类型,定义结构体时直接使用GPIO_InitTypedef GPIO_Init_Structure 后面的GPIO_Init_Structure就是我新定义的一个结构体,给它的成员赋值,然后就可以初始化对应的外设,如上图的操作,就可以初始化GPIOB的Pin5 。上面文字得条理看起来的可能不是很清晰,你就可以理解为GPIO_InitTypedef相当于我们常用的 int  。GPIO_Init_Structure 就相当于我们定义的一个int型变量a。而a有int类型的特征,所以a也是一个结构体,它有三个成员。

枚举enum:

https://cdn.china-scratch.com/timg/180313/1540405304-3.jpg

当大家看到上面的结构体可能看起来有些疑惑,明明是赋值,可是没看到一个数字,都是一串没见过的字符。那么请看结构体的第一个图,结构体成员的GPIO_Mode的类型是GPIOMode_TypeDef,这里的GPIOMode_TypeDef就是一个枚举型。枚举型规定,GPIO_Mode所给的值必须是上图中枚举型成员中有的,可以赋值GPIO_Mode_Out_PP,也可以赋值0x18。但是更好的方法是赋值GPIO_Mode_Out_PP,因为通过这个枚举型可以看出这里的配置成为推挽输出。而一个0x18,复查程序时,你又不知道这是哪一个配置了。同时使用枚举型又可以避免出错,因为赋给枚举型变量的值如果不是枚举成员,编译就不会通过。

联合体union:

联合体成员列表里的成员共用相同的内存空间,而不像struct结构体那样按顺序排列占用不同的内存空间。联合体用到的相当少,目前只在stdio.h中见过,所以不必深究。

断言assert:

https://cdn.china-scratch.com/timg/180313/1540404404-4.jpg

这里的断言,可以认为他是一个安全检测;assert_param(duty<="" p="">

程序中常用的代码剪裁,功能限定:

https://cdn.china-scratch.com/timg/180313/1540401138-5.jpg

在早期的库函数的conf.h和map.h中往往会有这样的代码,这是什么意思呢?这里是用作代码剪裁,或者屏蔽掉部分外设的库函数。就是说,我把_ADC3这个宏注释掉,下面的条件编译就不能通过,那么库函数中就不能使用ADC3的所有相关。一旦出现ADC3相关就会出现未定义的Error。在可剪裁的RTOS中,也会经常使用这种宏定义的方式来控制功能是否启用。

写在最后:多学无害,技多不压身。

--end--

声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com