四时宝库

程序员的知识宝库

开启CAN通信学习(二)——基于Kvaser的CAN通信案例

1 案例硬件介绍

Kvaser是瑞典的一家专门提供CAN和LIN总线分析仪及数据记录仪的公司,在CAN产品开发领域已经有近30年的经验,本案例选择的CAN通信硬件型号是Kvaser Leaf Light v2,产品如下图所示:

公众号dotNet工控上位机:thinger_swj】

为了配套该产品,还准备了一个威柏电子(Westpac)提供的模拟控制器RL78 CAN ECU来进行功能测试,如下图所示,该模拟控制器可以通过上位机控制,实现速度调节及转向灯控制。

硬件准备就绪,这个接线也比较简单,由于是已经集成好的DB9插头,所以ECU与CAN卡之间直接公头和母头对接就可以了,CAN卡通过USB接入电脑,安装好驱动后,就可以通过电脑的设备管理器中看到CAN设备了,如下图所示:

2 案例开发准备

CAN通信开发需要调用厂家提供好的一些SDK或者Lib库,而且厂家一般都是提供一些Demo,Demo中包含多种不同的语言,我们找到dotnet或者C#或者cs的字眼,然后打开相关的案例进行研究。Kvaser并没有提供类似的Demo,只是提供了一个Kvaser CANLib SDK的软件,安装之后打开包含以下内容:

接着打开dotnet >> win32 >> fw40,找到下面这些dll,我们的开发主要就是基于这个文件夹里面的dll来实现的,dotnet下面有win32和x64两个文件夹,这里根据不同的项目平台版本,选择相应的dll。

Kvaser针对CANLib库的使用,提供了一个HTML帮助手册,如下图所示,如果对于某个函数或者参数不理解,可以通过这个帮助手册来查找:!

虽然有了dll以及帮助手册,但是对于应该调用哪些方法,调用方法之间的顺序,很多时候我们仍然是一头雾水,下面的这个开发指南应该是雪中送炭。

3 案例程序开发

万事具备之后,这时候我们就可以进行程序开发了,先创建一个Windows窗体应用程序,项目名称为thinger.com.kvaserCANECU,界面初步设计如下图所示:

公众号dotNet工控上位机:thinger_swj】

(1)UI界面设计完成后,首先将canlibCLSNET.dll复制到项目中并添加引用

(2)在窗体初始化中调用canInitializeLibrary初始化并初始化波特率

        public FrmMain()        {            InitializeComponent();            //初始化CanLibrary            Canlib.canInitializeLibrary();            this.cmb_BaudRate.Items.Add("500000");            this.cmb_BaudRate.Items.Add("250000");            this.cmb_BaudRate.SelectedIndex = 1;        }

(3)刷新按钮事件下,获取所有能获取到的CAN通信信息

        private void btn_Refresh_Click(object sender, EventArgs e)        {            int count = 0;            canstatus = Canlib.canGetNumberOfChannels(out count);            if (canstatus != Canlib.canStatus.canOK)            {                HandleError("canGetNumberOfChannels", canstatus);                return;            }            this.cmb_Channel.Items.Clear();            for (int i = 0; i < count; i++)            {                string result = string.Empty;                object obj;                //获取通道                canstatus = Canlib.canGetChannelData(i, Canlib.canCHANNELDATA_CHANNEL_NAME, out obj);                HandleError("canCHANNELDATA_CHANNEL_NAME", canstatus);                result += obj.ToString();?                //获取序列号                canstatus = Canlib.canGetChannelData(i, Canlib.canCHANNELDATA_CARD_SERIAL_NO, out obj);                HandleError("canCHANNELDATA_CARD_SERIAL_NO", canstatus);                result += "   " + obj.ToString();                this.cmb_Channel.Items.Add(result);            }            if (count > 0)                this.cmb_Channel.SelectedIndex = 0;        }?        private void HandleError(string cmd, Canlib.canStatus state)        {            if (state != Canlib.canStatus.canOK)            {                string error = string.Empty;                Canlib.canGetErrorText(state, out error);                this.tssl_Info.Text = cmd + " Error:" + error;            }            else            {                this.tssl_Info.Text = "系统正常";            }        }?

(4)打开按钮事件中,实现打开CAN卡及关闭CAN卡的功能

        private void btn_Open_Click(object sender, EventArgs e)        {            if (this.btn_Open.Text == "打开")            {                //打开                handle = Canlib.canOpenChannel(this.cmb_Channel.SelectedIndex,                 Canlib.canOPEN_OVERRIDE_EXCLUSIVE + Canlib.canOPEN_ACCEPT_VIRTUAL);                //设置波特率                canstatus = Canlib.canSetBitrate(handle, Convert.ToInt32(this.cmb_BaudRate.Text));                HandleError("canSetBitrate", canstatus);                //BUS ON                canstatus = Canlib.canBusOn(handle);                if (canstatus != Canlib.canStatus.canOK)                {                    HandleError("canBusOn", canstatus);                    return;                }                else                {                    this.btn_Open.Text = "关闭";                 }            }            else            {                Canlib.canClose(handle);?                this.btn_Open.Text = "打开";            }        }

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接