指针和内存对齐在通信中的问题

相关概念:

大端模式:数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中,这种存储模式就类似把数据当做字符串顺序处理,例如:数据中两个字节按顺序为:FE 10 ,它表示的一个数就是0xFE10。
换句话说:内存的低地址存放着数据高位;

小端模式:数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储方式就是将地址的高低和数据的位结合起来,前面的例子按照小端模式表示,应该为:0x10FE。
换句话说:内存的低地址存放着数据低位。 

使用背景:

通信中数据是以字节形式传递的,而单片机中的数据种类有很多,char、int、long、数组、结构体,这些数据都需要转换为字节形式,按照通信协议的要求(高字节在前或低字节在前)进行发送。最基本的做法是使用未处理把每个字节分离,但这不是最好的办法,也不是常用的办法。常用的方法是使用指针。

使用实例:

从我的程序中举两个例子,之所以举这两个例子,是因为,在第二次使用时,我发现指针我还是没搞透,不过幸亏我了解自己,所以特意留意了这个问题,呵呵,不至于让他成为一个Bug。
例1.对传感器输出数据的调整 
由于传感器输出的数据是MSB在前,LSB在后;而MSP430的内存为 ”小端模式“,所以需要进行内存调整。搞明白了这个还需要搞明白怎样使用指针来进行内存交换。
这里 int  XYZ_RoughVal [3] = {0};  //是一块连续的内存。
 那么表达式 (u8)*((u8*)XYZ_RoughVal+j) 就可以取到这块内存中第j个字节的值,分析:
XYZ_RoughVal :数组地址,一个指针,类型为 int*,指向int数据
 (u8*)XYZ_RoughVal  :把地址指针转换为 u8* 类型,使得指针指向字节
 (u8*)XYZ_RoughVal+j :第j个元素的地址
*((u8*)XYZ_RoughVal+j)  :第j个元素的值
 (u8)*((u8*)XYZ_RoughVal+j) :强制转换为 u8

例2.把一个int型数据写入发送缓冲
int CarInfo = 0;
同样,协议要求MSB在前,但是MSP430为小端对齐,所以需要取得int数据中每个字节的值。而与数组不同的是,如果使用 *((u8*)CarInfo+1) 表达式,结果是错误的。为什么?
来分析下,CarInfo 是一个int数据, 那么 (u8*)CarInfo 是一个u8* 类型指针,但他指向的地址是 CarInfo 的值所表示的地址,譬如CarInfo内存地址为0x248,值为0x101,那么 (u8*)CarInfo指向的地址是 地址0x101,而地址0x101中存放的数据是0x0B。这就错了。
正确的表达式应该是  *((u8*)&CarInfo+1)  ,分析: &CarInfo:CarInfo的地址;  (u8*)&CarInfo:把这个地址转换为 u8* 类型。

小结:

指针是非常高效的,内存对齐是值得注意的。

分享到: 更多
版权申明:

本站保留所有原创文章的版权,本站地址:奔跑的博客[http://www.elecbench.com]

原创文章转载时请注明出处,并添加文章所在页面的链接:http://www.elecbench.com/%e6%8c%87%e9%92%88%e5%92%8c%e5%86%85%e5%ad%98%e5%af%b9%e9%bd%90%e5%9c%a8%e9%80%9a%e4%bf%a1%e4%b8%ad%e7%9a%84%e9%97%ae%e9%a2%98/

本站所有 2010年3月4日 以后发表、未标明为“转载”的文章均是本站原创。

发表评论


(设置自己的个性头像)

*

申请属于你的免费顶级域名