1►flexcan-fd简介
mm32f0160 系列 mcu 具有一个 flexcan 模块,该模块遵循 iso 11898-1 标准、 can fd 和 can 2.0b 协议规范,不仅兼容传统can,还支持can fd模式。在can-fd模式下,可实现最高8 mbps的fd模式通信速率,支持标准帧(11位标识符)和扩展帧(29位标识符),支持最大64字节有效负载,并且具有非常灵活的用于传输和接收的邮箱系统。
使用can fd较传统can具有如下优点:
(1)增加了数据长度,在发送长数据时,软件更加简单高效,满足更高的数据吞吐量。
(2)提高了传输速率,使得延迟时间更短,具有更好的实时性,满足更高的带宽。
(3)扩展了crc场,为数据内容提供了更好的保护,增加了系统安全性。
本章节初步学习使用mm32f0160 flexcan-fd接口实现can fd通信,相关例程参考灵动官网的libsamples或在此基础上修改。关于can fd协议不再进行详细介绍,感兴趣的小伙伴可以查阅相关资料增进了解。
2►can fd帧
iso 11898-1标准指定了符合iso 11898-1(2003)标准的经典帧格式,并引入了can fd(flexible data rate)帧格式。经典帧格式支持高达1mbps的比特率,以及每帧8字节的有效负载。fd帧格式支持超过1mbps的比特率,以及每帧超过8字节的有效负载。flexcan可以收发can fd和经典can格式交替的报文。
can fd 帧中有三个附加的控制位:
edl:扩展数据长度位,支持更多的数据负载。
brs比特率切换位:决定can fd帧是否切换比特率。
esi错误状态指示:错误主动节点发送显性,错误被动节点发送隐性。
can fd格式不支持远程帧,远程帧总是以经典can格式传输。接收到fd帧并匹配邮箱时,接收报文缓冲区的rtr位将被无效化。
can fd报文数据字段可超过8字节,支持12至64字节。can fd报文可切换比特率,使can帧的控制字段、数据字段和crc字段比特率高于帧的开始和结束。
can fd帧结构(部分)如下图所示:
can fd帧从sof(帧起始)到brs的仲裁段,以标称比特率传输;从brs到crc界定符的数据段,以数据比特率传输;从crc界定符到intermission位,传输恢复为标称比特率。如果can fd帧中brs为隐性,则位时序在brs的采样点发生变化。brs位之前,can fd仲裁段的标称位时序由can_cbt或can_ctrl1寄存器定义;检测到隐性brs时,数据位时序由can_fdcbt 寄存器定义。
3►协议时序
flexcan具有单独配置can fd协议时序的寄存器,can fd位时序寄存器(can_fdcbt)存储用于控制位时序参数的字段:fpresdiv、fpropseg、fpseg1、fpseg2和frjw。
can fd报文数据段的fdpresdiv定义了串行时钟(sclock)的预分频,见下列方程。串行时钟的周期定义了用于构成can fd波形的时间单位tq,tq为can引擎所能处理的最小时间单元。
比特率定义了接收或传输 can fd报文的速率,公式如下:
位时间可以细分为三个部分:
同步段(sync_seg):1tq的固定长度;信号边沿出现在该段内。
时间段1:包括传播段和相位段1。flexcan 使用 can_fdcbt寄存器的fdpropseg和fdpseg1字段,其总和(+1)为2 ~ 39tq。
时间段 2:包括相位段2。其值(+1)为2 ~ 8tq。时间段2不能小于信息处理时间2tq。
当采用can fd位作为持续时间的衡量标准时,一个can fd位的外设时钟个数numclkbit为:
fcanfdclk为pe时钟,单位hz。
fsys为系统(chi)时钟频率,单位hz。
4►报文缓冲区
mm32f0160 flexcan遵循can fd协议规范,该模块已经设计了对应的can fd报文缓冲区结构。经典 can 帧使用传统型 rx fifo,can fd帧使用增强型rx fifo。下图为flexcan所使用的报文缓冲区结构,包括can 2.0b的两种帧格式:扩展帧(29位id)和标准帧(11位id)。每个报文缓冲区由16、24、40或72字节组成,其中包括8、16、32或64字节的数据。邮箱使用 0x80 ~ 0x27f 的内存区域。
edl — 扩展数据长度,edl位区分can帧和can fd 帧。
brs — 比特率切换,定义是否在 can fd 帧内切换比特率。
esi — 错误状态指示,表示发送节点是错误主动还是错误被动。
code — 报文缓冲区代码,code 字段可以被 cpu 和 flexcan 读写,用作报文缓冲区匹配和仲裁过程的一部分。编码详见用户手册。
srr — 替代远程请求,
1:扩展帧格式传输时,必须使用隐性位。
0:扩展帧格式传输时,显性位无效。
只用于扩展帧格式。传输时(发送缓冲区)该位必须设置为 1,且将会和从 can 总线上接收到的值一起存储于接收缓冲区。该位可以被接收为隐性或显性,如果 flexcan 以显性位接收,则认为仲裁丢失。
ide — id扩展位,
1:扩展帧;
0:标准帧。
rtr — 远程传输请求
1:如果是发送mb,则表示当前mb可能有一个远程帧待发送;如果是接收mb,则接收到的远程帧将会被存储;
0:表示当前的m 中有一个数据帧待传输。在接收mb中,可能会被用于匹配过程。
如果flexcan传输1(隐性),接收到0(显性),则认为仲裁丢失。如果 rtr传输0(显性),接收到1(隐性),则认为是位错误。如果接收到的值与发送值相同,则被认为是一次成功的位传输。
注:配置can fd帧时rtr位必须为0。
dlc — 数据字节长度
该4位字段为发送/接收数据的长度(以字节为单位),位于偏移地址为0x8到0xf的mb空间。
接收阶段,该字段由flexcan写入,从接收帧的dlc字段复制而得;
传输阶段,该字段由cpu写入,且与要传输的帧的dlc字段相对应。
当rtr = 1 时,被传输的帧为远程帧,不包含数据字段(dlc 字段的设置无效,参见表格“有效数据字节”)。
time stamp — 自由运行计时器时间戳
该16位字段为自由运行计时器的复制,当标识符字段开头出现在can总线上时进行捕获。
prio — 本地优先级
该 3 位字段只有当mcr.lprio_en被置位时才有效,且只针对传输邮箱。用于附加到 id 来定义传输优先级,不会被传输。
id — 帧标识符
标准帧格式,只有高 11 位(28 ~ 18)用于识别接收或发送帧,忽略低 18 位。扩展帧格式,所有位都用于识别传输或接收帧。
data byte0 ~ 63 — 数据字段
数据帧最多可以使用64个字节,取决于为mb选择的有效负载大小。从总线上接收到的帧以该帧被接收时的格式进行存放。只有n小于dlc时,data byte(n)才有效。
5►mb 内存映射
flexcan内存缓冲区的内存映射如下表所示:
6►flexcan-fd api
从灵动官网下载的flexcan固件库中定义了fd相关的api函数如下:
7►flexcan-fd通信
配置flexcan为can fd模式,通过中断接收和发送报文。
7.1 flexcan配置
void flexcan_configure(void){ gpio_inittypedef gpio_initstruct; nvic_inittypedef nvic_initstruct; flexcan_config_t flexcan_configstruct; flexcan_rx_mb_config_t flexcan_rxmb_configstruct; rcc_clockstypedef rcc_clocks; rcc_getclocksfreq(&rcc_clocks); rcc_ahbperiphclockcmd(rcc_ahbenr_gpiob, enable); rcc_apb1periphclockcmd(rcc_apb1enr_flexcan, enable); gpio_pinafconfig(gpiob, gpio_pinsource8, gpio_af_3); gpio_pinafconfig(gpiob, gpio_pinsource9, gpio_af_3); gpio_structinit(&gpio_initstruct); gpio_initstruct.gpio_pin = gpio_pin_8; gpio_initstruct.gpio_speed = gpio_speed_50mhz; gpio_initstruct.gpio_mode = gpio_mode_floating; gpio_init(gpiob, &gpio_initstruct); gpio_structinit(&gpio_initstruct); gpio_initstruct.gpio_pin = gpio_pin_9; gpio_initstruct.gpio_speed = gpio_speed_50mhz; gpio_initstruct.gpio_mode = gpio_mode_af_pp; gpio_init(gpiob, &gpio_initstruct); nvic_initstruct.nvic_irqchannel = flex_can_irqn; nvic_initstruct.nvic_irqchannelpriority = 0; nvic_initstruct.nvic_irqchannelcmd = enable; nvic_init(&nvic_initstruct); flexcan_getdefaultconfig(&flexcan_configstruct); flexcan_configstruct.baudrate = 1000000u; /* 1mbps */ flexcan_configstruct.baudratefd = 2000000u; /* 2mbps */ flexcan_configstruct.clksrc = enum_flexcan_clksrc1; flexcan_configstruct.enableloopback = false; flexcan_configstruct.disableselfreception = true; flexcan_configstruct.enableindividmask = true; flexcan_init(flex_can1, &flexcan_configstruct); flexcan_enterfreezemode(flex_can1); flex_can1->mcr |= 1 imask1 |= (0x01u
配置pb8、pb9复用为flexcan的rx、tx引脚;
配置can 1mbps和can fd 2mbps、mb选择64字节负载;
配置nvic中断;
配置mb1、mb3为发送邮箱;
配置mb0、mb2为接收邮箱;
mb0仅接收id为0x111的标准帧;
mb2仅接收id为0x222的扩展帧。
7.2 发送标准帧报文
void flexcan_fd_sendstandardframemessage(uint32_t id, uint8_t *buffer, uint8_t length){ flexcan_fd_frame_t flexcan_fd_framestruct; flexcan_fd_framestruct.length = length; flexcan_fd_framestruct.type = (uint8_t)enum_flexcan_frametypedata; flexcan_fd_framestruct.format = (uint8_t)enum_flexcan_frameformatstandard; flexcan_fd_framestruct.brs = 1; flexcan_fd_framestruct.edl = 1; flexcan_fd_framestruct.id = id; for (uint8_t i = 0; i < 16; i++) { flexcan_fd_framestruct.dataword[i] = buffer[i * 4] << 24 | buffer[i * 4 + 1] << 16 | buffer[i * 4 + 2] << 8 | buffer[i * 4 + 3]; } flexcan_writefdtxmb(flex_can1, 1, &flexcan_fd_framestruct);}
flexcan_fd_frame_t是按照flexcan mb结构定义的结构体,将要发送的标准帧按照帧结构依次设置结构体的各字段,接着写入mb1发送邮箱。
7.3 发送扩展帧报文
void flexcan_fd_sendextendframemessage(uint32_t id, uint8_t *buffer, uint8_t length){ flexcan_fd_frame_t flexcan_fd_framestruct; flexcan_fd_framestruct.length = length; flexcan_fd_framestruct.type = (uint8_t)enum_flexcan_frametypedata; flexcan_fd_framestruct.format = (uint8_t)enum_flexcan_frameformatextend; flexcan_fd_framestruct.brs = 1; flexcan_fd_framestruct.edl = 1; flexcan_fd_framestruct.id = id; for (uint8_t i = 0; i < 16; i++) { flexcan_fd_framestruct.dataword[i] = buffer[i * 4] << 24 | buffer[i * 4 + 1] << 16 | buffer[i * 4 + 2] < 0x18) & 0xff; buffer[i*4+1] = (flexcan_fd_framestruct.dataword[i] >> 0x10) & 0xff; buffer[i*4+2] = (flexcan_fd_framestruct.dataword[i] >> 0x08) & 0xff; buffer[i*4+3] = (flexcan_fd_framestruct.dataword[i] >> 0x00) & 0xff; } if (index == 0) { flexcan_fd_sendstandardframemessage((flexcan_fd_framestruct.id >> can_id_std_shift), buffer, flexcanfd_tx_64bytes_datalen); } else { flexcan_fd_sendextendframemessage((flexcan_fd_framestruct.id >> can_id_ext_shift), buffer, flexcanfd_tx_64bytes_datalen); }}
读接收邮箱(index),获取can fd报文中的数据,并发送该报文。
7.5 中断服务子程序
void flexcan_irqhandler(void){ uint32_t u32flag = 1; /* mb0 */ if (flexcan_getmbstatusflags(flex_can1, u32flag << 0) != 0) { flexcan_fd_rxmb_handler(0); flexcan_clearmbstatusflags(flex_can1, u32flag << 0); } /* mb1 */ if (flexcan_getmbstatusflags(flex_can1, u32flag << 1) != 0) { flexcan_clearmbstatusflags(flex_can1, u32flag << 1); } /* mb2 */ if (flexcan_getmbstatusflags(flex_can1, u32flag << 2) != 0) { flexcan_fd_rxmb_handler(2); flexcan_clearmbstatusflags(flex_can1, u32flag << 2); } /* mb3 */ if (flexcan_getmbstatusflags(flex_can1, u32flag << 3) != 0) { flexcan_clearmbstatusflags(flex_can1, u32flag << 3); }}
mb0、mb2完成接收调用mb接收函数,获取报文并通过mb1、mb3发送。mb1、mb3完成传输,清除对应标志。
7.6 flexcan_fd中断示例
void flexcan_fd_interrupt_sample(void){ uint8_t buffer[64] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xaa, 0xaa,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x55, 0x55,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xaa, 0xaa,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x88, }; printf(test %s, __function__); flexcan_configure(); while (1) { flexcan_fd_sendstandardframemessage(0x214, buffer, flexcanfd_tx_64bytes_datalen); platform_led_toggle(led1); platform_delayms(1000); }}
调用flexcan_configure(),在while中间隔1s中发送标准帧报文,帧id为0x214,数据为定义好的buffer[64]。
在主函数中调用flexcan_fd_interrupt_sample()。
8►验证
连接can调试工具,配置波特率can 1mbps、can fd 2mbps,观测上位机软件:
接收区间隔1s接收到一次fd报文,id为0x214。
在发送区发送标准帧fd报文,id为0x111,发送扩展帧fd报文,id为0x222,各发送5次:
每发送1次报文,接收区接收到1次该id的报文,和程序预期一致。
推动5G商业变现,释放5G商业价值
一文带你看遍LED照明灯具性能特征与注意点(图文)
5G!AMEYA360签约芯讯通授权代理商
3D打的学校在非洲马拉维开学
我国首份生成式人工智能监管性文件已正式实施
使用MM32F0160 FlexCAN-FD接口实现CAN FD通信
传感技术与传感器未来发展趋势与行业特点
日东科技在线式垂直炉提供高效封装固化方案
数独、寄存器和相信的力量
AR技术布局教育行业 让科学教育更简单
基于嵌入式Linux内核的崩溃信息记录机制LCRT的研究分析
雅特力AT32 MCU矢量变频器应用方案,赋能工业自动化高速发展
美限制英伟达对华出口芯片 中方回应
2017年度消费电子展(CES)--- 邂逅Imagination,探索消费电子产品的未来技术!
TCP keepalive机制具体是怎么样的
串口透传模块是什么,它的使用方法是什么
螺纹安装铂电阻 直管封装铂电阻电阻铠装铂电阻精密高 稳定性好
新机频发!最近值得入手的几款手机,华为P10、小米6上榜
PCB板极限温度应该如何测试
磁阀式电流互感器(MVCT)的工作原理及幅频特性研究