全部文档
OneOS简介 硬件支持 编译构造工具 API参考文档 高级语言 用户编程手册 应用笔记 FAQ

CAN设备


API 列表

接口 说明
os_device_find 查找设备
os_device_open 打开设备
os_device_read 读取数据
os_device_write 写入数据
os_device_control 控制设备
os_device_set_rx_indicate 设置接收回调函数
os_device_close 关闭设备

os_device_find

该函数用于查找 CAN 设备,应用程序根据 CAN设备名称通过该函数查找 CAN 设备并获取设备指针,进而可以操作 CAN设备,函数原型如下:

os_device_t *os_device_find(const char *name);
参数 说明
name CAN设备名称
返回 说明
设备指针 查找到CAN设备将返回CAN设备的指针
OS_NULL 没有找到CAN设备

os_device_open

该函数用于开启 CAN 设备,通过CAN设备指针,应用程序可以打开和关闭设备,打开设备时,会检测设备是否已经初始化,没有初始化则会默认调用初始化接口进行初始化,函数原型如下:

os_err_t os_device_open(os_device_t *dev, os_uint16_t oflag);
参数 说明
dev CAN设备名称
oflag 打开设备模式标志
返回 说明
OS_EOK 设备打开成功
OS_EBUSY 如果设备注册时指定的参数中包括 OS_DEVICE_FLAG_STANDALONE 参数,此设备将不允许重复打开
其他错误码 设备打开失败

OneOS当前的 CAN 设备驱动框架支持中断接收和中断发送模式。故oflag 参数支持下列取值 (可以采用或的方式实现多种模式的支持):

#define OS_DEVICE_FLAG_INT_RX           0x100     /**< INT mode on Rx */
#define OS_DEVICE_FLAG_INT_TX           0x400     /**< INT mode on Tx */

os_device_control

该函数用于CAN 设备参数修改,通过命令控制字,应用程序可以对 CAN 设备参数进行配置,函数原型如下:

os_err_t os_device_control(os_device_t *dev, int cmd, void *arg);
参数 说明
dev CAN设备指针
cmd 控制命令
arg 控制参数
返回 说明
OS_EOK 函数执行成功
其他错误码 执行失败

arg(控制参数)根据命令不同而不同,cmd(控制命令)可取以下值:

#define OS_DEVICE_CTRL_RESUME       0x01     /* resume device */
#define OS_DEVICE_CTRL_SUSPEND      0x02     /* suspend device */
#define OS_DEVICE_CTRL_CONFIG       0x03     /* configure device */

#define OS_CAN_CMD_SET_FILTER       0x13     /* 设置硬件过滤表 */
#define OS_CAN_CMD_SET_BAUD         0x14     /* 设置波特率 */
#define OS_CAN_CMD_SET_MODE         0x15     /* 设置 CAN 工作模式 */
#define OS_CAN_CMD_SET_PRIV         0x16     /* 设置发送优先级 */
#define OS_CAN_CMD_GET_STATUS       0x17     /* 获取 CAN 设备状态 */
#define OS_CAN_CMD_SET_STATUS_IND   0x18     /* 设置状态回调函数 */
#define OS_CAN_CMD_SET_BUS_HOOK     0x19     /* 设置 CAN 总线钩子函数 */

os_device_write

该函数用于发送 CAN 数据,在发送数据前务必正确开启CAN设备,函数原型如下:

os_size_t os_device_write(os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size)
参数 说明
dev CAN设备指针
pos 写入数据偏移量,此参数 CAN 设备默认为0(未使用)
buffer CAN 消息类型的指针
size CAN 消息大小
返回 说明
>0 发送的CAN消息量大小
=0 数据发送失败

其中buffer一般指向CAN消息结构体,其原型如下:

struct os_can_msg
{
    os_uint32_t id  : 29;    /* can_id:为适配扩展长度29位,标准格式时11位 */
    os_uint32_t ide : 1;     /* 标识扩展帧位 */
    os_uint32_t rtr : 1;     /* 标识远程帧位 */
    os_uint32_t rsv : 1;     /* 保留位 */
    os_uint32_t len : 8;     /* 数据段长度 */
    os_uint32_t priv : 8;    /* 报文发送优先级 */
    os_int32_t hdr : 8;      /* 硬件过滤表号 */
    os_uint32_t reserved : 8; /* 保留位 */
    os_uint8_t data[8];       /* can数据 */
};

os_device_set_rx_indicate

该函数用于设置CAN接收的回调函数,当CAN设备在中断模式下接收到总线数据时,会产生中断,此时如设置了中断回调函数,则可通过回调函数通知上层应用task对接收的数据进行处理,函数原型如下:

os_err_t os_device_set_rx_indicate(os_device_t *dev, os_err_t (*rx_ind)(os_device_t *dev, os_size_t size))
参数 说明
dev 设备指针,CAN应用中则为CAN设备指针
rx_ind 接收中断回调函数指针
dev 回调函数参数1:设备指针
size 回调函数参数2:缓冲区数据大小
返回 说明
OS_EOK 回调函数设置成功

回调函数的功能根据应用程序的需要由调用者实现。当CAN接收产生中断时,会将CAN设备指针(dev)和数据大小(size)传给回调函数,可供应用程序使用。一般的,接收回调函数可发送信号量或者事件通知CAN数据解析处理任务有数据到达,便于上次应用及时对数据进行处理。

os_device_read

该函数用于接收 CAN 数据,函数原型如下:

os_size_t os_device_read(os_device_t *dev, os_off_t pos, void *buffer, os_size_t size)
参数 说明
dev CAN设备指针
pos 写入数据偏移量,此参数 CAN 设备默认为0(未使用)
buffer CAN 消息类型的指针
size CAN 消息大小
返回 说明
>0 接收的CAN消息量大小
=0 数据接收失败

os_device_close

该函数用于关闭 CAN 设备,当不再使用CAN设备时,可以关闭 CAN 设备(关闭、打开设备接口需配对使用,以保证设备处于关闭状态),函数原型如下:

os_err_t os_device_close(os_device_t *dev)
参数 说明
dev CAN设备指针
返回 说明
OS_EOK 关闭设备成功
OS_ERROR 设备已经完全关闭,不能重复关闭设备
其他错误码 关闭设备失败

CAN参数配置示例:

参数设置主要通过os_device_control函数实现。各项参数的具体设置如下所示:

/ 确定CAN设备名称,并查找设备是否存在 /

#define CAN_DEV_NAME       "can1"           /* CAN device name */
static os_device_t *can_dev;                /* CAN device pointer */
os_err_t res;
can_dev = os_device_find(CAN_DEV_NAME);     /* Find can devices */

/ 中断方式发送接收打开CAN设备 /

res = os_device_open(can_dev, OS_DEVICE_FLAG_INT_TX | OS_DEVICE_FLAG_INT_RX);

/ OS_CAN_CMD_SET_BAUD:设置CAN设备的波特率 /

res = os_device_control(can_dev, OS_CAN_CMD_SET_BAUD, (void *)CAN500kBaud);

/ OS_CAN_CMD_SET_MODE:设置CAN的工作模式,本例设置为回环模式 /

res = os_device_control(can_dev, OS_CAN_CMD_SET_MODE, (void *)OS_CAN_MODE_LOOPBACK);

/ OS_CAN_CMD_GET_STATUS:读取CAN设备的状态 /

res = os_device_control(can_dev, OS_CAN_CMD_GET_STATUS, &status);

/ OS_CAN_CMD_SET_FILTER:设置CAN硬件过滤表 /

struct os_can_filter_item item[1] =
{
    OS_CAN_FILTER_ITEM_INIT(0x01, 0, 0, 1, 0x01, OS_NULL, OS_NULL),
};
struct os_can_filter_config cfg = {1, 1, item};
res = os_device_control(can_dev, OS_CAN_CMD_SET_FILTER, &cfg);

其中CAN的过滤设置主要通过结构体实现:

/* filter结构体 */
struct os_can_filter_item
{
    os_uint32_t id  : 29;   /* CAN message ID */
    os_uint32_t ide : 1;    /* Extended frame flag */
    os_uint32_t rtr : 1;    /* Remote frame flag */
    os_uint32_t mode : 1;   /* can Filter table mode */
    os_uint32_t mask;       /* ID 掩码,0 表示对应的位不关心,1 表示对应的位必须匹配 */
    os_int32_t hdr;         /* -1 表示不指定过滤表号,对应的过滤表控制块也不会被初始化,正数为过滤表号,对应的过滤表控制块会被初始化 */
#ifdef OS_CAN_USING_HDR
    /* 过滤表回调函数 */
    os_err_t (*ind)(os_device_t dev, void *args , os_int32_t hdr, os_size_t size);
    /* 回调函数参数 */
    void *args;
#endif /*OS_CAN_USING_HDR*/
};

/* 为方便初始化过滤表,开发了对应的过滤表宏 */
#define OS_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask,ind,args) \
     {(id), (ide), (rtr), (mode), (mask), -1, (ind), (args)}

/* 过滤表配置前还需指定过滤表配置控制块 */
struct os_can_filter_config
{
    os_uint32_t count;       /* 过滤表数量 */
    os_uint32_t actived;      /* 过滤表激活选项,1 表示初始化过滤表控制块,0 表示不初始化过滤表控制块 */
    struct os_can_filter_item *item;   /* 过滤表指针,可指向一个过滤表数组 */
};

上述有关CAN的设置均可通过os_device_control的返回值判断是否设置成功。

CAN收发数据示例:

#define CAN_DEV_NAME       "can1"   
static struct os_semaphore rx_sem;    
static os_device_t *can_dev;  
static os_err_t can_rx_call(os_device_t *dev, os_size_t size)
{
    os_sem_post(&rx_sem);

    return OS_EOK;
}

static void can_rx_task(void *parameter)
{
    int i;
    //os_err_t res;
    struct os_can_msg rxmsg = {0};

    os_device_set_rx_indicate(can_dev, can_rx_call);
    while (1)
    {

        rxmsg.hdr = -1;
        os_sem_wait(&rx_sem, OS_IPC_WAITING_FOREVER);
        os_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
        os_kprintf("ID:%x ", rxmsg.id);
        for (i = 0; i < 8; i++)
        {
            os_kprintf("%2x ", rxmsg.data[i]);
        }

        os_kprintf("\n");
    }
}

int can_start(int argc, char *argv[])
{
    struct os_can_msg msg = {0};
    os_err_t res;
    os_size_t  size;
    os_task_t *can_task;
    char can_name[OS_NAME_MAX];

    if (argc == 2)
    {
        strncpy(can_name, argv[1], OS_NAME_MAX);
    }
    else
    {
        strncpy(can_name, CAN_DEV_NAME, OS_NAME_MAX);
    }
    can_dev = os_device_find(can_name);
    if (!can_dev)
    {
        os_kprintf("find %s failed!\n", can_name);
        return OS_ERROR;
    }
    os_sem_init(&rx_sem, "rx_sem", 0, OS_IPC_FLAG_FIFO);

    res = os_device_open(can_dev, OS_DEVICE_FLAG_INT_TX | OS_DEVICE_FLAG_INT_RX);
    OS_ASSERT(res == OS_EOK);
    res = os_device_control(can_dev, OS_CAN_CMD_SET_BAUD, (void *)CAN500kBaud);
    res = os_device_control(can_dev, OS_CAN_CMD_SET_MODE, (void *)OS_CAN_MODE_LOOPBACK);


    can_task = os_task_create("can_rx", can_rx_task, OS_NULL, 1024, 25, 10);
    if (can_task != OS_NULL)
    {
        os_task_startup(can_task);
    }
    else
    {
        os_kprintf("create can_rx task failed!\n");
    }
    return res;
}
SH_CMD_EXPORT(can_start, can_start,"can device sample");


void send_can_data(int argc, char *argv[])
{
    struct os_can_msg msg = {0};
    os_size_t  size;
    msg.id = 0x68;             
    msg.ide = OS_CAN_STDID;    
    msg.rtr = OS_CAN_DTR;      
    msg.len = 8;                
    msg.data[0] = 0x10;
    msg.data[1] = 0x11;
    msg.data[2] = 0x12;
    msg.data[3] = 0x13;
    msg.data[4] = 0x14;
    msg.data[5] = 0x15;
    msg.data[6] = 0x16;
    msg.data[7] = 0x17;
    size = os_device_write(can_dev, 0, &msg, sizeof(msg));
    if (size == 0)
    {
        os_kprintf("can dev write data failed!\n");
    }
}
SH_CMD_EXPORT(send_can_data, send_can_data,"send can data");

例程主要由can_start和send_can_data组成,并将两个函数导入到SH命令行中。其中send_can_data主要发送一组CAN数据,can_start实现的功能如下图所示:

can_start

在串口的命令行中输入can_start启动CAN设备后,再输入send_can_data即可接收到回显的发送数据,如下所示:

sh />can_start
sh />send_can_data
sh />ID:68 10 11 12 13 14 15 16 17 
sh />send_can_data
sh />ID:68 10 11 12 13 14 15 16 17

results matching ""

    No results matching ""

    返回顶部