1 干货分享|基于HPM6750 CAN2.0 及 CAN- FD 操作指南-德赢Vwin官网 网
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

干货分享|基于HPM6750 CAN2.0 及 CAN- FD 操作指南

先楫半导体HPMicro 2022-06-16 09:13 次阅读

简介


本文主要介绍了HPM6750的控制器局域网CAN(以下简称CAN控制器)的概述以及基于HPM-SDK CAN控制器的开发指导(包括实现CAN2.0、CAN-FD)。


CAN控制器

1. 概述

CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO 国际标准化的串行通信协议。HPM6750 MCU搭载了4路CAN控制器,CAN0/CAN1/CAN2/CAN3,它们具有如下特性:


● 支持 CAN 2.0B 协议,支持多达 8 字节的数据载荷, 数据速率可达 1Mbit/s;

● 支持 CAN FD 协议,支持多达 64 字节的数据载荷, 数据速率可达 2.5Mbit/s;

● 支持 1 ∼ 1/256 的波特率预分频,灵活配置波特率;

● 16 个接收缓冲器;

– FIFO 方式;

– 错误或者不被接收的数据不会覆盖存储的消息;

● 1 个高优先主发送缓冲器 PTB;

● 8 个副发送缓冲器 STB;

– FIFO 方式;

– 优先级仲裁方式;

● 16 组独立的筛选器;

– 支持 11 位标准 ID 和 29 位扩展 ID;

– 可编程 ID CODE 位以及 MASK 位;

● PTB/STB 均支持支持单次发送模式;

● 支持静默模式;

● 支持回环模式;

● 支持待机模式;

● 支持捕捉传输的错误种类以及定位仲裁失败位置;

● 可编程的错误警告值;

● 支持 ISO11898-4 规定时间触发 CAN 以及接收时间戳可配置停止位:1位,1.5位或者2位。

2. 系统框图

1cafecd8-e6f8-11ec-aa96-dac502259ad0.png

3. 管脚


管脚名称
方向
功能说明
RXD
输入
CAN接受数据信号
TXD
输出
CAN 发送数据信号
STBY
输出
CAN 外部收发器待机控制信号

CAN控制器功能开发指引

1. API功能描述


CAN开发主要使用以下接口

//获取CAN默认配置hpm_stat_t can_get_default_config(can_config_t *config);//CAN初始化接口hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq);//接收过滤器配置hpm_stat_t can_set_filter(CAN_Type *base, const can_filter_config_t *config);//CAN数据发送接口(阻塞模式)hpm_stat_t can_send_message_blocking(CAN_Type *base, const can_transmit_buf_t *message);//CAN高优先级数据发送接口(PTB阻塞模式)hpm_stat_t can_send_high_priority_message_blocking(CAN_Type *base, const can_transmit_buf_t *message);//CAN 数据接收接口(阻塞模式)hpm_stat_t can_receive_message_blocking(CAN_Type *base, can_receive_buf_t *message);//CAN数据接收接口(非租塞模式)hpm_stat_t can_read_received_message(CAN_Type *base, can_receive_buf_t *message);//设置发送补偿及使能(CAN-FD高速率使用,TDC)void can_set_transmitter_delay_compensation(CAN_Type *base, uint8_t sample_point, bool enable);

2. API数据结构

2.1 CAN配置



typedef struct { union { struct { //当禁用use_lowlevel_timing_setting时,以下参数有效。 uint32_t baudrate; //CAN 2.0波特率设定 uint32_t baudrate_fd; // CAN-FD波特率设定,当enable_canfd使能才有效 uint16_t can20_samplepoint_min; //CAN 2.0最小采样点(0~1000) uint16_t can20_samplepoint_max; //CAN 2.0最大采样点(0~1000) uint16_t canfd_samplepoint_min; //CAN-FD 最小采样点(0~1000) uint16_t canfd_samplepoint_max; //CAN-FD 最大采样点(0~1000) }; struct {//当启用use_lowlevel_timing_setting时,以下参数有效。 can_bit_timing_param_t can_timing; //CAN2.0 位时间参数 can_bit_timing_param_t canfd_timing; //CAN-FD 位时间参数 }; };can_loopback_mode_t loopback_mode; //CAN回环模式,默认是正常模式bool use_lowlevel_timing_setting; //是否启用位时间参数设定 bool enable_canfd; //是否启用CAN-FD bool enable_self_ack; //是否启用自ACK帧bool disable_re_transmission_for_ptb; //是否禁用高优先级PTB发送重传, false:单发模式 true:重传模式bool disable_re_transmission_for_stb; //是否禁用STP发送重传, false:单发模式, true:重传模式uint16_t filter_list_num; //接受过滤器list总数can_filter_config_t *filter_list; //接受过滤器list指针} can_config_t;

2.2 CAN过滤配置

/** * @brief CAN acceptance filter modes */typedef enum _can_filter_mode { can_filter_mode_both_frames, //标准格式和扩展格式过滤选模式can_filter_mode_standard_frames, //标准格式过滤模式can_filter_mode_extended_frames, //扩展格式过滤模式} can_filter_mode_t;

/** * @brief CAN acceptance configuration */typedef struct {uint16_t index; //过滤器indexcan_filter_mode_t mode; //过滤器模式 bool enable; //过滤器是否使能 uint32_t code; //ID code uint32_t mask; //ID mask} can_filter_config_t;

2.3 CAN发送

/** * @brief CAN transmit buffer data structure */typedef union _can_tx_buf {uint32_t buffer[18]; //发送 buffer,由于是联合体,和下面的共享一块内存区域,buffer大小:4*18=72struct { struct { uint32_t id: 29; //CAN ID uint32_t : 1; uint32_t transmit_timestamp_enable: 1; //时间戳使能 }; struct { uint32_t dlc: 4; //数据长度 uint32_t bitrate_switch: 1; //bitrate开关 uint32_t canfd_frame: 1; //can-fd标识位 uint32_t remote_frame: 1; //remote 标识位 uint32_t extend_id: 1; //扩展ID uint32_t : 24; }; uint8_t data[]; //数据指针 };} can_transmit_buf_t;

2.4 CAN接收

/** * @brief CAN receive buffer data structure */typedef union _can_rx_buf { uint32_t buffer[20]; //接收buffer,由于是联合体,和下面的数据共享一块内存区域 struct { struct { uint32_t id: 29; //can id uint32_t : 1; uint32_t error_state_indicator: 1; //错误状态指示 }; struct { uint32_t dlc: 4; //数据长度 uint32_t bitrate_switch: 1; //bitrate开关 uint32_t canfd_frame: 1; //canfd 标识 uint32_t remote_frame: 1; //remote标识 uint32_t extend_id: 1; //扩展ID uint32_t : 4; uint32_t loopback_message: 1; //回环数据标识 uint32_t error_type: 3; //错误类型 uint32_t cycle_time: 16; //cycle time }; uint8_t data[]; //数据指针 };} can_receive_buf_t;

3. 配置流程

CAN控制器的CAN2.0和CAN-FD配置流程如下图。

1cf08d88-e6f8-11ec-aa96-dac502259ad0.png

4. 样例

4.1 内部回环样例

需求:

1.CAN-FD协议

2.波特率2.5Mbps

3.内部回环模式

4.数据载荷64字节

5.遍历can-id从0~2047(11位标准ID)

6.每帧数据确保不同

7.阻塞发送、非阻塞接收(非中断模式)

8.对比接收和发送的数据包是否相等,并输出结果

void board_can_loopback_test(void){ bool result; uint32_t error_cnt = 0; uint32_t can_src_clk_freq; can_config_t can_config; board_init_can(BOARD_APP_CAN_BASE); can_src_clk_freq = board_init_can_clock(BOARD_APP_CAN_BASE); can_config.baudrate = 1000000; /* 1Mbps */ can_config.baudrate_fd = 2500000; /*5Mbps*/ can_config.loopback_mode = can_loopback_internal; //内部回环 can_config.enable_canfd = true; hpm_stat_t status = can_init(BOARD_APP_CAN_BASE, &can_config, can_src_clk_freq); if (status != status_success) { printf("CAN initialization failed, error code: %d\n", status); return; } can_transmit_buf_t tx_buf; can_receive_buf_t rx_buf; memset(&tx_buf, 0, sizeof(tx_buf)); memset(&rx_buf, 0, sizeof(rx_buf)); tx_buf.dlc = can_payload_size_64; tx_buf.canfd_frame = 1; tx_buf.bitrate_switch = 1; for (uint32_t i = 0; i < 2048; i++) { tx_buf.id = i; for (uint32_t j = 0; j < 64u; j++) { tx_buf.data[j] = (uint8_t)i + j + 1; } can_send_message_blocking(BOARD_APP_CAN_BASE, &tx_buf); can_read_received_message(BOARD_APP_CAN_BASE, &rx_buf); result = can_buf_compare(&tx_buf, &rx_buf); if (!result) { error_cnt++; can_set_transmitter_delay_compensation(BOARD_APP_CAN_BASE, 64, true); hpm_stat_t status = can_init(BOARD_APP_CAN_BASE, &can_config, can_src_clk_freq); if (status != status_success) { printf("CAN initialization failed, error code: %d\n", status); return; } printf("ID=%08x, result:%s\n", rx_buf.id, result ? "passed": "failed"); } } printf(" CAN loopback test for extend frame %s, error_cnt:%d\n", error_cnt == 0 ? "passed" : "failed", error_cnt);}

4.2 两路闭环收发样例

需求:

1.CAN2.0协议

2.波特率1000000,1Mbps

3.CAN0发送,CAN1接收

4.数据载荷8字节

5.CAN0阻塞发送,CAN1阻塞接收

6.对比CAN0发送包和CAN1接收包是否相同,并输出结果

7.压测100次,输出最终结果

void can0_can1_rxrx_loop_test(void){ pm_stat_t status; can_config_t can_config; bool use_canfd = false; can_get_default_config(&can_config); can_config.baudrate = 1000000; /* 1Mbps */ can_config.baudrate_fd = 5000000; /* 2Mbps */ can_config.enable_canfd = use_canfd; board_init_can(HPM_CAN0); board_init_can(HPM_CAN1); uint32_t can_src_clk_freq0 = board_init_can_clock(HPM_CAN0); uint32_t can_src_clk_freq1 = board_init_can_clock(HPM_CAN1); hpm_stat_t status0 = can_init(HPM_CAN0, &can_config, can_src_clk_freq0); if (status0 != status_success) { printf("CAN initialization failed, error code: %d\n", status0); return; } hpm_stat_t status1 = can_init(HPM_CAN1, &can_config, can_src_clk_freq1); if (status1 != status_success) { printf("CAN initialization failed, error code: %d\n", status1); return; } printf("CMD_STA_CMD_CTRL(0xA0)= %08x\n", HPM_CAN0->CMD_STA_CMD_CTRL); printf("F_PRESC = %08x\n", HPM_CAN0->F_PRESC); printf("S_PRESC = %08x\n", HPM_CAN0->S_PRESC); printf("TDC = %08x\n", HPM_CAN0->TDC); uint32_t error_cnt = 0; bool result = false; can_transmit_buf_t tx_buf; can_receive_buf_t rx_buf; memset(&tx_buf, 0, sizeof(tx_buf)); memset(&rx_buf, 0, sizeof(rx_buf)); tx_buf.id = 0x101; uint32_t id_max; if (!use_canfd) { tx_buf.dlc = can_payload_size_8; id_max = 8; } else { tx_buf.dlc = can_payload_size_8; id_max = 64; tx_buf.canfd_frame = 1; tx_buf.bitrate_switch = 1; } for(int index = 0; index < 100; index++) { for (uint32_t i = 0; i < id_max; i++) { tx_buf.data[i] = (uint8_t)(index+i); } can_send_high_priority_message_blocking(HPM_CAN0, &tx_buf); can_receive_message_blocking(HPM_CAN1, &rx_buf); result = can_buf_compare(&tx_buf, &rx_buf); if (!result) { error_cnt++; printf(" CAN0->CAN1 for standard frame %s\n", result ? "passed" : "failed"); } can_receive_message_blocking(HPM_CAN0, &rx_buf); result = can_buf_compare(&tx_buf, &rx_buf); if (!result) { error_cnt++; printf(" CAN1->CAN0 for standard frame %s\n", result ? "passed" : "failed"); } } printf(" CAN can0 can1 rxrx loop test for result: %s, error_cnt:%d\n", error_cnt == 0 ? "passed" : "failed", error_cnt);}

4.3 四路收发样例

需求:

1.CAN-FD协议

2.波特率2.5Mbps

3.数据载荷64字节

4.启用中断接收

5.CAN0/CAN1/CAN2/CAN3顺序发送数据

6.确保CAN0/CAN1/CAN2/CAN3 can-id不同

7.确保每次发送的数据包内容不同

8.分别对比每次一路CAN发送数据包和其它三路CAN接收的数据包是否相同,并输出结果

9.压测100次,并输出结果

static can_info_t s_can_info[] = { { .can_base = HPM_CAN0 }, { .can_base = HPM_CAN1 },#if defined(HPM_CAN2) { .can_base = HPM_CAN2 },#endif#if defined (HPM_CAN3) { .can_base = HPM_CAN3 },#endif};volatile static bool has_new_rcv_msg_array[4];volatile static can_receive_buf_t s_can_rx_buf_array[4];SDK_DECLARE_EXT_ISR_M(IRQn_CAN0, board_can_isr0);SDK_DECLARE_EXT_ISR_M(IRQn_CAN1, board_can_isr1);SDK_DECLARE_EXT_ISR_M(IRQn_CAN2, board_can_isr2);SDK_DECLARE_EXT_ISR_M(IRQn_CAN3, board_can_isr3);void board_can_isr0(void){ uint8_t flags = can_get_tx_rx_flags(HPM_CAN0); if ((flags & CAN_EVENT_RECEIVE) != 0) { can_read_received_message(HPM_CAN0, (can_receive_buf_t *)&s_can_rx_buf_array[0]); has_new_rcv_msg_array[0] = true; } can_clear_tx_rx_flags(HPM_CAN0, flags);}void board_can_isr1(void){ uint8_t flags = can_get_tx_rx_flags(HPM_CAN1); if ((flags & CAN_EVENT_RECEIVE) != 0) { can_read_received_message(HPM_CAN1, (can_receive_buf_t *)&s_can_rx_buf_array[1]); has_new_rcv_msg_array[1] = true; } can_clear_tx_rx_flags(HPM_CAN1, flags);}void board_can_isr2(void){ uint8_t flags = can_get_tx_rx_flags(HPM_CAN2); if ((flags & CAN_EVENT_RECEIVE) != 0) { can_read_received_message(HPM_CAN2, (can_receive_buf_t *)&s_can_rx_buf_array[2]); has_new_rcv_msg_array[2] = true; } can_clear_tx_rx_flags(HPM_CAN2, flags);}void board_can_isr3(void){ uint8_t flags = can_get_tx_rx_flags(HPM_CAN3); if ((flags & CAN_EVENT_RECEIVE) != 0) { can_read_received_message(HPM_CAN3, (can_receive_buf_t *)&s_can_rx_buf_array[3]); has_new_rcv_msg_array[3] = true; } can_clear_tx_rx_flags(HPM_CAN3, flags);}void board_can0_1_2_3_txrx_loop_test(void){ hpm_stat_t status; can_config_t can_config; bool use_canfd = true; can_get_default_config(&can_config); can_config.baudrate = 1000000; /* 1Mbps */ can_config.baudrate_fd = 2500000; /* 5Mbps */ can_config.enable_canfd = use_canfd; /* Initialize CAN */ for (uint32_t i=0; i < ARRAY_SIZE(s_can_info); i++) { can_info_t *info = &s_can_info[i]; board_init_can(info->can_base); info->clock_freq = board_init_can_clock(info->can_base); status = can_init(info->can_base, &can_config, info->clock_freq); if (status != status_success) { printf("CAN %d initialization failed, error code: %d\n", i, status); return; } printf("CMD_STA_CMD_CTRL(0xA0)= %08x\n", info->can_base->CMD_STA_CMD_CTRL); printf("F_PRESC = %08x\n", info->can_base->F_PRESC); printf("S_PRESC = %08x\n", info->can_base->S_PRESC); printf("TDC = %08x\n", info->can_base->TDC); can_enable_tx_rx_irq(info->can_base, CAN_EVENT_RECEIVE); } intc_m_enable_irq_with_priority(IRQn_CAN0, 1); intc_m_enable_irq_with_priority(IRQn_CAN1, 1); intc_m_enable_irq_with_priority(IRQn_CAN2, 1); intc_m_enable_irq_with_priority(IRQn_CAN3, 1);

uint32_t error_cnt = 0; bool result = false; can_transmit_buf_t tx_buf[4]; uint32_t data_max; memset(tx_buf, 0, sizeof(tx_buf)); for(int i = 0; i < 4; i ++) { tx_buf[i].id = i+1; if (!use_canfd) { tx_buf[i].dlc = can_payload_size_8; data_max = 8; } else { tx_buf[i].canfd_frame = 1; tx_buf[i].bitrate_switch = 1; tx_buf[i].dlc = can_payload_size_64; data_max = 64; } } for(int index = 0; index < 100; index++) { for(uint32_t can_i = 0; can_i < 4; can_i++) { for (uint32_t i = 0; i < data_max; i++) { tx_buf[can_i].data[i] = (uint8_t)(index+can_i+i); } } for(uint32_t can_i = 0; can_i < 4; can_i++) { can_send_high_priority_message_blocking(s_can_info[can_i].can_base, &tx_buf[can_i]); for(int j= 1; j < 4; j++) { printf("recv canid:%d\n", (can_i+j)%4); while(!has_new_rcv_msg_array[(can_i+j)%4]) { } has_new_rcv_msg_array[(can_i+j)%4] = false; result = can_buf_compare(&tx_buf[can_i], &s_can_rx_buf_array[(can_i+j)%4]); if (!result) { error_cnt++; } printf(" CAN%d->CAN%d for standard frame %s\n", can_i, (can_i+j)%4, result ? "passed" : "failed"); } } } printf(" CAN can0 can1 rxrx loop test for result: %s, error_cnt:%d\n", error_cnt == 0 ? "passed" : "failed", error_cnt);}

划重点

使用HPM6750的CAN控制器,可以轻松实现4路CAN2.0/CAN-FD同时收发数据,易于实现CAN网络隔离以及网络中继的复杂需求,实现了工业网关的功能。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • CAN
    CAN
    +关注

    关注

    57

    文章

    2744

    浏览量

    463605
收藏 人收藏

    评论

    相关推荐

    虹科干货 三代CAN技术演进:从CAN CC到CAN XL的创新路径(上篇)

    CAN FD作为CAN技术的一个重要迭代,其高速率和大数据量的传输能力为现代汽车和其他需要高效数据传输的应用场景提供了有力的支持。从CAN CC到C
    的头像 发表于 11-01 11:04 327次阅读

    HPM6750 Bootloader设计

    我正在做一个hpm6750evk2的bootloader。设计很简单,boot工程代码只做跳转到1M后的APP工程代码处,APP工程就是做的一个点灯的程序而已,boot、APP工程都是跑
    发表于 10-23 18:59

    CAN FD与传统CAN的区别是什么

    随着汽车电子、工业自动化的蓬勃发展,CAN总线上的设备数量、数据量都大大增加,给CAN总线带来了极大的挑战。为满足更高的带宽及数据吞吐量,CAN FD
    的头像 发表于 10-22 10:47 380次阅读
    <b class='flag-5'>CAN</b> <b class='flag-5'>FD</b>与传统<b class='flag-5'>CAN</b>的区别是什么

    CAN-FDCAN总线网络第二章

    日常工作中使用 CAN FD 的公司实习。无论哪种方式,本指南都会向您展示 CAN FD:具有灵活数据的
    的头像 发表于 10-02 15:20 244次阅读
    <b class='flag-5'>CAN-FD</b>:<b class='flag-5'>CAN</b>总线网络第二章

    MCAN(CAN FD)模块入门

    德赢Vwin官网 网站提供《MCAN(CAN FD)模块入门.pdf》资料免费下载
    发表于 09-14 10:08 0次下载
    MCAN(<b class='flag-5'>CAN</b> <b class='flag-5'>FD</b>)模块入门

    从替代到创新,国产CAN FD芯片持续突破

    德赢Vwin官网 网报道(文/吴子鹏)随着汽车电子、工业自动化设备的发展迭代,CAN总线上的设备、数据量都大大增加,给CAN总线带来了极大的挑战。因此,CAN FD应运而生。
    的头像 发表于 09-02 08:13 6515次阅读

    虹科技术 全新Linux环境PCAN驱动程序发布!CAN/CAN FD通信体验全面升级!

    全新8.17.0版本的PCAN-Linux驱动程序正式发布,专为CANCAN FD接口量身打造。无论是CAN 2.0 a/b还是
    的头像 发表于 08-29 09:36 431次阅读
    虹科技术 全新Linux环境PCAN驱动程序发布!<b class='flag-5'>CAN</b>/<b class='flag-5'>CAN</b> <b class='flag-5'>FD</b>通信体验全面升级!

    CAN/CAN FD/CAN XL三大总线协议解读,是逐步替代关系吗?

    德赢Vwin官网 网报道(文/吴子鹏)在软件定义汽车逐渐成为主流的当下,数据传输的速度和效率成为打造智能汽车的瓶颈,在这种大背景下,传统CAN总线应对一些需求已经相当吃力,因此CAN FDCAN
    的头像 发表于 08-12 01:12 4384次阅读

    CAN FD盒基本功能包括哪些

    CAN FD盒基本功能有哪些? CAN FD盒作为CAN FD总线通信的重要设备,其基本功能包括
    的头像 发表于 07-02 16:21 878次阅读

    全新Linux环境PCAN驱动程序发布!CAN/CAN FD通信体验全面升级!

    全新8.17.0版本的PCAN-Linux驱动程序正式发布,专为CANCAN FD接口量身打造。无论是CAN 2.0 a/b还是
    的头像 发表于 04-19 10:38 914次阅读

    汽车CAN FD总线测试原理及应用

    CAN FD总线报文周期一致性测试方法,可自动实现监控测试并快速生成测试报告,主要根据CAPL语言设计建立测试应用工程。
    发表于 04-01 12:53 896次阅读
    汽车<b class='flag-5'>CAN</b> <b class='flag-5'>FD</b>总线测试原理及应用

    什么是CAN2.0协议?

    CAN2.0协议是控制器局域网络(ControllerAreaNetwork,CAN)的一种版本,也被称为传统CAN协议,由德国博世BOSCH公司开发,并已成为国际上广泛应用于汽车电子、工业自动化
    的头像 发表于 03-29 08:19 1324次阅读
    什么是<b class='flag-5'>CAN2.0</b>协议?

    CAN总线最大能够带多少节点?CANFD相对于CAN2.0有哪些差异呢?

    CAN总线最大能够带多少节点?CANFD相对于CAN2.0有哪些差异呢? CAN总线最大能够带多少节点? CAN总线是一种广泛应用于汽车领域的多主机串行通信总线。
    的头像 发表于 01-31 14:08 3648次阅读

    如何使用DSLogic分析CAN/CAN-FD 信号?

    一文档介绍本文将一步步介绍如何使用DSLogic逻辑分析仪采集并分析CAN/CAN-FD信号,因为CAN信号的测量和CAN-FD的大致一样,所以下文以
    的头像 发表于 01-08 14:54 1319次阅读
    如何使用DSLogic分析<b class='flag-5'>CAN</b>/<b class='flag-5'>CAN-FD</b> 信号?

    通过系统级测试来避免 CAN 收发器的数据传输问题

    CAN-Flexible Data (FD)。传统的 CAN2.0 系统可通过添加 CAN-FD 节点来实现增强,CAN-FD 节点可提
    的头像 发表于 01-01 11:24 694次阅读
    通过系统级测试来避免 <b class='flag-5'>CAN</b> 收发器的数据传输问题