/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-06-25 misonyo first implementation. */ /* * 程序清单:这是一个 CAN 设备使用例程 * 例程导出了 can_sample 命令到控制终端 * 命令调用格式:can_sample can2 * 命令解释:命令第二个参数是要使用的 CAN 设备名称,为空则使用默认的 CAN 设备 * 程序功能:通过 CAN 设备发送一帧,并创建一个线程接收数据然后打印输出。 */ #include #include "rtdevice.h" #define CAN_DEV_NAME "can2" /* CAN 设备名称 */ static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */ static rt_device_t can_dev; /* CAN 设备句柄 */ /* 接收数据回调函数 */ static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size) { /* CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */ rt_sem_release(&rx_sem); return RT_EOK; } static void can_rx_thread(void *parameter) { int i; struct rt_can_msg rxmsg = {0}; /* 设置接收回调函数 */ rt_device_set_rx_indicate(can_dev, can_rx_call); #ifdef RT_CAN_USING_HDR rt_err_t res; struct rt_can_filter_item items[5] = { RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ff,hdr为-1,设置默认过滤表 */ RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ff,hdr为-1 */ RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211,hdr为-1 */ RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), /* std,match ID:0x486,hdr为-1 */ {0x555, 0, 0, 0, 0x7ff, 7,} /* std,match ID:0x555,hdr为7,指定设置7号过滤表 */ }; struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有5个过滤表 */ /* 设置硬件过滤表 */ res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg); RT_ASSERT(res == RT_EOK); #endif while (1) { /* hdr值为-1,表示直接从uselist链表读取数据 */ rxmsg.hdr = -1; /* 阻塞等待接收信号量 */ rt_sem_take(&rx_sem, RT_WAITING_FOREVER); /* 从CAN读取一帧数据 */ rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg)); /* 打印数据ID及内容 */ rt_kprintf("ID:%x ", rxmsg.id); for (i = 0; i < 8; i++) { rt_kprintf("%2x ", rxmsg.data[i]); } rt_kprintf("\n"); } } int can_sample(int argc, char *argv[]) { struct rt_can_msg msg = {0}; rt_err_t res; rt_size_t size; rt_thread_t thread; char can_name[RT_NAME_MAX]; if (argc == 2) { rt_strncpy(can_name, argv[1], RT_NAME_MAX); } else { rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX); } can_dev = rt_device_find(can_name); if (!can_dev) { rt_kprintf("find %s failed!\n", can_name); return RT_ERROR; } /* 初始化CAN接收信号量 */ rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); /* 以中断接收及发送方式打开CAN设备 */ res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX); RT_ASSERT(res == RT_EOK); thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10); if (thread != RT_NULL) { rt_thread_startup(thread); } else { rt_kprintf("create can_rx thread failed!\n"); } msg.id = 0x78; /* ID为0x78 */ msg.ide = RT_CAN_STDID; /* 标准格式 */ msg.rtr = RT_CAN_DTR; /* 数据帧 */ msg.len = 8; /* 数据长度为8 */ /* 待发送的8字节数据 */ msg.data[0] = 0x00; msg.data[1] = 0x11; msg.data[2] = 0x22; msg.data[3] = 0x33; msg.data[4] = 0x44; msg.data[5] = 0x55; msg.data[6] = 0x66; msg.data[7] = 0x77; /* 发送一帧CAN数据 */ size = rt_device_write(can_dev, 0, &msg, sizeof(msg)); if (size == 0) { rt_kprintf("can dev write data failed!\n"); } return res; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(can_sample, can device sample);