英创新CAN驱动接口调用方法及说明

供稿:成都英创信息技术有限公司

  • 关键词:英创,CAN驱动接口
  • 作者:emtronix
  • 摘要:用户可从英创开发光盘中或联系英创工程师获得CAN例程源码。参考例程使用英创已经封装好的.h及.cpp库文件可以使开发更方便。

  用户可从英创开发光盘中或联系英创工程师获得CAN例程源码。参考例程使用英创已经封装好的.h及.cpp库文件可以使开发更方便。


注册表设置项说明


  CAN驱动设置参数位于注册表[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN1]及[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN2]下



  主要配置参数项:

  TxTimeout :发送超时时间,单位ms。

  BusErrorReport :错误帧上报标记,0:不上报,1:上报错误帧


  设置程序可以连接英创工程师获得。


CAN打开及关闭


  打开关闭采用标准的流式设备驱动接口CreateFile及CloseHandle,设备名为”CAN1:”及”CAN2:”


  调用示例如下:


  //打开CAN1

  HANDLE hCan;

  hCan = CreateFile( L”CAN1:”, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);


  //关闭CAN

  CloseHandle(hCan);


CAN波特率设置


  参考CAN例程,对驱动的DeviceIoCon trol操作已封装在SetBaud函数中。


  BOOL SetBaud(HANDLE hCan, DWORD dwBaud)

  参数hCan:CreateFile打开CAN返回的设备句柄

  参数dwBaud:波特率,单位bps

  返回值:TRUE 设置成功,FALSE 设置失败


  调用示例如下:

  //设置波特率250bps CAN

  SetBaud(m_hCan, 250000);


CAN过滤设置


  调用方法

  参考CAN例程,对驱动的DeviceIoCon trol操作已封装在SetFilter函数中。


  BOOL SetFilter(HANDLE hCan, PCAN_FILTER pFilter, DWORD num)

  参数hCan:CreateFile打开CAN返回的设备句柄

  参数pFilter:过滤器结构体数组指针

  参数num:过滤器结构体数组长度,最大为4

  返回值:TRUE 设置成功,FALSE 设置失败


  注:此函数如果重复调用,生效的为最后一次调用设置值。


CAN_FILTER过滤器结构体定义



  typedef struct _can_filter

  {

    CAN_ID can_id;

    CAN_ID can_mask;

  } CAN_FILTER, *PCAN_FILTER


  过滤器由id和mask组成,设置的过滤器组数最大4个。CAN包能满足其中一组过滤器以下条件才能接收

  CAN包id & 过滤器mask = 过滤器id


  即,2进制中,过滤MASK为1的对应位需和过滤ID值一致,示例表


  调用示例如下


  //设置一组寄存器

  CAN_FILTER      Filter[4];

  memzero(Filter, sizeof(CAN_FILTER));

  Filter[0].can_id.id = 5;

  Filter[0].can_mask.id = 22;

  SetFilter(m_hCan, Filter, 1);


CAN发送/接收


  发送接收同样采用标准的流式设备驱动接口ReadFile及WriteFile


  调用方法

  参考CAN例程,封装好的函数定义。

  int     WriteCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){

      DWORD dwLen;

      if(!WriteFile( hCan, (char *)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 )) return 0;

      return dwLen/sizeof(CAN_FRAME);

  }


  int     ReadCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){

      DWORD dwLen;

      if(!ReadFile( hCan, (char *)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 )) return 0;

      return dwLen/sizeof(CAN_FRAME);

  }


  参数hCan:CreateFile打开CAN返回的设备句柄

  参数pFrame:帧结构体数组指针

  参数num:帧结构体数组长度,默认值1,可空

  返回值:发送/接收的数据包个数


  注:发送函数为阻塞函数,超时时间可以在注册表中设置,默认1000ms。

    发送失败后,应用程序应当自行判断是否需要重新发送。


  接收函数应当单独开一个接收线程,并配合WaitCANEvent函数使用,参考下一节。


CAN_FRAME数据帧结构体定义


  typedef struct{

       unsigned int id:29;

       unsigned int error:1;      

       unsigned int remote:1;

       unsigned int extended:1;

  }CAN_ID;


  typedef struct _can_frame

  {

      CAN_ID   can_id;        /* 32 bit CAN_ID + EFF/RTR/ERR flags */

      BYTE    can_dlc;     /* frame payload length in byte (0 ..CAN_MAX_DLEN) */

      BYTE    data[CAN_MAX_DLEN];

  } CAN_FRAME, *PCAN_FRAME;


  调用示例如下:



  DWORD dwNum;

  //发送

  CAN_FRAME Sendframe;

  memzero(Sendframe, sizeof(CAN_FRAME));

  Sendframe.can_id.id = 6;

  m_Sendframe.data[0] = 0x01;

  m_Sendframe.can_dlc = 1;

   dwNum = WriteCAN(hCan, &Sendframe);


  //接收

  CAN_FRAME   Revframe[MAX_ARRAY];

  dwNum = ReadCAN(hCan, Revframe, MAX_ARRAY);


WaitCANEvent函数使用


  如果轮询方式接收CAN包,系统负荷会过高,采用事件方式事半功

  WaitCANEvent为等待CAN接收事件的阻塞函数,通过返回值可以判断是否有CAN数据接收。


  BOOL WaitCANEvent( HANDLE hDevice, LPDWORD lpEvtMask, DWORD dwTimeout )

  参数hDevice:CreateFile打开CAN返回的设备句柄

  参数lpEvtMask:返回事件类型,新驱动目前恒为0

  参数dwTimeout:超时时间

  返回值:FALSE 等待超时,TRUE 有数据帧收到


  接收线程调用示例



  //主线程中开启接收线程

  m_hRecvThread = CreateThread(0, 0, RecvTread, this, 0, NULL);


  //接收线程函数定义

  DWORD Ctest_can_v2Dlg::RecvTread(LPVOID lparam)

  {

      Ctest_can_v2Dlg* pDlg = (Ctest_can_v2Dlg*)lparam;

      DWORD       dwEvtMask;

      int         num;

      CAN_FRAME   rbuf[MAX_ARRAY];


     while(!pDlg->m_bThreadStop)

      {

          if(WaitCANEvent(pDlg->m_hCan, &dwEvtMask, 200))

          {

              if( dwEvtMask == 0 )      // 接收到数据包

              {

                  num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);

                  while( num )

                  {

                      OnRecv(pDlg, rbuf, num);        //调用回调函数处理数据

                      num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);

                  }

              }

              else        //258

              {

            }

        }

    }

      return 0;

  }


错误帧定义


  当设置注册表选项,允许接收错误帧后,CAN总线上的出错信息将以帧的形式上报上来。

  错误帧的帧结构体中,值为1,可通过该值判断是接收到的数据帧还是驱动上报的错误帧。

  if(Frame.can_id.error){

    //错误帧

  }

  else{

    //数据帧;

  }


  错误帧详细定义,请参数手册《CAN错误帧定义》。


精简掉的接口


  新CAN驱动能够自动复位CAN总线,不需要再手动复位,所以之前ResetCAN,StartCAN,StopCAN精简掉了。

  

  SetCANLoop功能实用性不大,故精简掉。

  

  但是为了兼容老驱动,这些函数依然可以正常调用。


  相关测试例程可以联系英创工程师获得。


  成都英创信息技术有限公司

  http://www.emtronix.com

发布时间:2017年1月3日 15:25  人气:   审核编辑(李晨晖)
更多内容请访问(成都英创信息技术有限公司
相关链接

我有需求