TL-LED 发表于 2024-8-25 14:43

【匠芯创D133CBS】 CAN通信收发测试

本帖最后由 TL-LED 于 2024-8-25 14:42 编辑

<p><span style="font-size:16px;">测试开发板的CAN通信。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>一、硬件电路</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">1.1、CAN简介</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">CAN 是一种广泛应用于汽车控制系统和一般工业环境中的区域网络总线。作为一款多主机、多广播的通信协议,CAN<br />
以其高可靠性和卓越的错误检测能力而著称。D133芯片CAN特性:<br />
&bull; 支持 CAN2.0A 和 CAN2.0B 协议<br />
&bull; 支持 11 位标准格式标识符和 29 位扩展格式标识符<br />
&bull; 可编程通信速率最高可达 1 Mbps<br />
&bull; 支持多种操作模式:正常模式、只听模式、自测模式、休眠模式、复位模式<br />
&bull; 支持接收过滤器,支持两种过滤模式<br />
&bull; 64 bytes 缓冲器<br />
&bull; 支持错误检测与处理:错误计数、错误报警阈值可配置、错误捕获、仲裁丢失捕获</span></p>

<p>&nbsp;</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>&nbsp;</p>

<p></p>

<p>&nbsp;</p>

<p><strong><span style="font-size:16px;">二、程序</span></strong></p>

<p>&nbsp;</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;">&bull; bsp/artinchip/drv/can/drv_can.c,CAN 模块 driver 层源码<br />
&bull; bsp/artinchip/hal/can/aic_hal_can.c,CAN 模块 hal 层源码<br />
&bull; bsp/artinchip/include/hal/aic_hal_can.h,CAN 模块 hal 层头文件</span></p>

<p>&nbsp;</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 &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;rtthread.h&gt;
#include "rtdevice.h"
#include &lt;aic_core.h&gt;
#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(&amp;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(&amp;rx_sem, RT_WAITING_FOREVER);

      rxmsg.hdr = -1;
      size = rt_device_read(can_dev, 0, &amp;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 &lt; rxmsg.len; i++)
      {
            rt_kprintf("%02x ", rxmsg.data);
      }

      rt_kprintf("\n");

      txmsg.id = rxmsg.id+1;
      if (txmsg.id &gt; 0x7FF)
            txmsg.ide = 1;
      else
            txmsg.ide = 0;
      txmsg.len = rxmsg.len;
      txmsg.rtr = rxmsg.rtr;//CAN_FRAME_TYPE_DATA;

      for(i=0;i&lt;8;i++)
      {
            txmsg.data=rxmsg.data;
      }



      size = rt_device_write(can_dev, 0, &amp;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, &amp;cfg);
#endif

      rt_device_set_rx_indicate(can_dev, can_rx_call);

      rt_sem_init(&amp;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>&nbsp;</p>

<p><span style="font-size:16px;"><strong>三、运行结果</strong></span></p>

<p>&nbsp;</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>&nbsp;</p>

<p><span style="font-size:16px;">3.2、CAN调试卡发送数据,开发板接收后,将ID+1返回数据给开发板。</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

Jacktang 发表于 2024-8-25 21:43

<p>CAN通信收发测试成功</p>

peterhzm 发表于 2024-8-27 14:58

<p>请问楼主,如果是新入门CAN总线,想先从协议入手,应该看什么书合适呀?直接拿板子有点懵</p>
页: [1]
查看完整版本: 【匠芯创D133CBS】 CAN通信收发测试