SylixOS CAN驱动框架之一

SylixOS应用层代码详

  1. SylixOS CAN驱动框架

    如图 11所示,在SylixOS中CAN总线的框架可分为4层,应用层、系统层、驱动层和硬件层。本文主要介绍应用层的开发和使用。

    11 SylixOS CAN驱动框架

  2. SylixOS CAN设备应用层框架

    在SylixOS中CAN应用层的框架如如图 12所示,在本文档中以调用open,read,write,Ioctl等基本应用层函数举例,方便理解操作。

    12 SylixOS CAN应用层框架

  3. SylixOS CAN应用层函数介绍

  4. CAN的报文格式

    由于SylixOS 的CAN驱动传输过程中涉及到系统层,在系统层中已经定义好了CAN报文的格式(SylixOS系统层以结构体形式定义一帧CAN报文,在下文中会详细介绍),所以必须使用固定的结构体,如程序清单 21所示。

    程序清单 21 CAN报文结构体

    /*********************************************************************************************************

    CAN 帧结构定义

    *********************************************************************************************************/

    typedefstruct {

    UINT32CAN_uiId; /* 标识码 */

    UINT32CAN_uiChannel; /* 通道号 */

    BOOLCAN_bExtId; /* 是否是扩展帧 */

    BOOLCAN_bRtr; /* 是否是远程帧 */

    UCHARCAN_ucLen; /* 数据长度 */

    UCHARCAN_ucData[CAN_MAX_DATA]; /* 帧数据 */

    } CAN_FRAME;

    typedefCAN_FRAME *PCAN_FRAME; /* CAN帧指针类型 */

    /*********************************************************************************************************
      CAN 帧结构定义
    *********************************************************************************************************/
    typedef struct {
        UINT32          CAN_uiId;                                           /*  标识码                      */
        UINT32          CAN_uiChannel;                                      /*  通道号                      */
        BOOL            CAN_bExtId;                                         /*  是否是扩展帧                */
        BOOL            CAN_bRtr;                                           /*  是否是远程帧                */
        UCHAR           CAN_ucLen;                                          /*  数据长度                    */
        UCHAR           CAN_ucData[CAN_MAX_DATA];                           /*  帧数据                      */
    } CAN_FRAME;
    typedef CAN_FRAME  *PCAN_FRAME;                                         /*  CAN帧指针类型               */
    


  5. 发送线程

    发送CAN报文的线程代码如程序清单 22所示。

    程序清单 22 发送线程

    /*********************************************************************************************************

    ** 函数名称: pthread_test_send

    ** 功能描述: CAN 驱动测试 pthread 发送线程

    ** 输 入 : pvArg 线程参数

    ** 输 出 : 线程返回值

    ** 全局变量:

    ** 调用模块:

    *********************************************************************************************************/

    staticVOID *pthread_test_send(VOID *pvArg)

    {

    INTiFd;

    CAN_FRAMEcanframe;

    ssize_tstLen;

    ssize_tstFrameNum;

    char *devname = (char *)pvArg;

    INTiSendCnt;

    iFd = open(devname, O_RDWR, 0666);

    if (iFd < 0) {

    printf("failed to open %s!\n", devname);

    return (LW_NULL);

    }

    if (ioctl(iFd, CAN_DEV_SET_BAUD, _G_iCanBuad)) {

    printf("set baud to %d error.\n", _G_iCanBuad);

    close (iFd);

    return (LW_NULL);

    }

    ioctl(iFd, FIOFLUSH, 0);

    iSendCnt = _G_iSendCnt;

    printf("start %s send test with baud %d, send total = %d.\n", devname, _G_iCanBuad, _G_iSendCnt);

    while (iSendCnt--) {

    canframe.CAN_bExtId = LW_FALSE;

    canframe.CAN_bRtr = LW_FALSE;

    canframe.CAN_ucLen = CAN_MAX_DATA;

    lib_memcpy((CHAR *)canframe.CAN_ucData, "01234567", CAN_MAX_DATA);

    canframe.CAN_uiId = 0;

    stLen = write(iFd, &canframe, sizeof(CAN_FRAME));

    ioctl(iFd, CAN_DEV_STARTUP, 0);

    stFrameNum = stLen / sizeof(CAN_FRAME);

    if (stFrameNum != 1) {

    printf("failed to send can frame!, abort sending\n");

    break;

    }

    printf("send succ\n");

    }

    /*

    * 等待数据全部发送完成

    */

    while (1) {

    INTiNum;

    if (ioctl(iFd, FIONWRITE, &iNum)) {

    printf("error");

    break;

    }

    if (iNum == 0) {

    break;

    }

    }

    ioctl(iFd, CAN_DEV_STARTUP, 0);

    close(iFd);

    return (NULL);

    }

  6. 接收线程

    接收CAN报文的线程代码如程序清单 23所示。

    程序清单 23 接收线程

    /*********************************************************************************************************

    ** 函数名称: pthread_test_recv

    ** 功能描述: CAN 驱动测试 pthread 接收线程

    ** 输 入 : pvArg 线程参数

    ** 输 出 : 线程返回值

    ** 全局变量:

    ** 调用模块:

    *********************************************************************************************************/

    staticVOID *pthread_test_recv(VOID *pvArg)

    {

    INTiFd;

    CAN_FRAMEcanframe;

    ssize_tstLen;

    ssize_tstFrameNum;

    char *devname = (char *)pvArg;

    charcFramInfo[64];

    memset(&canframe, 0, sizeof(CAN_FRAME));

    iFd = open(devname, O_RDWR, 0666);

    if (iFd < 0) {

    printf("failed to open %s!\n", devname);

    return (LW_NULL);

    }

    printf("Successed to open %s!\n", devname);

    if (ioctl(iFd, CAN_DEV_SET_BAUD, _G_iCanBuad)) {

    printf("set baud to %d error.\n", _G_iCanBuad);

    close (iFd);

    return (LW_NULL);

    }

    printf("start %s recv test with baud %d.\n", devname, _G_iCanBuad);

    while (1) {

    stLen = read(iFd, &canframe, sizeof(CAN_FRAME));

    stFrameNum = stLen / sizeof(CAN_FRAME);

    if (stFrameNum != 1) {

    printf("failed to recv can frame, abort recving!\n");

    break;

    } else {

    sprintf(cFramInfo, "id=%d, len=%d, data=%02x %02x %02x %02x %02x %02x %02x %02x\n",

    canframe.CAN_uiId, (INT)canframe.CAN_ucLen,

    canframe.CAN_ucData[0],

    canframe.CAN_ucData[1],

    canframe.CAN_ucData[2],

    canframe.CAN_ucData[3],

    canframe.CAN_ucData[4],

    canframe.CAN_ucData[5],

    canframe.CAN_ucData[6],

    canframe.CAN_ucData[7]);

    printf(cFramInfo);

    }

    }

    close(iFd);

    return (NULL);

    }

  7. 输入参数分析

    输入参数分析函数代码如程序清单 24所示。

    程序清单 24 输入参数解析

    /*********************************************************************************************************

    ** 函数名称: canParseArg

    ** 功能描述: 参数解析

    ** 输 入 : NONE

    ** 输 出 : ERROR_CODE

    ** 全局变量:

    ** 调用模块:

    *********************************************************************************************************/

    staticintcanParseArg (intargc, char *argv[])

    {

    intc;

    inttmp;

    _G_iCanOp = __can_ro;

    if (argc < 1) {

    return (0);

    }

    while (1) {

    c = getopt(argc, argv, "d:rwxb:c:");

    if (c == -1) {

    break;

    }

    switch (c) {

    case'r': _G_iCanOp = __can_ro; break;

    case'w': _G_iCanOp = __can_wo; break;

    case'x': _G_iCanOp = __can_rw; break;

    case'b':

    if (sscanf(optarg, "%d", &tmp) == 1) {

    if (baudValid(tmp)) {

    printf("set baud %d\r\n", tmp);

    _G_iCanBuad = tmp;

    }

    }

    break;

    case'd':

    strncpy(_G_cCanDevName, optarg, 32);

    _G_cCanDevName[31] = 0;

    _G_iCanDev = _G_cCanDevName;

    break;

    case'c':

    if (sscanf(optarg, "%d", &tmp) == 1) {

    if (tmp > 0) {

    _G_iSendCnt = tmp;

    }

    }

    break;

    default:

    return (-1);

    }

    }

    return (0);

    }

    /*********************************************************************************************************

    entry :

    ./can_test -d /dev/can0 -r -b 125000

    ./can_test -d /dev/can0 -w -b 125000

    ./can_test -d /dev/can0 -x -b 125000

    *********************************************************************************************************/

  8. Main函数及线程创建函数

    Main函数及线程创建函数如程序清单 25所示。

    程序清单 25 main函数

    intmain (intargc, char *argv[])

    {

    intret;

    ret = canParseArg(argc, argv);

    if (ret) {

    printf("invalid options.\n");

    return (-1);

    }

    canTestStart(_G_iCanDev, _G_iCanOp);

    return 0;

    }

    /*********************************************************************************************************

    ** 函数名称: canTestStart

    ** 功能描述: CAN 测试

    ** 输 入 : NONE

    ** 输 出 : ERROR_CODE

    ** 全局变量:

    ** 调用模块:

    *********************************************************************************************************/

    INTcanTestStart (char *pcdevname, intrw)

    {

    pthread_ttid_recv;

    pthread_ttid_send;

    INTiError = ERROR_NONE;

    if (rw & __can_ro) {

    iError |= pthread_create(&tid_recv, NULL, pthread_test_recv, pcdevname);

    pthread_join(tid_recv, NULL);

    }

    if (rw & __can_wo) {

    iError = pthread_create(&tid_send, NULL, pthread_test_send, pcdevname);

    pthread_join(tid_send, NULL);

    }

    return (iError == 0 ? ERROR_NONE : PX_ERROR);

    }

    Main函数主要是用创建收发线程和输入参数捕获

猜你喜欢

转载自blog.csdn.net/Best_Ccc/article/details/55104635
今日推荐