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

    文章

    6107

    浏览量

    37171
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    RK3576 单板机 C/Python/MQTT 应用开发手册(二)

    本文为龙科技RK3576 单板机应用开发指南,包含开发环境配置、GDB 调试、外设控制(LED/CAN/ 串口)、Python 开发及 M
    的头像 发表于 04-21 10:43 100次阅读
    RK3576 单板机 <b class='flag-5'>C</b>/Python/MQTT 应用<b class='flag-5'>开发</b>手册(二)

    RK3576 单板机 C/Python/MQTT 应用开发手册(一)

    本文为龙科技RK3576 单板机应用开发指南,包含开发环境配置、GDB 调试、外设控制(LED/CAN/ 串口)、Python 开发及 M
    的头像 发表于 04-20 13:55 345次阅读
    RK3576 单板机 <b class='flag-5'>C</b>/Python/MQTT 应用<b class='flag-5'>开发</b>手册(一)

    C#运动控制开源(一): CAD导图和小线段速度前瞻的优化之CAD导图

    C#实现CAD解析及如何对小线段轨迹进行运动前瞻
    的头像 发表于 04-02 14:33 1349次阅读
    <b class='flag-5'>C#</b>运动控制开源(一): CAD导图和小线段速度前瞻的优化之CAD导图

    RK3562 单板机 Linux 应用开发实战手册:LED/CAN/TCP/UART 案例与 Python 开发(二)

    本文为龙科技RK3562 单板机应用开发指南,核心包含交叉编译工具链部署、GDB 远程调试,以及 LED、CAN、TCP/UDP、MQTT 等实战案例。文档支持 C/
    的头像 发表于 02-25 11:35 1785次阅读
    RK3562 单板机 Linux 应用<b class='flag-5'>开发</b>实战手册:LED/<b class='flag-5'>CAN</b>/TCP/UART 案例与 Python <b class='flag-5'>开发</b>(二)

    瑞萨RA系列FSP库开发实战指南之I2C通讯协议的物理层和协议层简介

    I2C通讯协议(Inter-Integrated Circuit)是由 Philips公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN
    的头像 发表于 01-21 10:10 4118次阅读
    瑞萨RA系列FSP库<b class='flag-5'>开发</b>实战指南之I2<b class='flag-5'>C</b><b class='flag-5'>通讯</b>协议的物理层和协议层简介

    C#上位机实战开发指南

    电子发烧友网站提供《C#上位机实战开发指南.pdf》资料免费下载
    发表于 01-11 17:15 6次下载

    卡塔尔通讯信息技术部与Ooredoo电信公司一行来访达实智能开展培训

    2026年1月7日至8日,卡塔尔通讯信息技术部(MCIT)以及卡塔尔Ooredoo电信公司一行来访达实智能开展培训。达实智能董事长刘磅、副总裁易鸿、海湾区域经理海乐姆(阿拉伯籍)等陪同接待。
    的头像 发表于 01-09 16:03 913次阅读

    AI智能体开发C#软件的临时方案

    AI智能体 (Agent) 可以帮你生成完整的C# 工程,包括主体代码、WinForm界面设计和引用添加。但是目前Visual Studio (VS) 的Agent功能好像还不太完善,时常出一些奇怪
    的头像 发表于 12-30 10:50 977次阅读
    AI智能体<b class='flag-5'>开发</b><b class='flag-5'>C#</b>软件的临时方案

    【瑞萨RA6E2地奇星开发板试用】介绍、环境搭建、工程测试

    【瑞萨RA6E2地奇星开发板试用】介绍、环境搭建、工程测试 本文介绍了瑞萨 RA6E2 地奇星开发板的基本信息,包括产品特点、参数资源、
    发表于 12-07 15:27

    龙芯中科助力2025教育信息技术应用创新大赛成功举办

    2025年11月13日-15日,由中国教育技术协会主办、浙江大学与中国教育技术协会网络安全专业委员会联合承办,中国电子工业标准化技术协会信息技术应用创新工作委员会、浙江高校信
    的头像 发表于 11-21 16:23 931次阅读

    佛瑞亚如何通过信息技术推动业务增长

    在数字化、信息化的浪潮下,信息技术已经不仅是后台工具,更成为驱动企业发展的关键力量。本期Women Inspiring Mobility,我们采访了佛瑞亚中国区信息技术总监马瑛,了解她和团队如何将
    的头像 发表于 07-29 14:00 1058次阅读

    飞腾主板为信产业发展提高硬实力

    信息技术飞速发展的当下,信产业已成为我国实现科技自立自强、保障国家信息安全的关键领域。信,即信息技术应用创新,其核心目标是实现
    的头像 发表于 07-22 18:20 841次阅读

    DEKRA德凯成为沙特通信和信息技术设备技术法规认证机构

    近日,DEKRA德凯成功获得沙特标准、计量和质量组织(SASO)认可,正式成为沙特通信和信息技术设备技术法规(Technical Regulation for Communications
    的头像 发表于 07-15 14:27 1061次阅读

    C#上位机与运动控制卡网络通讯的周期上报

    使用C#上位机编程实现运动控制卡网络通讯的周期上报功能
    的头像 发表于 06-26 13:59 1016次阅读
    <b class='flag-5'>C#</b>上位机与运动控制卡网络<b class='flag-5'>通讯</b>的周期上报

    科普|信是什么?一文读懂“信息技术应用创新”战略

    什么是信?信,即“信息技术应用创新”,是国家推动IT系统自主可控、安全可控的重要战略工程。它不仅是技术层面的创新,更承载着保障国家网络安全、推动产业升级和实现数字主权的重任。简单来
    的头像 发表于 06-13 10:06 9631次阅读
    科普|信<b class='flag-5'>创</b>是什么?一文读懂“<b class='flag-5'>信息技术</b>应用创新”战略