WM_CH 发表于 2017-7-7 17:51:02

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:54:57

本帖最后由 WM_CH 于 2017-7-7 17:59 编辑

好像都是从右往左,只不过Intel是从上往下,Motorola是从下往上



20061002838 发表于 2017-7-7 18:07:57

8位机没有大小端,编译器自己决定,Keil C51是大端,IAR 8051是小端
ARM的处理器大小端ARM公司没有指定,由厂家自己定。MCU通常是只支持小端,有些处理器同时支持大小端,用户自己配置,例如S3C2400,寄存器地址有两套,大小端的各一套
STM32上面可以使用RBIT指令,按位反转

q457344370 发表于 2017-7-7 18:23:27

国内用的大多Motorola,国外大多Intel,只要不跨字节没啥区别

霸气侧漏 发表于 2017-7-7 18:56:13

很明显,你说呢

RAMILE 发表于 2017-7-7 19:19:02

本帖最后由 RAMILE 于 2017-7-7 19:22 编辑

一种推理:

现在很多汽车芯片 像发动机 车身什么的,用的都是 FSL的PPC或者MSX12XXX

FSL就是Motorola的半导体部门,除了日本车,其他的几乎都用Motorola的方案

所以,当初博世提出CAN方案,很大可能就是在Motorola的MCU上实现的,所以6800就是要和8080Intel不一样

当年Motorola的CPU也是很牛的

WM_CH 发表于 2017-7-7 19:53:21

RAMILE 发表于 2017-7-7 19:19
一种推理:

现在很多汽车芯片 像发动机 车身什么的,用的都是 FSL的PPC或者MSX12XXX


原来不是有什么好处,只是历史遗留的习惯,谢谢

WM_CH 发表于 2017-7-7 19:53:48

20061002838 发表于 2017-7-7 18:07
8位机没有大小端,编译器自己决定,Keil C51是大端,IAR 8051是小端
ARM的处理器大小端ARM公司没有指定,由 ...

多谢这么专业的指导{:smile:}

WM_CH 发表于 2017-7-7 20:05:40

本帖最后由 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,这样的一个数据,对吗?





WM_CH 发表于 2017-7-7 20:18:58

霸气侧漏 发表于 2017-7-7 18:56
很明显,你说呢

测漏兄帮下忙呗{:smile:}

brentcao 发表于 2017-7-7 20:26:55

WM_CH 发表于 2017-7-7 20:05
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。

这里再追问一下 ...

应该有转字节序的函数的什么ntohl ntohs的

q457344370 发表于 2017-7-7 20:52:36

WM_CH 发表于 2017-7-7 20:05
兄台一语点破,原来我在纠结跨字节的问题。刚刚核对了一下协议,还是有跨字节的数据的。

这里再追问一下 ...

看MCU和你需要用的是不是一致的,一致直接用共用体+位域就可以做了,如果想要兼容性直接写个函数实现吧,根据起始位和长度读写bool u8 u16 u32共6个函数,如果不考虑效率,里边直接用for就可以搞定

q457344370 发表于 2017-7-7 20:58:21

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;
      }

dory_m 发表于 2017-7-8 13:25:29

先学习,谢谢!!!

huangqi412 发表于 2017-7-8 15:57:05

CAN属于通信协议, 林林总总的通信协议多了去。不管哪种,最后总要归个大小端的类。 比如底层是串口UART,上面可以是各种协议,这些协议有些就是大端,有些就是小端。比如MODBUS是大端,而别的有些也是基于UART的却是小端。       TCP,USB神马的自己去看吧。
8位的大小端是编译器决定的,高于8位的CPU除非内核限制死了大小端,不然编译器也可以决定大小端的。不管哪种情况,林林总总的CPU用起来也是最终要归个大小端的类。
问题来了,N个通信协议在N个CPU间传输,AaBb组合问题,难免有人要不顺,为什么有人顺有人不顺?没有对错,只有组合和运气。      神马,你说你用的CPU可以人为指定大小端?不怕跟别人通信纠结?那让你同时两个协议通信,一个通信协议大端一个通信协议小端看你怎么办。所以还是看运气啊。。。如果这两个协议大小端一样就顺了,不然你就去SWAP倒字序吧。

huangqi412 发表于 2017-7-8 16:04:31

总之,所有规则都是人为定的,人为折腾出来的。谁拳头大,谁先出声,就随谁的喜好定了。
然后有些地方喜欢大端的人拳头大,有些地方喜欢小端的人先出声。最后,当两个地方碰在一起,就出现了大小端不和谐的情况。

huangqi412 发表于 2017-7-8 16:08:32

日期写法都有人要争个Y/M/DM/D/Y   D/M/Y神马的      度量衡更加没有统一要换算,英制公制。

WM_CH 发表于 2017-7-10 15:45:48

q457344370 发表于 2017-7-7 20:58
给你几个用for循环实现的,效率差点,还是能用的,需要效率的话你自己写吧
...

多谢兄台指导         

WM_CH 发表于 2017-7-10 17:51:25

huangqi412 发表于 2017-7-8 15:57
CAN属于通信协议, 林林总总的通信协议多了去。不管哪种,最后总要归个大小端的类。 比如底层是串口UART,上 ...

不好意思,兄台见笑了。我还以为是这样做比较方便,原来只是历史问题。

huangqi412 发表于 2017-7-11 20:07:37

WM_CH 发表于 2017-7-10 17:51
不好意思,兄台见笑了。我还以为是这样做比较方便,原来只是历史问题。 ...

不止字节有区别你看看单片机spi配置寄存器位也有区别都是spi接口 有些芯片是msb有些却是lsb

WM_CH 发表于 2017-7-11 20:09:03

huangqi412 发表于 2017-7-11 20:07
不止字节有区别你看看单片机spi配置寄存器位也有区别都是spi接口 有些芯片是msb有些却是lsb ...

感谢兄台指点{:handshake:}

都没注意过。。


WM_CH 发表于 2017-9-12 09:46:12

楼主位的两种方式,不就是简单的字节序不同的区别嘛。。。。{:lol:}
页: [1]
查看完整版本: CAN总线,汽车厂的协议ByteOrder是Motorola Forward lsb为何要这么做