实验5 CAN通信实验
1. 实验目的
按照指定协议,解析can报文,显示电压温度等信息。
说明:4.3寸及以上带can版本的串口屏,支持can通信。
2. 页面设计
(1)整数控件,显示电压值
(2)整数控件,显示温度值
(3)整数控件,显示SOC
(4)文本控件,显示故障信息
(5)can协议解析器控件,可以编写脚本代码,解析can报文。
图片资源,使用了一个480*272分辨率的背景图片。页面的背景图片额可以使用专业的绘图软件更加丰富、绚烂的背景图片。图片素材决定了显示的整体外观,让界面的设计更加容易。
字体字体除了工程自带的字库Tahoma_4x_ASCII(包括英文和数字),另外创建了一个中文的字库,双击这个字库,可以看到详细的信息。字库详细制作方法可以参考第三章的添加字库小节。
3. 串口屏协议处理
该例程使用了can解析器。串口屏每次收到一帧can数据,都会触发一次can解析器的脚本,和单片机的can中断函数类似。
协议定义(仅供参考)
扩展数据帧,波特率250K |
||
---|---|---|
ExdId |
data[0~7] |
|
0x1800AB01 |
[0~1]电池1电压值 |
小端模式,单位mV |
0x1800AB02 |
[0~1]电池5电压值 |
小端模式,单位mV |
0x1800AB10 |
[0] 温度1 |
小端模式,单位℃ |
0x1800AB11 |
[1] 温度3 |
小端模式,单位℃ |
0x1800AB12 |
[0]SOC |
范围0~100 |
0x1800AB13 |
[0]故障信息 |
选中can解析器,可看到事件编辑窗口,事件代码如下:
if(can.rxId == 0x1800AB01)
{
cell1.val = (can.rxDataBuf[1]<<8)|can.rxDataBuf[0]; //电池1
cell2.val = (can.rxDataBuf[3]<<8)|can.rxDataBuf[2]; //电池2
cell3.val = (can.rxDataBuf[5]<<8)|can.rxDataBuf[4]; //电池3
cell4.val = (can.rxDataBuf[5]<<8)|can.rxDataBuf[6]; //电池4
}
else if(can.rxId == 0x1800AB02)
{
cell5.val = (can.rxDataBuf[1]<<8)|can.rxDataBuf[0]; //电池5
cell6.val = (can.rxDataBuf[3]<<8)|can.rxDataBuf[2]; //电池6
}
else if(can.rxId == 0x1800AB11)
{
t1.val = can.rxDataBuf[0];//温度1
t2.val = can.rxDataBuf[1];//温度2
t3.val = can.rxDataBuf[2];//温度3
t4.val = can.rxDataBuf[3];//温度4
}
else if(can.rxId == 0x1800AB12)
{
soc.val = can.rxDataBuf[0];//SOC
}
else if(can.rxId == 0x1800AB13) //故障信息
{
if(can.rxDataBuf[0] == 0x00)
fault.txt = "无故障";
else if(can.rxDataBuf[0] == 0x01)
fault.txt = "电池故障";
else if(can.rxDataBuf[0] == 0x02)
fault.txt = "温度故障";
else if(can.rxDataBuf[0] == 0x03)
fault.txt = "系统故障";
}
事件解析器的代码很简单,can.rxId存放报文id, can.rxDataBuf存放数据,数组长度8字节。按照协议解析数据即可。
4. 硬件过滤器的配置
显示屏接入can总线时,可以设置硬件过滤器。硬件上过滤掉不需要接收的报文,减少显示屏处理过多无用报文的压力,提高显示屏刷屏流畅度。设计can程序时,配置过滤器很有必要。
显示屏can收发调试过程中,可以不配置过滤器,方便调试。工程调试完成后,再将掩码和滤码设置成合适的值。
显示屏过滤器最多有14个,编号0~13,每个过滤器有两种过滤模式:屏蔽位模式、标识符列表模式
屏蔽位模式:
需要设置过滤标识符filter 和过滤掩码mask。硬件收到一帧can报文id时,按照mask为1的bit,与过滤标识符对比,全部mask位相同时,则接收该报文,否则拒收。换个说法:如果( id & mask) == filter , 接收此报文;否则不符合过滤要求, 不接收此报文。 适用于要接收can报文比较多且报文id有一定规律。
标识符列表模式:
硬件收到一帧can报文id时,与过滤器列表一一对应,如果有匹配的报文id则接收该报文,否则拒收。每个过滤器可以设置两个ID,所以最多可设置28个。适用于要接收的can报文比较少的情况,可以实现can报文的精准过滤。
——————————————————————————————————————————————————————
串口屏的过滤器设置可以通过项目设置界面配置(只能配置过滤器0的屏蔽位模式),也能在脚本里调用can控件的方法setFilter来配置(通过参数来配置过滤器的参数,可以灵活的设置的工作模式)。
1、项目设置界面;
打开 ”can通信实验.pix”工程,点击项目设置图标 ,可以查看到can的波特率、过滤报文的掩码和滤码。
这种配置方式,只能设置过滤器0的屏蔽位模式。适用于过滤器简单的设置,优点是配置简单
计算掩码mask和滤码filter的时候,考虑所有要接收的报文id,找出相同的bit和有差异的bit。该例程的所有要接收的报文有6个id,如下:
0x1800AB01
0x1800AB02
0x1800AB10
0x1800AB11
0x1800AB12
0x1800AB13
有差异的bit有[1:0]、[4],其余bit都是相同的。则mask的[1:0]、[4]为0,其他为1,即mask=0xFFFFFFEB。相同的bit即为filter,即filter=0x1800AB00。最后可将上面5个验证 是否( id & mask) == filter .
2、调用can控件的方法setFilter
当过滤的规则比较复杂时,建议使用setFilter方法来配置过滤器。
打开 ”can通信实验_setFilter.pix”工程,点击page0空白处,可以看到加载页面事件,脚本代码如下
这里需要注意的是,该脚本是首页的加载页面事件,用了一个变量startup来标记该脚本只执行一次,因为配置过滤器只需上电配置一次就可以了。
void setFilter(u8 filterid,u8 mode,u32 param1, u32 param2);
/*
函数功能:配置can接收过滤器
参数1:filterid,过滤器编号,0~13
参数2:mode,过滤器模式,0屏蔽位模式,1标识符列表模式
参数3:param1,过滤器参数1,参数位定义见下表
参数4:param2,过滤器参数2,参数位定义见下表
*/
过滤器param1和param2位定义:
位31:21 |
STID[10:0]/EXID[28:18]:标准标识符或扩展标识符 |
---|---|
位20:3 |
EXID[17:0]扩展标识符低18bit |
位2 |
IDE:标识符类型 |
位1 |
RTR:远程发送请求 |
位0 |
保留位 |
标识符列表模式
can.setFilter(0,1,(0x1800AB01<<3)|0x04,(0x1800AB02<<3)|0x04); //过滤器0
can.setFilter(1,1,(0x1800AB10<<3)|0x04,(0x1800AB11<<3)|0x04); //过滤器1
can.setFilter(2,1,(0x1800AB12<<3)|0x04,(0x1800AB13<<3)|0x04); //过滤器2
屏蔽位模式
can.setFilter(0,0,(0xFFFFFFEB<<3)|0x04,(0x1800AB00<<3)|0x04); //过滤器0
方法setFilter的参数patam1和param2都与0x04按位或运算,表示只接收扩展帧。
注:
假如要接收标准帧,如0x6A1(标准帧),0x6A2(标准帧),可以这样设置:
CAN_Set_Filter2(0,1,0x6A1<<21,0x6A2<<21); //过滤器0,标识符列模式
或者
CAN_Set_Filter2(0,0,0xFFC<<21,0x6A0<<21); //过滤器0,屏蔽位模式
至于这里为什么是左移21位,可以参考上表param1和param2位定义。
5. 下载验证
编译成功后,点击下载按钮,选择正确的端口号和波特率,下载到串口屏。将串口屏接到can总线上,串口屏收到正确报文时,会解析并显示。
调试时,用任意can收发器的助手,给显示屏发报文测试即可。界面如下:
can调试工具发送数据
测试命令如下:
报文ID |
数据 |
说明 |
---|---|---|
1800AB01 |
E4 0C E4 0C E4 0C E4 0C |
设置电池1~4 |
1800AB02 |
E4 0C E4 0C |
设置电池5~6 |
1800AB10 |
20 20 |
设置温度1~2 |
1800AB11 |
20 20 |
设置温度3~4 |
1800AB12 |
60 |
设置SOC |
1800AB13 |
00 |
故障信息 |