服务与案例 Service 当前位置: 首页 > 服务与案例 > 应用案例 >
固定电话:028-68743610
客服手机:13730631678
客服QQ  :
客服邮箱:@transcendence2014.com
 
联系地址:四川省成都市成华区双林横路12号
使用CAN分析仪协助单片机开发
2015-08-29 22:54:14

使用CAN分析仪协助单片机开发

  普通的单片机开发,除了集成开发环境的单步调试外,使用串口输入输出调试信息比较多。
  单步调试的好处显而易见,但缺点也很明显:不得不中断当前程序的运行。但在很多时候,是想在不中断程序运行的情况下调试。这种情况下,传统的方式就是上面说的串口调试输出。
  但用串口的缺点也很明显,就是速度不快,而且一般只能传输原始字节信息。如果是从单片机输出信息的话,就需要电脑的串口通信程序查看这些原始信息,再手动解码才能了解它是什么意思。要向单片机输入控制信息的话,也是只能手动输入字节,然后在单片机程序中解码。
  而用CAN通信来输入输出调试信息的话,因为CAN通信本身的特性,会比串口方便很多,而且更加灵活易用。
下面我们就详细比较说明一下使用串口与CAN调试的优缺点。

1. 从单片机输出调试信息

1.1使用串口的方法与缺点

  比如,我们需要向外输出一组调试信息:发机机转速与油门为一组(下称A组)。那么,我们可能需要作如下定义:
  A组标识符为0x01,占用一字节。转速与油门都为32位浮点数(这是无损传输,也可以用网络传输中常用的分辨率+偏移方式作有损传输,能减少传输的字节数,用户请自己查看相关信息,这里不详述)。
  这样的话,传输A组数据至少就需要9字节(标识符1字节,转速4字节,油门4字节,这里不考虑换行等控制字节了)。
  假如转速为2000转,油门是40%。2000的浮点内部表示为:0x44FA0000, 40的浮点内部表示为0x42200000。这样A组用串口发送的数据即为:
  0x01 0x44 0xFA 0x00 0x00 0x42 0x20 0x00 0x00
  其中,黄色为标识符,蓝色是转速,红色是油门。
  这样的数据传输到电脑的串口程序中,用户需要一个小工具(浮点内部形式转换为可识别的十进制形式),才能知道转速与油门实际是多少。
  若使用有损传输,假如转速的分辨率为0.1,用两字节表示,油门的分辨率为0.4,用一字节表示。那么转速的字节=2000/0.1 = 0x4E20,油门的字节=40/0.4 = 0x64。则传输的数据为:
  0x01 0x4E 0x20 0x64
  这相对前面的无损传输容易识别得多,但这仍然不能一目了然,必须得手动计算(如使用计算器等),才会知道结果。数据量小的话,手动计算也没有什么问题,但数据太多,又经常使用的话,这就比较繁琐了。这其实是绝大部分串口程序本身的缺陷,它不能提供自动转换的功能,用户能见的就只是原始字节数据。
  同时,还得考虑发送是异步还是同步的问题。
  假定发送串口数据的函数是printf。   如果是同步的,就得待一组数据发送完后,printf函数才返回。根据单片机的串口外设提供的功能不同,有多种处理方式,但基本而言,考虑到串口的通信速率比较低,这个操作可能会导致程序一定程度的堵塞,会影响到正常程序的执行。特别是在多组数据同时发送时,堵塞会更加严重。
  如果发送是异步的,也就是说printf只将数据放放缓存中,然后就返回。这就基本上不会出现堵塞的情况,对程序的干扰就比较小了。但这样的话,实际的是发送操作让外设,或者程序其它部分来控制完成。如果用户使用的开发环境本身提供这样的库函数上下文环境尚可,如果没有提供,要用户自己来完成的话,写代码就比较麻烦了(其实很多时候都还是需要用户自己来写的,实现起来也并非想象中那么容易)。

1.2使用CAN通信的方法与优点

  如果不使用串口,而使用CAN通信来处理上述问题的话,事情会简单得多。首先,单片机上的CAN外设一般都带有多个缓存,通信的数据发送天然是异步的,绝不会存在堵塞程序运行的问题。用户只需要实现CAN的基本驱动即可,不用因为考虑同步异步的问题,又多花时间在CAN基本驱动的上层加上其它缓存处理代码。而且CAN数据速率比较高(最高为1MBps),传输的数据实时性也远大过串口。
  另外,因为CAN数据格式的统一性,为电脑上的CAN分析仪之类的工具提供了自动解析原始字节的可能性。比如上面的浮点数据与有损传输数据的自动解析。一般只有相对比较高端的CAN分析仪才会提供这样的自动解析功能,普通的所谓的CAN分析仪只会显示原始字节,与那种串口显示程序没有什么大的差别。
  这里我们用华谌科技的CAN分析仿真系统CANslinkal为例,介绍如何使用数据的自动解析功能(CANupoks也可以完成同样的操作,这里不赘述)。
  依然是前面提到的A组数据,只是需要注意,其ID为0x01,作为CAN ID使用,不再包含在数据字节中。数据字节只包含发动机转速与油门的8字节数据(这里用无损传输)。在用户单片机程序中,用如下方式组装与发送数据:
\

  打开CANslinkal软件,建立一个工程,然后打开CAN数据库编辑页面,如下图,建立对ID 0x01的解析数据库:
\

  如上图,我们就建立的A组数据的解析依据,当系统运行时,收到0x01这个ID,且为标准ID时,就会根据其数据内容自动解析结果。结果可以在ID观测页面显示,也可以在别的地方显示,视用户的自己选择。这里我们在ID观测页面查看。
  实际运行时,我们需要连接CANslinkal硬件与单片机的CAN通信线,并运行二者才能通信。这里我们因为是作演示,就用另一台CANslinkal硬件模拟单片机发送数据。将两台CANslinkal相连如下,

\
  为了模拟单片机发送A组数据,我们在橙色所示CANslinkal软件上,使用脚本功能,建立如下发送逻辑:
\

  该脚本的功能是,每100毫秒发送一次A组数据,主体代码与我们前面所述单片机代码是一样的。
连接好硬件,并对两台CANslinkal硬件设置合适的通信参数,运行之后,在ID观测页面,我们就以看见自动解析的A组数据的值了:
\

  由上图可以看见。只要收到了单片机发的来数据,CANslinkal就会自动把原始数据显示出来,同时将原始数据代表的实际的物理数值自动解析出来。这远比手动解析原始数据要方便得多。
  当然,CANslinkal提供了自动解析数据功能显示的结果,不仅仅只会在ID观测页面中以这样的方式呈现。还可以在“监测器”与“图形面板中”用多样的方式呈现出来,这都全在用户自己如何使用而已。如下图,我们在监测器中与图形面板中显示同样的数据(这里我们修改了发送的数据值,转速与油门都在一定范围内变动,以方便我们查看比较):
\
\

2. 向单片机输入调试命令

  很多的时候,在调试时,我们希望向单片机输入信息,让单片机执行某种操作。其中常用的一种操作就是取某个地址的值。特别是外设寄存器,一般都是映射到存储中的某个地址中的,通过读取这个地址,就能读取寄存器的值。这为开发与确认外设功能非常有帮助。下面我们就用例子来说明这种操作
 

2.1使用串口的方法与缺点

  假定芯片是32位的,我们想读取地址0x12345678的开始的四字节的数据。为了区分多种命令,我们这样组装命令数据:
 
   第0字节是命令标识:0x0A,它表示从某个地址读取四字节数据。
   第1到第4字节是32位的地址,用大端方式组装。
 
   单片机作如下格式的应答:
   第0字节是应答标识:0x8A,它表示是对0x0A命令的答复。
   第1到第4字节是32位地址,也就是命令要求的地址。
   第5到第8字节是32位的数据,它就是从要求地址开始的4字节数据。
   最终命令的数据为:
  0x0A 0x12 0x34 0x56 0x78
  其中黄色为命令标识,蓝色为地址。
  单片机应答的数据为(假定数据为0x0F 0x0E 0x0D 0x0C):
  0x8A 0x12 0x34 0x56 0x78 0x0F 0x0E 0x0D 0x0C
  其中黄色为应答标识,蓝色为地址,红色为数据。
  串口要处理这个,没有更多的办法,就只能老老实实的手动组装命令,然后手动解析应答的结果。
这种不方便之外还在其次,最麻烦的是在单片机上写代码去接收这个命令。我们都知道串口就只能一个字节一个字节的发送数据,如果每收到一个字节,打印显示出来,对我们大脑来说,其功能是一目了然的,然而写串口代码的话,就很难:命令是多个字节的组合,所以我们不得不定义什么时候是命令的开始,什么时候是命令的结束。这就意味着,我们不得不在串上基本驱动上面实现一个通信协议。固然有许多可用的协议做参考,但自己写代码来实现的话,都是相当的困难且易出错的(有兴趣的用户可以自己去实现一个串口的应用协议,看看其难度有多大)。

2.2使用CAN通信的方法与优点

  如果用CAN通信来给单片机输入命令,并借助CAN分析仪的功能来实现的话,我们能做更多更灵活的操作。而且单片只要有基本的CAN驱动就行了,不用什么上层应用协议。因为CAN数据最大是8个字节,是由CAN控制器自动完成这8个字节的接收的,完全不用用户写代码实现这个。而8个字节对我们的绝大部分调试都是足够了的。
这里依然以上面发送读取地址的命令为例说明,并用CANslinkal分析仪作为工具来辅助完成。
  依然用0x0A为命令标识符,但0x0A用作CAN ID,这样意义更明了些。这样发送的数据如下:
  CAN ID: 0x0A,固定为标准类型
  CAN数据:八字节,前四字节表示地址,与上面一样,分别为0x12 0x34 0x56 0x78。这是用大端方式组装的。后  四字节不使用,无意义。
 在CANslinkal中,我们用模块编程来完成这个操作。需要做的操作为:
  1. 建立ID为0x0A的CAN数据库条目,以让分析仪自动为我们组装地址。
  2. 建立仿真模块程序,当接收到用户按钮的发送命令时,就将地址用0x0A的ID发送出去。
  3. 建立仿真面板,里面有两个控件,一个是发送按钮,命令模块程序把命令发送出去。一个是地址输入控件,用来输入我们要请求的地址。注意我们前面说是地址是0x12345678,但用CANslinkal来做这个的话,我们可以在运行过程自由输入任意地址,而不用固定为这个唯一的地址,这为调试提供了更灵活的功能。
  下面我们一步一步说明上面的操作。
  首先还是打开CANslinkal程序,建立一个新的CANslinkal工程,并在CAN数据库中建立如下项目:
\

  然后新建一个仿真文件,并在顶层的周期系统下,建立如下逻辑:
\

  该逻辑的意义为:当用户从仿真面板(后述)中按下发送按钮时,就是触发“发送CAN数据”这个使能系统执行。
  使能系统执行的内容,就是发送CAN数据。双击该系统进入其中,建立如下逻辑:
\

  该逻辑表示,从仿真面板中取得用户输入的地址,然后让名为“发送CAN数据”的CAN单帧发送模块将地址自动组装在CAN数据中,然后发送出去。该CAN单帧发送模块的属性设置如下:
\

  可以看见,它就是使用了我们前面建立的CAN数据库项目。并且数据从通道1发送出去。
  最后,我们为该仿真文件建立一个面板,然后设计如下:
\

  注意里的的按钮是与前面仿真文件中的“发送地址请求”的面板输入模块相关联的,地址输入框是与仿真文件中“地址”面板输入控件相关联的。具体操作这里不详述。
 这样运行CANslinkal,然后按下“发送地址请求”按钮,就会把地址请求数据发送出去了。运行过程中,用户是可以在面板中随意修改请求的地址的。
  前面描述了发送请求命令的处理。对单片机对此命令的应答的话,我们可以作如下处理:
依然用0x8A作为CAN ID应答,数据中的前四字节还是地址,后四字节还是数据。
  因为是作演示,我们如前面一样,用另一套CANslinkal来模拟该命令的应答。具体如何实现我们这里就不再详述了,只是应答的内容,我们仅仅把地址按字节取反就行了。这也比较方面我们确认功能。
  然后我们运行CANslinkal,在“ID观测”页面中,就可以看见下面的通信内容:
\

  这对种应答式的通信,我们将其放在“CAN数据流”页面中观察更一目了然:
\

  上图数据流中,可以看见,我们发送了两次地址数据请求命令,一次地址是0x12345678,一次地址是0x0A0B0C0D,ID 0x8A的应答的内容,就如我们前面定义一样,是将地址取反,作为数据发送过来的。
 

3总述

  通过上面对比串口与CAN通信调试程序,我们可以发现CAN通信的优点是非常多的,完全可以替代串口实现更易用更强大的调试功能。当然,使用它的前提是用户首先把单片机上CAN基本驱动实现了,另外得有一个好用的CAN分析仪工具。不要认为能够接收与发送原始CAN数据的就是一个合理可用的CAN分析仪,用户应该慎重选择顺手的工具,以能达到事半功倍的效果。