0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

英创信息威廉希尔官方网站 C/C#开发基于WEC7的CAN通讯介绍

英创信息威廉希尔官方网站 来源:英创信息威廉希尔官方网站 作者:英创信息威廉希尔官方网站 2020-01-17 10:01 次阅读

英创EM335x工控主板,使用的Cortex-A8及WEC7操作系统。本文以EM335x工控主板光盘例程为例,简单介绍一下C和C#代码如何调用WEC7平台下CAN驱动,实现CAN通信的方法。

C代码

客户可以在自己工程中添加例程中的EM335X_CAN.h及EM335X_CAN.cpp,使用里面封装好的EM335X_CAN类。
#include 'EM335X_CAN.h'
EM335X_CAN can;

打开CAN
调用EM335X_CAN类的OpenCAN方法。比如用250Kbps打开CAN1(默认只有CAN1)。
DWORD dwCanNo = 1;
DWORD dwBaudRate = 250000;
can.OpenCAN( dwCanNo, dwBaud );

关闭CAN
调用EM335X_CAN类的CloseCAN方法。
can.CloseCAN( );

发CAN数据包
调用EM335X_CAN类的WriteCAN方法。
can.WriteCAN(&canmsg );

接收CAN数据包

例程中使用了一个独立的线程来接收。然后将收到的数据传递给PackagePro函数处理。参数一为数据buffer指针,参数二为数据的长度。
int EM335X_CAN::PackagePro(char* pBuf , int len)

用户可以根据应用具体需求,添加相应的逻辑代码。

CAN发送接收数据包结构体定义
不论是CAN发送,还是CAN接收,都是以数据包为单位发送接收的。单个数据包大小为16字节,结构体定义如下:
typedef struct {
CAN_ID id;
BYTE dlc;
BYTE data[8];
}CAN_MESSAGE,*PCAN_MESSAGE;

id,一个CAN_ID的结构体,该结构体定义在下面说明。
dlc,1字节,数据长度,取值0-8;
data,8字节,传输的数据。

注:因为结构体对齐的原因,该结构体大小为16字节。

CAN_ID结构体是一个整型,32位,用来记录CAN通信所需的ID信息
typedef struct{
unsigned int id:29;
unsigned int reserved:1;
unsigned int remote:1;
unsigned int extended:1;
}CAN_ID;

id,结构体整型的低29位,表示id号。
reserved,第30位,用来标记是接收的数据包,还是发送的数据包,默认设置为0即可。
remote,第31位,用来设置是数据帧还是远程帧。0为数据帧,1为远程帧。
extended,第32位,用来设置是标准帧还是扩展帧。0为标准帧,1为扩展帧。

CAN过滤条件Filter设置
EM335x同样支持数据包过滤功能,设置Filter可以使得CAN只接收自己需要的数据包。

调用EM335X_CAN类的SetFilter方法,可以添加一个过滤条件,或者删除一个已有的过滤条件。例如:
bResult = can.SetFilter( &Filter, FALSE );

第一个参数为过滤条件参数,为一个CAN_FILTER的结构体,在下面有说明。第二个参数如果为FALSE,则表示添加该过滤条件,如果为TRUE,则表示删除已有的该过滤条件。

有多个过滤条件的情况下,只要数据包可以满足任意一个过滤条件,那么该数据包就可以被接收。

CAN过滤条件Filter结构体定义
CAN_FILTER结构体定义如下:(CAN_ID结构体的定义前面数据包结构体里有说明)
typedef struct {
CAN_ID id;
CAN_ID mask;
}CAN_FILTER,*PCAN_FILTER;

这里的过滤逻辑如下:


假设收到的数据包里的id,我们记为id_message,与过滤条件中的filter参数里的id和mask满足条件:(id_message&mask) == (id&mask),那么该数据包就可以接收,也就是说,mask表示需要进行对比的位,如果数据包的id这几位与filter设置里的id的这几位相同,那么该数据包就可以接收。

比如:
一个filter的mask = 0x03,即2进制的b0000 0011,即需要比较最后的两位。
filter的id = 0x02,即2进制的b0000 0010。
那么数据包id如果最后两位为 10,该数据包就可以通过过滤条件被接收。
数据包id = 0xF7,即2进制b1111 0111,无法接收。
数据包id = 0xE6,即2进制b1110 0110,可以接收。
数据包id = 0x2E,即2进制b0010 1110,可以接收。

CAN环回模式设置
环回模式为,可以选择板子自己发送的数据包,是否自己也能同时接收到。

调用EM335X_CAN类的CAN_Loopback方法,如果希望自己发送的CAN包,自己也能接收到,那么设置第二个参数为TRUE。如果希望关闭环回功能,那么第二个参数设置为FALSE。

CAN其它命令
EM335X_CAN类的CanCommand方法可以控制CAN复位,启动和停止。
BOOL CanCommand( CAN_COMMAND eCommand);

参数CAN_COMMAND是一个枚举型,它的定义如下,STOP= 0,START =1,RESET=3:
typedef enum {
STOP,
START,
RESET
} CAN_COMMAND;

1、复位CAN
CAN复位会重置CAN驱动里的各个寄存器值,并执行相关的初始化操作。

在打开CAN的时候,OpenCAN函数里已经调用了该函数实现CAN复位。用户可以根据自己应用的实际情况,决定在什么时机执行CAN复位。

2、启动CAN
在设置好CAN波特率,环回,filter等参数后,CAN驱动线程并没有马上启动,需要执行CAN启动,CAN线程才开始工作。

在打开CAN的时候,OpenCAN函数在设置完参数后调用CAN启动。用户可以根据自己应用的实际情况,决定在什么时机执行该函数,例如:当CAN接收线程的接收到错误事件时,可以在错误处理代码里添加停止CAN,和重新启动CAN的调用。

3、停止CAN
停止CAN会关闭CAN驱动线程,在关闭CAN的时候,CloseCAN函数调用CAN停止。

C#代码

C#代码参考了C代码,相对C接口稍微做了调整。我们同样封装了一个CAN的类在EM335x_CAN_API.cs中,方便客户添加到自己工程中。

打开CAN
打开CAN的流程为:打开CAN设备,获得设备句柄,初始化CAN,然后设置CAN的参数(波特率,环回模式),创建CAN接收线程,最后启动CAN,然后CAN驱动线程开始工作。

1、打开CAN设备
int CanNo = 1;
hCAN = CAN.OpenCAN(CanNo);

2、重置CAN
执行Reset操作,初始化CAN。
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.RESET);

3、设置波特率
设置CAN的波特率,如250Kbps:
uBaud = 250000;
bRet = CAN.CAN_SetBaudRate(hCAN, uBaud);

4、设置CAN环回模式
如果希望自己发送的CAN包,自己也能接收到,那么可以设置第二个参数为1,例程中暂时关闭该功能,所以设置的0。
bRet = CAN.CAN_Loopback(hCAN, 0);

5、创建单独的接收线程
因为接收时,函数需要等待CAN接收事件,为阻塞状态,不宜直接写在主线程中,这里添加一个接收线程,专门处理CAN数据接收。
创建线程:
revThread = new Thread(new ThreadStart(BeginReceive));
threadStop = false;
revThread.Start();//启动waitforMessage线程

6、启动CAN
当准备就绪,就可以启动CAN设备了。
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.START);

关闭CAN
主要是结束接收线程,停止CAN,及关闭CAN设备句柄等。
revThread.Abort();//结束线程
revThread.Join();
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.STOP);
bRet = CAN.CloseCAN(hCAN);

发CAN数据包
调用WriteFile发送CAN数据包。
bRet = CAN.WriteFile(hCAN, ref pktSend, CAN.sizePacket, ref uLen, 0);

接收CAN数据包
调用ReadFile发送CAN数据包。
bResult = CAN.ReadFile(hCAN, ref pktRev, CAN.sizePacket, ref uLen, 0);

CAN发送接收数据包结构体定义
不论是CAN发送WriteFile,还是CAN接收ReadFile,都是以数据包为单位发送接收的。单个数据包大小为16字节,结构体定义如下:
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct CAN_MESSAGE
{
[FieldOffset(0)]
public uint id;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] data;//数据字节
}

id是一个整型4字节,32位,用来记录CAN通信所需的ID信息。
id的低29位,表示id号。
id的第30位,用来标记是接收的数据包,还是发送的数据包。
id的第31位,用来设置是数据帧还是远程帧。该位为0则是数据帧,该位为1则是远程帧。
id的第32位,用来设置是标准帧还是扩展帧。该位为0则是标准帧,该位为1则是扩展帧。

data为12字节byte数组。
data[0]为CAN数据包内数据的长度,取值0-8;
data[1]-data[8],8字节,为CAN数据包内传输的数据。
data[9]-data[11]未使用。

注:结构体这样设计的主要原因还是因为要和C代码的驱动接口,做成这样效率会高些。

例如,我们要发送一个,id为5的标准数据帧,数据长度为3,分别是0x01,0x02,0x03,代码如下:
CAN_MESSAGE pktSend = new CAN_MESSAGE();
pktSend.id = 5;
//如果是数据帧就不变,如果是远程帧就
//pktSend.id = pktSend.id | 0x20000000;//remote
//如果是标准帧就不变,如果是扩展帧就
//pktSend.id = pktSend.id | 0x40000000;//extended
pktSend.data[0] = 3;
pktSend.data[1] = 0x01;
pktSend.data[2] = 0x02;
pktSend.data[3] = 0x03;

例如,我们要发送一个,id为55的扩展帧,数据长度为6,分别是0x04,0x04,0x04,0x05,0x05,0x05,代码如下:
CAN_MESSAGE pktSend = new CAN_MESSAGE();
pktSend.id = 5;
//如果是数据帧就不变,如果是远程帧就
//pktSend.id = pktSend.id | 0x20000000;//remote
//如果是标准帧就不变,如果是扩展帧就
pktSend.id = pktSend.id | 0x40000000;//extended
pktSend.data[0] = 6;
pktSend.data[1] = 0x04;
pktSend.data[2] = 0x04;
pktSend.data[3] = 0x04
pktSend.data[4] = 0x05;
pktSend.data[5] = 0x05;
pktSend.data[6] = 0x05;

CAN过滤条件Filter设置
EM335x同样支持数据包过滤功能,设置Filter可以使得CAN只接收自己需要的数据包。

调用EM335X_CAN类的SetFilter方法,可以添加一个过滤条件,或者删除一个已有的过滤条件。例如:
CAN.CAN_SetFilter (hCAN, Filter, false );

第一个参数为CAN句柄,第二个参数为过滤条件参数,为一个CAN_FILTER的结构体,在下面有说明。第三个参数如果为FALSE,则表示添加该过滤条件,如果为TRUE,则表示删除已有的该过滤条件。

有多个过滤条件的情况下,只要数据包可以满足任意一个过滤条件,那么该数据包就可以被接收。

CAN过滤条件Filter结构体定义
CAN_FILTER结构体定义如下:
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct CAN_FILTER
{
[FieldOffset(0)]
public uint id;
[FieldOffset(4)]
public uint mask;
}

这里的过滤逻辑如下:

假设收到的数据包里的id,我们记为id_message,与过滤条件中的filter参数里的id和mask满足条件:(id_message&mask) == (id&mask),那么该数据包就可以接收,也就是说,mask表示需要进行对比的位,如果数据包的id这几位与filter设置里的id的这几位相同,那么该数据包就可以接收。

比如:
一个filter的mask = 0x03,即2进制的b0000 0011,即需要比较最后的两位。
filter的id = 0x02,即2进制的b0000 0010。
那么数据包id如果最后两位为 10,该数据包就可以通过过滤条件被接收。
数据包id = 0xF7,即2进制b1111 0111,无法接收。
数据包id = 0xE6,即2进制b1110 0110,可以接收。

详细信息,可以电话,邮件或论坛提问方式咨询英创工程师。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式主板
    +关注

    关注

    7

    文章

    6085

    浏览量

    35345
收藏 人收藏

    评论

    相关推荐

    C6748开发板求助

    求助各位大佬,使用龙的C6748开发板,运行LINE_IN例程,为什么输入正弦波后,输出的是杂波
    发表于 12-27 17:01

    运动控制卡网络通讯的心跳检测之C#上位机编程

    使用C#上位机编程实现运动控制卡网络通讯的心跳检测功能
    的头像 发表于 12-24 10:54 104次阅读
    运动控制卡网络<b class='flag-5'>通讯</b>的心跳检测之<b class='flag-5'>C#</b>上位机编程

    以太网IO控制卡:C#实时读写时间测试

    C#语言进行ECI IO卡的项目开发和快速读取多个IO状态与上位机交互速度的测试结果
    的头像 发表于 11-21 13:50 218次阅读
    以太网IO控制卡:<b class='flag-5'>C#</b>实时读写时间测试

    中科达荣获2024年软件和信息威廉希尔官方网站 服务优秀企业

    及前百家企业”名单。中科达凭借非凡的威廉希尔官方网站 实力与持续的创新能力,成功入选“2024年度软件和信息威廉希尔官方网站 服务竞争力百强企业”以及“2024年软件和信息威廉希尔官方网站 服务优秀企业”。
    的头像 发表于 10-30 11:44 486次阅读

    加速鲲鹏落地!拓维信息迁移工具荣获鲲鹏原生开发威廉希尔官方网站 认证

    认证。图/拓维·数据库适配中间件取得鲲鹏原生开发N认证在数字化时代的大潮中,信战略作为国家推动信息威廉希尔官方网站 应用创新、保障信息安全与自主可控的关键举措,其重要性日益凸显
    的头像 发表于 09-10 08:03 447次阅读
    加速鲲鹏落地!拓维<b class='flag-5'>信息</b>信<b class='flag-5'>创</b>迁移工具荣获鲲鹏原生<b class='flag-5'>开发</b><b class='flag-5'>威廉希尔官方网站
</b>认证

    威廉希尔官方网站 分享】CAN总线相关知识探讨以及Model3C两路CAN的应用

    CAN总线相关知识,以个位数价格的工业级HMI芯片–Model3C为例, 2路CAN的应用
    的头像 发表于 09-05 10:59 551次阅读
    【<b class='flag-5'>威廉希尔官方网站
</b>分享】<b class='flag-5'>CAN</b>总线相关知识探讨以及Model3<b class='flag-5'>C</b>两路<b class='flag-5'>CAN</b>的应用

    [can开发板] 一款低价can/obd2总线Linux开发

    CAN总线/汽车CAN总线/OBD2通讯/OBD分析仪/USB转CAN/DBC编解码/带远程访问功能的CAN/OBD
    发表于 07-05 16:46

    如何检测can通讯电路的好坏

    CAN(Controller Area Network)是一种基于总线通信的局域网威廉希尔官方网站 ,广泛应用于汽车电子、工业控制等领域。在实际应用中,CAN通讯电路的好坏对整个系统的稳定性和可靠性
    的头像 发表于 06-16 09:42 3041次阅读

    简单易用的以太网数据采集卡应用开发C#

    C#语言以太网数据采集卡的开发
    的头像 发表于 05-17 14:25 780次阅读
    简单易用的以太网数据采集卡应用<b class='flag-5'>开发</b>之<b class='flag-5'>C#</b>

    MGMF442L1C7-MINAS A6N系列 介绍 松下

    电子发烧友网为你提供Panasonic(Panasonic)MGMF442L1C7-MINAS A6N系列 介绍相关产品参数、数据手册,更有MGMF442L1C7-MINAS A6N系列 介绍
    发表于 05-09 19:08
    MGMF442L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介绍</b> 松下

    MGMF292L1C7-MINAS A6N系列 介绍 松下

    电子发烧友网为你提供Panasonic(Panasonic)MGMF292L1C7-MINAS A6N系列 介绍相关产品参数、数据手册,更有MGMF292L1C7-MINAS A6N系列 介绍
    发表于 04-22 19:11
    MGMF292L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介绍</b> 松下

    MGMF242L1C7-MINAS A6N系列 介绍 松下

    电子发烧友网为你提供Panasonic(Panasonic)MGMF242L1C7-MINAS A6N系列 介绍相关产品参数、数据手册,更有MGMF242L1C7-MINAS A6N系列 介绍
    发表于 04-04 19:10
    MGMF242L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介绍</b> 松下

    MGMF132L1C7-MINAS A6N系列 介绍 松下

    电子发烧友网为你提供Panasonic(Panasonic)MGMF132L1C7-MINAS A6N系列 介绍相关产品参数、数据手册,更有MGMF132L1C7-MINAS A6N系列 介绍
    发表于 03-04 18:37
    MGMF132L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介绍</b> 松下

    MGMF092L1C7-MINAS A6N系列 介绍 松下

    电子发烧友网为你提供Panasonic(Panasonic)MGMF092L1C7-MINAS A6N系列 介绍相关产品参数、数据手册,更有MGMF092L1C7-MINAS A6N系列 介绍
    发表于 02-15 18:36
    MGMF092L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介绍</b> 松下

    单轴PSO视觉飞拍与精准输出:EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(七)

    正运动威廉希尔官方网站 EtherCAT控制卡在VS平台采用C#语言实现的各种PSO功能。
    的头像 发表于 01-03 09:50 1045次阅读
    单轴PSO视觉飞拍与精准输出:EtherCAT超高速实时运动控制卡XPCIE1032H上位机<b class='flag-5'>C#</b><b class='flag-5'>开发</b>(七)