CAN总线,汽车厂的协议ByteOrder是Motorola Forward lsb为何要这么做
CAN总线,汽车厂的协议ByteOrder是Motorola Forward lsb为何要这么做,好处是什么?KEIL C51中,变量都是大端模式的,KEIL MDK中,变量是小端模式的。
其实这是与MCU类型相关的,51是8位机,但所有的编译器都是大端的,为了兼容原有的环境,就只能一直大下去。而ARM是32位的CPU,其内核先天就是小端的,那编译器也不会特立独行地搞个大端出来。
在STM32里面,字节序是Intel(即小端),位序为Standard。CAN总线8字节数据 分布情况如图:
但是汽车厂给的CAN通信协议中,字节序为Motorola,位序是Forward lsb。CAN总线8字节数据 分布情况如图:
在下不知道,字节序定义为Motorola forward lsb的好处是什么?
如果stm32收到的数据需要串口打印出来,那势必需要进行格式转换,这种转换怎么做?
小弟迷惑
本帖最后由 WM_CH 于 2017-7-7 17:59 编辑
好像都是从右往左,只不过Intel是从上往下,Motorola是从下往上
8位机没有大小端,编译器自己决定,Keil C51是大端,IAR 8051是小端
ARM的处理器大小端ARM公司没有指定,由厂家自己定。MCU通常是只支持小端,有些处理器同时支持大小端,用户自己配置,例如S3C2400,寄存器地址有两套,大小端的各一套
STM32上面可以使用RBIT指令,按位反转 国内用的大多Motorola,国外大多Intel,只要不跨字节没啥区别 很明显,你说呢 本帖最后由 RAMILE 于 2017-7-7 19:22 编辑
一种推理:
现在很多汽车芯片 像发动机 车身什么的,用的都是 FSL的PPC或者MSX12XXX
FSL就是Motorola的半导体部门,除了日本车,其他的几乎都用Motorola的方案
所以,当初博世提出CAN方案,很大可能就是在Motorola的MCU上实现的,所以6800就是要和8080Intel不一样
当年Motorola的CPU也是很牛的
RAMILE 发表于 2017-7-7 19:19
一种推理:
现在很多汽车芯片 像发动机 车身什么的,用的都是 FSL的PPC或者MSX12XXX
原来不是有什么好处,只是历史遗留的习惯,谢谢 20061002838 发表于 2017-7-7 18:07
8位机没有大小端,编译器自己决定,Keil C51是大端,IAR 8051是小端
ARM的处理器大小端ARM公司没有指定,由 ...
多谢这么专业的指导{:smile:} 本帖最后由 WM_CH 于 2017-7-7 20:18 编辑
q457344370 发表于 2017-7-7 18:23
国内用的大多Motorola,国外大多Intel,只要不跨字节没啥区别
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。
这里再追问一下,要是跨字节访问怎么做呢,兄台这块还请指导一下,我脑子彻底懵了
夸两个字节的话,低字节的高几位比如(Byte0的bit7 , bit6),通过位移,和高字节的低几位拼起来(比如Byte1的bit1 , bit0),
最后的结果就是B1b1, B1b0, B0b7, B0b6,这样的一个数据,对吗?
霸气侧漏 发表于 2017-7-7 18:56
很明显,你说呢
测漏兄帮下忙呗{:smile:} WM_CH 发表于 2017-7-7 20:05
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。
这里再追问一下 ...
应该有转字节序的函数的什么ntohl ntohs的 WM_CH 发表于 2017-7-7 20:05
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。
这里再追问一下 ...
看MCU和你需要用的是不是一致的,一致直接用共用体+位域就可以做了,如果想要兼容性直接写个函数实现吧,根据起始位和长度读写bool u8 u16 u32共6个函数,如果不考虑效率,里边直接用for就可以搞定 WM_CH 发表于 2017-7-7 20:05
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。
这里再追问一下 ...
给你几个用for循环实现的,效率差点,还是能用的,需要效率的话你自己写吧
/// <summary>
/// Intel
/// </summary>
/// <param name="bytes"></param>
/// <param name="start"></param>
/// <param name="length"></param>
/// <param name="value"></param>
/// <returns></returns>
public static byte[] SetBitIntel(this byte[] bytes, int start, int length, uint value)
{
for (int i = 0; i < length; i++)
{
int posByte = (i+ start) / 8;
int posBit = (i + start) % 8;
byte bitValue = (byte)((value >> i) & 0x01);
bytes &= (byte)(~(1 << posBit));
bytes |= (byte)(bitValue<< posBit);
}
return bytes;
}
/// <summary>
/// Intel
/// </summary>
/// <param name="bytes"></param>
/// <param name="start"></param>
/// <param name="length"></param>
/// <returns></returns>
public static uint GetBitIntel(this byte[] bytes, int start, int length)
{
uint value = 0;
for (int i = 0; i < length; i++)
{
int posByte = (i + start) / 8;
int posBit = (i + start) % 8;
value |= (((uint)bytes >> posBit) & 0x01) << i;
}
return value;
}
/// <summary>
/// Motorola
/// </summary>
/// <param name="bytes"></param>
/// <param name="start"></param>
/// <param name="length"></param>
/// <param name="value"></param>
/// <returns></returns>
public static byte[] SetBitMotorola(this byte[] bytes, int start, int length, uint value)
{
int posByte = start / 8;
int posBit = start % 8;
for (int i = 0; i < length; i++)
{
byte bitValue = (byte)((value >> i) & 0x01);
bytes &= (byte)(~(1 << posBit));
bytes |= (byte)(bitValue << posBit);
if(i >= length)
{
break;
}
if(++posBit >= 8)
{
posBit = 0;
posByte--;
}
}
return bytes;
}
/// <summary>
/// Motorola
/// </summary>
/// <param name="bytes"></param>
/// <param name="start"></param>
/// <param name="length"></param>
/// <returns></returns>
public static uint GetBitMotorola(this byte[] bytes, int start, int length)
{
uint value = 0;
int posByte = start / 8;
int posBit = start % 8;
for (int i = 0; i < length; i++)
{
value |= (((uint)bytes >> posBit) & 0x01) << i;
if (i >= length)
{
break;
}
if (++posBit >= 8)
{
posBit = 0;
posByte--;
}
}
return value;
} 先学习,谢谢!!! CAN属于通信协议, 林林总总的通信协议多了去。不管哪种,最后总要归个大小端的类。 比如底层是串口UART,上面可以是各种协议,这些协议有些就是大端,有些就是小端。比如MODBUS是大端,而别的有些也是基于UART的却是小端。 TCP,USB神马的自己去看吧。
8位的大小端是编译器决定的,高于8位的CPU除非内核限制死了大小端,不然编译器也可以决定大小端的。不管哪种情况,林林总总的CPU用起来也是最终要归个大小端的类。
问题来了,N个通信协议在N个CPU间传输,AaBb组合问题,难免有人要不顺,为什么有人顺有人不顺?没有对错,只有组合和运气。 神马,你说你用的CPU可以人为指定大小端?不怕跟别人通信纠结?那让你同时两个协议通信,一个通信协议大端一个通信协议小端看你怎么办。所以还是看运气啊。。。如果这两个协议大小端一样就顺了,不然你就去SWAP倒字序吧。
总之,所有规则都是人为定的,人为折腾出来的。谁拳头大,谁先出声,就随谁的喜好定了。
然后有些地方喜欢大端的人拳头大,有些地方喜欢小端的人先出声。最后,当两个地方碰在一起,就出现了大小端不和谐的情况。 日期写法都有人要争个Y/M/DM/D/Y D/M/Y神马的 度量衡更加没有统一要换算,英制公制。 q457344370 发表于 2017-7-7 20:58
给你几个用for循环实现的,效率差点,还是能用的,需要效率的话你自己写吧
...
多谢兄台指导 huangqi412 发表于 2017-7-8 15:57
CAN属于通信协议, 林林总总的通信协议多了去。不管哪种,最后总要归个大小端的类。 比如底层是串口UART,上 ...
不好意思,兄台见笑了。我还以为是这样做比较方便,原来只是历史问题。 WM_CH 发表于 2017-7-10 17:51
不好意思,兄台见笑了。我还以为是这样做比较方便,原来只是历史问题。 ...
不止字节有区别你看看单片机spi配置寄存器位也有区别都是spi接口 有些芯片是msb有些却是lsb huangqi412 发表于 2017-7-11 20:07
不止字节有区别你看看单片机spi配置寄存器位也有区别都是spi接口 有些芯片是msb有些却是lsb ...
感谢兄台指点{:handshake:}
都没注意过。。
楼主位的两种方式,不就是简单的字节序不同的区别嘛。。。。{:lol:}
页:
[1]