【匠芯创D133CBS】 CAN通信收发测试
本帖最后由 TL-LED 于 2024-8-25 14:42 编辑<p><span style="font-size:16px;">测试开发板的CAN通信。</span></p>
<p> </p>
<p><span style="font-size:16px;"><strong>一、硬件电路</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">1.1、CAN简介</span></p>
<p> </p>
<p><span style="font-size:16px;">CAN 是一种广泛应用于汽车控制系统和一般工业环境中的区域网络总线。作为一款多主机、多广播的通信协议,CAN<br />
以其高可靠性和卓越的错误检测能力而著称。D133芯片CAN特性:<br />
• 支持 CAN2.0A 和 CAN2.0B 协议<br />
• 支持 11 位标准格式标识符和 29 位扩展格式标识符<br />
• 可编程通信速率最高可达 1 Mbps<br />
• 支持多种操作模式:正常模式、只听模式、自测模式、休眠模式、复位模式<br />
• 支持接收过滤器,支持两种过滤模式<br />
• 64 bytes 缓冲器<br />
• 支持错误检测与处理:错误计数、错误报警阈值可配置、错误捕获、仲裁丢失捕获</span></p>
<p> </p>
<p><span style="font-size:16px;">1.2、CAN通信部分</span></p>
<p><span style="font-size:16px;"></span></p>
<p><span style="font-size:16px;">1.3、连接</span>CAN调试卡</p>
<p> </p>
<p></p>
<p> </p>
<p><strong><span style="font-size:16px;">二、程序</span></strong></p>
<p> </p>
<p><span style="font-size:16px;">2.1、驱动程序</span></p>
<p><span style="font-size:16px;">CAN的驱动程序,厂家已经移植好了,在开发板的BSP文件下。</span></p>
<p><span style="font-size:16px;">• bsp/artinchip/drv/can/drv_can.c,CAN 模块 driver 层源码<br />
• bsp/artinchip/hal/can/aic_hal_can.c,CAN 模块 hal 层源码<br />
• bsp/artinchip/include/hal/aic_hal_can.h,CAN 模块 hal 层头文件</span></p>
<p> </p>
<p><span style="font-size:16px;">2.2、应用程序</span></p>
<p><span style="font-size:16px;">can.c</span></p>
<pre>
<code>//can.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rtthread.h>
#include "rtdevice.h"
#include <aic_core.h>
#include "aic_hal_can.h"
static rt_device_t can_dev;
#define CAN_DEV_NAME "can0"
#define CAN_RX_FILTER_ENABLE 0
static struct rt_semaphore rx_sem;
u8 can_rx_flag = 0;
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void can_rx_thread(void *parameter)
{
int i;
rt_size_t size;
struct rt_can_msg rxmsg = {0};
struct rt_can_msg txmsg = {0};
while (1)
{
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
rxmsg.hdr = -1;
size = rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
if (!size)
{
rt_kprintf("CAN read error\n");
break;
}
rt_kprintf("%s received msg:\nID: 0x%x ", CAN_DEV_NAME, rxmsg.id);
if (rxmsg.len)
rt_kprintf("DATA: ");
for (i = 0; i < rxmsg.len; i++)
{
rt_kprintf("%02x ", rxmsg.data);
}
rt_kprintf("\n");
txmsg.id = rxmsg.id+1;
if (txmsg.id > 0x7FF)
txmsg.ide = 1;
else
txmsg.ide = 0;
txmsg.len = rxmsg.len;
txmsg.rtr = rxmsg.rtr;//CAN_FRAME_TYPE_DATA;
for(i=0;i<8;i++)
{
txmsg.data=rxmsg.data;
}
size = rt_device_write(can_dev, 0, &txmsg, sizeof(txmsg));
if (size != sizeof(txmsg))
{
rt_kprintf("can dev write data failed!\n");
break;
}
}
rt_device_close(can_dev);
}
int test_can_rx_hdl(void)
{
rt_err_t ret = 0;
rt_thread_t thread;
if (!can_rx_flag)
{
//查找CAN设备
can_dev = rt_device_find(CAN_DEV_NAME);
if (!can_dev)
{
rt_kprintf("find %s failed!\n", CAN_DEV_NAME);
return -RT_ERROR;
}
//打开CAN设备
ret = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
if (ret)
{
rt_kprintf("%s open failed!\n", CAN_DEV_NAME);
return -RT_ERROR;
}
//设置CAN波特率
ret = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
if (ret)
{
rt_kprintf("%s set baudrate failed!\n", CAN_DEV_NAME);
ret = -RT_ERROR;
goto __exit;
}
//使能CAN接收中断
rt_device_control(can_dev, RT_DEVICE_CTRL_SET_INT, NULL);
#if CAN_RX_FILTER_ENABLE
/* config can rx filter */
struct rt_can_filter_item items =
{
//Only receive standard data frame with ID 0x100~0x1FF
RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL),
};
struct rt_can_filter_config cfg = {1, 1, items};
ret = rt_device_control(g_can_rx_dev, RT_CAN_CMD_SET_FILTER, &cfg);
#endif
rt_device_set_rx_indicate(can_dev, can_rx_call);
rt_sem_init(&rx_sem, "can_rx_sem", 0, RT_IPC_FLAG_PRIO);
thread = rt_thread_create("can_rx_thread", can_rx_thread, RT_NULL, 2048, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create can_rx thread failed!\n");
ret = -RT_ERROR;
}
can_rx_flag = 1;
rt_kprintf("The %s received thread is ready...\n", CAN_DEV_NAME);
}
else
{
rt_kprintf("The %s received thread is running...\n", CAN_DEV_NAME);
}
rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)CAN_NORMAL_MODE);
return RT_EOK;
__exit:
rt_device_close(can_dev);
return ret;
}
static int test_can_sample(int argc, char *argv[])
{
test_can_rx_hdl();
return 0;
}
MSH_CMD_EXPORT_ALIAS(test_can_sample, test_can_sample, can device loopback sample);
</code></pre>
<p> </p>
<p><span style="font-size:16px;"><strong>三、运行结果</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">程序编译后,下载到开发板运行</span></p>
<p><span style="font-size:16px;">3.1、开发板串口执行命令:test_can_sample</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;">3.2、CAN调试卡发送数据,开发板接收后,将ID+1返回数据给开发板。</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p>CAN通信收发测试成功</p>
<p>请问楼主,如果是新入门CAN总线,想先从协议入手,应该看什么书合适呀?直接拿板子有点懵</p>
页:
[1]