638|2

441

帖子

3

TA的资源

纯净的硅(高级)

楼主
 

【匠芯创D133CBS】 CAN通信收发测试 [复制链接]

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

测试开发板的CAN通信。

 

一、硬件电路

 

1.1、CAN简介

 

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

 

1.2、CAN通信部分

1.3、连接CAN调试卡

 

 

二、程序

 

2.1、驱动程序

CAN的驱动程序,厂家已经移植好了,在开发板的BSP文件下。

• bsp/artinchip/drv/can/drv_can.c,CAN 模块 driver 层源码
• bsp/artinchip/hal/can/aic_hal_can.c,CAN 模块 hal 层源码
• bsp/artinchip/include/hal/aic_hal_can.h,CAN 模块 hal 层头文件

 

2.2、应用程序

can.c

//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[i]);
        }

        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[i]=rxmsg.data[i];
        }



        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[1] =
        {
            //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);

 

三、运行结果

 

程序编译后,下载到开发板运行

3.1、开发板串口执行命令:test_can_sample

 

3.2、CAN调试卡发送数据,开发板接收后,将ID+1返回数据给开发板。

 

最新回复

请问楼主,如果是新入门CAN总线,想先从协议入手,应该看什么书合适呀?直接拿板子有点懵   详情 回复 发表于 2024-8-27 14:58
点赞 关注
 
 

回复
举报

6809

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

CAN通信收发测试成功

 
 
 

回复

16

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

请问楼主,如果是新入门CAN总线,想先从协议入手,应该看什么书合适呀?直接拿板子有点懵

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表