ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AUTOSAR CAN驱动EB配置指南:核心参数与500kbps实战

AUTOSAR CAN驱动EB配置指南:核心参数与500kbps实战 搞AUTOSAR底层的人十有八九都要被EB tresos折磨过。尤其是CAN驱动这块看着界面上一堆CanController、CanHardwareObject、CanFilter英文缩写密密麻麻排成一片刚上手的人根本分不清哪些参数决定生死、哪些参数可以一路默认。这篇东西就是把我自己在EB里配置CAN驱动的完整思路、参数含义和踩坑记录整理出来重点讲清楚每个关键配置项到底在干什么、配错了会发生什么以及从零配出一个能跑通500kbps速率的CAN驱动需要经历哪些步骤。不管你是刚接触MCAL配置的应届生还是从其他工具链转过来的工程师这篇文章都值得花十分钟从头到尾读一遍。1. 先搞清楚EB里CAN驱动到底在配什么1.1 CAN驱动在整个软件架构里的位置很多人一打开EB就急着找“CAN那个模块”结果看到Can、CanIf、CanNm、CanTp一堆带Can前缀的模块直接懵了。这里要明确一件事EB里面这些模块分属不同的AUTOSAR层我们这篇文章说的“CAN驱动”特指最底层的Can模块CAN Driver / MCAL层。如果用一句话描述各层关系可以这么理解Can模块是直接操作CAN控制器寄存器的“手”CanIf是帮上层协议栈把数据路由到具体硬件通道的“调度员”CanNm是网络管理CanTp是传输协议。我们在EB里要做的就是把Can模块这双手的每个指头都配置到位让它知道用哪个控制器、哪个邮箱、什么波特率、怎么过滤报文。至于上层怎么调用那是CanIf和PduR的事但底层硬件跑不跑得起来完全取决于Can模块的配置。实际配置时需要注意EB里的Can模块代码生成后API函数是Can_Init、Can_Write、Can_Read等这些函数都会被上层CanIf调用。如果你的工程只有一个Can模块那还好说如果同时配了多个控制器比如两个CAN通道甚至支持CAN FD每个控制器的基地址、中断、波特率都要分别对应正确否则上层报文路由过来的时候数据可能从错误的通道发出去。1.2 EB工程里和CAN驱动强相关的配置入口在EB tresos的工程界面里左侧Module Configuration或者Component列表下面通常会看到以下几个和CAN驱动有直接关系的模块入口Can这就是CAN驱动程序本身我们所有核心配置都在这。CanIfCAN接口层如果只需要验证Can驱动是否通可以先不配。CanTrcvCAN收发器驱动如果你的板子用的是外部收发器芯片比如TJA1043、TJA1051相关的使能、唤醒配置在这里。Port / Mcu / Gpt这几个虽然不是CAN专属但引脚复用、时钟使能、时间基准都和CAN驱动能否工作密切相关。经验之谈新人最容易犯的错就是只盯着Can模块配置忽略了Mcu模块里CAN外设时钟是否打开、Port模块里CAN收发引脚是否被复用对了结果生成的代码在硬件上完全没反应查半天发现是时钟没配。所以我建议你在动手之前先把Mcu时钟树和Port引脚复用表过一遍确认CAN1、CAN2这些外设时钟源是开启状态引脚被正确复用为CAN功能。2. 核心配置参数逐项拆解这是全文的精华部分。EB里Can模块的配置项很多但真正决定驱动能不能用的主要集中在CanGeneral、CanController、CanHardwareObject这几组。我把每个关键参数的含义、推荐值和配错后果写详细一些你以后配置的时候直接拿来对照。2.1 CanGeneral全局参数影响行为模式的基座CanGeneral是Can模块的全局配置容器里面有一堆开关和周期参数。重要的几个如下。CanDevErrorDetect开发阶段错误检测开关。置true时生成的代码会检查API调用参数合法性比如指针是否为NULL、句柄是否越界出错会调用Det_ReportError。建议开发阶段打开量产时关掉。这个参数如果不开很多配置错误会被静默吞掉——比如Can_Write参数传错了函数直接不干活你根本不知道原因。CanIndex模块索引。一个工程里如果只配一个Can实例通常就是0。它不是优先级也不是通道编号就是AUTOSAR模块实例的区分序号在多实例配置时才有实际意义。CanRxProcessing和CanTxProcessing这两个参数决定接收和发送是在中断里处理还是主循环轮询。可选值一般是INTERRUPT或POLLING。实际项目里接收建议用中断因为报文来了不会丢发送如果总线负载不高、或者你想简化逻辑轮询也可以但会占用CPU时间。需要注意这个开关只决定Can模块内部的处理方式中断能不能触发还取决于你在代码里调没调Can_EnableControllerInterrupts以及中断服务函数有没有被正确注册到向量表。CanMainFunctionPeriodCan_MainFunction_Read之类的周期函数的调用周期单位是秒。这个参数更多是给OS任务配置做参考的EB本身不会强制管理但周期函数连续调用的间隔如果超过这个值接收报文就有超时风险。CanMultiPduSupport一个硬件对象是否支持承载多个PDU。如果你是做传统CAN建议false一个硬件对象对应一个报文做CAN FD或者复杂报文收发时可以打开。打开后资源开销会大一些。这里我还想特别提醒一个隐藏很深的参数——CanVersionInfoApi。它决定是否生成Can_GetVersionInfo函数。很多人的工程会把所有API都生成出来但实际没用到的函数会造成额外的代码空间占用。我个人习惯是关掉不用的API除了看起来清爽对OTA升级时的Flash分块也有好处。2.2 CanController波特率与时钟才是重灾区CanController组里配置的是CAN控制器硬件本身。一个控制器对应芯片上的一个CAN外设比如S32K1xx系列里的CAN0、CAN1所以你有几个CAN通道就要在这里添加几个控制器条目。CanControllerBaseAddressCAN控制器的寄存器基地址。这个参数必须和芯片数据手册完全一致。举例来说某款芯片CAN0的基地址是0x40024000你如果填成了0x40025000生成的Can_Init里访问的全是错误寄存器控制器根本初始化不起来。这个参数配错的现象很诡异——代码看似正常执行但寄存器没写进去读状态全是复位默认值。我建议每次拿到芯片都先打开数据手册Memory Map表对照着填别凭印象。CanControllerClockMhzCAN控制器的输入时钟频率单位MHz。这个参数和波特率计算直接相关。CAN控制器内部的位时序都是基于这个时钟分频得到的填错的话波特率会朝着一个奇怪的值跑比如你想配500kbps实际跑出来是400kbps总线上两个节点就会不停报错。CanControllerBaudRate目标波特率单位bps。常规项目一般就是500000、250000、125000这几个档位。这个值和你上面配置的外设时钟、采样点取值共同决定了位时序寄存器里的具体数值。CanControllerPropagationDelay传播延时补偿单位秒。这个参数用来补偿收发器和总线上的物理延时在长距离、高波特率场景下需要认真算一般板级短距离通信可以给一个很小的值或者维持默认但总线长度超过1米、波特率大于500k时建议按照“2×物理介质单程延时”去填。CanControllerPin收发器控制引脚。很多板子用GPIO控制CAN收发器的STBstandby或EN引脚CanControllerPin就是干这个的。如果这里没配收发器可能处于睡眠模式结果是节点自己认为发送成功了但总线上其他节点完全听不到。这个问题极其隐蔽尤其是在用TJA1043这类带模式控制的收发器时。CanControllerTxPduCleanupTime发送缓冲区清理时间。发送完成后硬件邮箱不会立刻释放需要等一段时间才能真正被复用。这个值设得太小连续发送时会偶发丢帧设得太大高频发送时邮箱不够用。一般取发送一位时间bit time的几十倍即可实际工程里我常用默认值只有做极限压力测试时才去调。配CanController时还有一个容易忽略的点多个控制器条目之间的配置拷贝。有些工程师图省事把一个控制器的配置复制过去改个基地址就算完事但像CanControllerClockMhz这种参数如果两个控制器来自不同时钟域比如一个来自PLL一个来自FIRC波特率就全乱了。所以每增加一个控制器所有参数都要逐项检查不要用复制粘贴后只改一两个字段的方式偷懒。2.3 CanHardwareObject收发通道与验收滤波CanHardwareObject简称HOH是CAN硬件邮箱/对象的软件抽象。每个HOH对应一个可以收发报文的硬件资源比如一个邮箱或者一组FIFO。这是整个CAN驱动配置里业务相关度最高的部分因为上层每个PDU都要映射到一个HOH上。CanObjectTypeHOH的方向RECEIVE或TRANSMIT。需要注意有些芯片的邮箱只支持单向有些支持双向切换配置时看清芯片手册。如果收发共用一个邮箱配置错了方向数据往里写的时候可能会把硬件状态机搞乱。CanHandleTypeBASIC或FULL。FULL类型的HOH在硬件上独占一个邮箱适合高频收发BASIC类型的HOH在硬件上多个HOH共用一个邮箱靠软件区分不同ID适合CAN ID多但单个ID频率不高的场景。用BASIC时有个经典坑多个HOH共用硬件邮箱收到报文后如果软件判断这个ID不是当前要处理的会丢弃如果上层把报文频率预期得过高实际丢帧率会突然上升。CanIdTypeSTANDARD11位标准帧或EXTENDED29位扩展帧。这个要和你上层PDU配置的CAN ID类型严格对应。配错了的话报文用的是扩展ID格式但驱动只去匹配标准ID结果是收发永远对不上。CanHwObjectCount硬件对象数量。对支持多邮箱的芯片这个值要小于等于芯片实际可用的邮箱数否则生成代码会访问越界硬件资源。CanFilterMask和CanFilterCode验收滤波匹配值。这是新手翻车率最高的地方。不少CAN控制器的接收过滤逻辑是这样的只有当(接收到的ID异或CanFilterCode) 与 CanFilterMask 按位与的结果等于0时报文才被接收。用公式表示就是((ID ^ FilterCode) FilterMask) 0。这里我给一个实际例子如果你只想接收CAN ID为0x123的报文且只关心标准ID那么FilterCode填0x123FilterMask填0x7FF这样就只有ID完全等于0x123的报文能通过。如果你想把0x100~0x11F这一片ID都收进来Mask就要把后5位遮挡掉填成0x7E0Code填0x100。很多工程师分不清Mask里0和1的作用把Mask填反了结果要么所有报文都进不来要么所有报文都放行后者在总线繁忙时直接表现为控制器不停进中断、CPU占用率暴涨。CanFIFO是否启用FIFO模式。启用后多个HOH共享一个硬件FIFO配合DMA可以实现零拷贝接收。但这个特性对芯片支持有要求别在普通CAN控制器上硬开否则生成的代码里会有一堆无效的FIFO操作逻辑。配置HOH时我强烈建议做一个Excel映射表把每个HOH的编号、方向、ID类型、关联PDU、滤波值全部列出来。因为EB里配置项是树状的你很难一眼看出哪个HOH对应业务里的哪个报文。特别是CAN ID一多靠脑子记忆迟早出错。2.4 中断配置收不到数据的罪魁祸首之一CAN驱动在中断模式下接收完成、发送完成、错误告警都会触发中断。EB里中断相关的配置分散在Can模块和MCU的中断配置模块里。在Can模块内部你需要确认CanRxProcessing和CanTxProcessing确实是INTERRUPT模式在MCU层的中断控制器里需要把CAN外设的中断使能打开并配置好优先级。这两个地方的开关是与的关系——任何一个没打开中断都不会触发。关于中断优先级我建议CAN接收中断的优先级设得比普通外设高但又不能高于调度器的tick中断。如果优先级设得比OS tick还高高频率报文会打断系统调度严重时看起来就像系统卡死。另外很多芯片的中断服务函数入口需要你手动注册EB生成的代码不会自动帮你挂到向量表上这个步骤最容易漏。3. 实操从零配置一个500kbps的CAN驱动这部分我把整个配置流程走一遍以一颗典型的带有FlexCAN外设的MCU为例目标就是跑通一个标准帧收发波特率500kbps。不同芯片的具体界面和参数细节有差异但思路完全一致。3.1 建工程和加载驱动模块的准备工作在EB tresos里新建工程后第一步是把芯片对应的MCAL驱动包导入进来一般是一个包含arxml描述文件和编译产物的插件集合。导入后在模块列表里出现Can、Mcu、Port等模块就算加载成功。接着建议先配Mcu和Port再配Can。Mcu里把CAN外设的时钟打开Port里把CAN相关引脚复用为CAN功能。还有一个前置工作是把系统时钟链路理清——CAN外设时钟到底来自哪个PLL频率是多少。这个频率值要手动记录后面填CanControllerClockMhz时要用。举一个具体计算例子。假设芯片CAN外设时钟来自PLL频率为40MHz目标波特率500kbps位时间为1 / 500000 2μs。如果预分频值BRP取4则每个时间量子TQ的长度为4 / 40MHz 0.1μs 100ns2μs的位时间就等于20个TQ。按经典CAN位时间结构Sync段固定占1个TQ假定采样点取75%则TSEG1 TSEG2 19个TQ其中TSEG1 14个TQ、TSEG2 5个TQ采样点位置是(1 14) / 20 75%。这个75%对500kbps这种中等速率足够但如果总线较长建议采样点提高到80%以上压采样点通常用于容忍线缆传输延时。在EB界面里有些芯片的Controller配置里会直接暴露TSEG1、TSEG2、BRP这些位时序参数有些则是封装在厂商特定的配置子容器里。后者你只需要填好CanControllerClockMhz和CanControllerBaudRate代码生成工具会自动帮你算好分频寄存器的值。但自动计算不等于完全可信——生成完成后最好反推检查寄存器值对应的实际波特率偏差超过1%就要排查时钟源配置。3.2 配置CanController条目的完整步骤在EB的Can模块下找到CanController容器按下面步骤操作右键添加一个CanController条目。CanControllerBaseAddress填0x40024000以芯片手册为准。CanControllerClockMhz填40。CanControllerBaudRate填500000。CanControllerActivation勾选true。如果使用了外部收发器控制引脚在CanControllerPin里选好Port引脚。这里有一个容易踩的坑是CanControllerActivation。有些工程师配完了控制器但这个开关还是false生成的Can_Init里根本不会执行该控制器的初始化代码总线引脚一直是高阻状态示波器量不到任何波形。这个参数和“当前是否使用该通道”直接相关不用就false用了必须true。配置完控制器后顺手检查CanControllerRef这个引用关系是否指向正确的控制器定义。这个引用在多控制器工程里极其重要CanHardwareObject是靠它才知道自己挂在哪个控制器下面。引用配错数据线程全乱。3.3 配置硬件对象和收发映射控制器配好后在CanHardwareObject容器里添加HOH条目。以最简单的收发各一个为准添加一个CanHardwareObjectCanObjectType选择RECEIVECanIdType选择STANDARDCanObjectId填对应的邮箱编号比如邮箱0。再添加一个CanObjectType选择TRANSMIT邮箱编号填1。给接收HOH配置CanFilterCode为0x123CanFilterMask为0x7FF这样只放行ID为0x123的标准帧。将两个HOH的CanControllerRef都指向第3.2步创建的控制器。在EB的代码生成后上层CanIf会通过Can_Write函数和收发信ID来索引HOH。索引顺序不是你在界面上添加的顺序而是由内部的CanObjectId等参数决定的映射关系。所以实际项目中我强烈要求HOH的ObjectId和芯片邮箱物理编号一一对应避免交叉映射导致的神秘报文错乱。3.4 配置中断和轮询模式把CanRxProcessing设为INTERRUPTCanTxProcessing设为INTERRUPT。然后在MCU中断模块里找到CAN对应的中断源使能它优先级按项目需求设置一般给个中等偏高的优先级。中断服务函数的名字通常在EB生成的Can_Cfg.h或相应头文件里有明确函数原型比如Can_RxIsr、Can_TxIsr之类。如果EB没有把这些函数自动注册到启动文件你需要手动在启动文件或中断向量表里加上这串地址否则中断一触发就会跑飞。如果你想用更简单的轮询方式快速验证硬件通路可以把两个Processing都改成POLLING然后在主循环里按周期调用Can_MainFunction_Read和Can_MainFunction_Write。但注意轮询模式下如果主循环周期不稳定报文丢失率就会不稳定所以这只适合调试量产尽量用中断。3.5 生成代码、集成与回环验证一切配置完成点击生成代码。生成后建议先看一下生成的Can_Cfg.c和Can_Cfg.h里面几个关键宏——确认你配置的参数真的生成到代码里了。比如波特率相关寄存器初始化值、滤波寄存器的值顺手对一下3.1节的计算结果。集成到工程后第一步验证不是接总线而是先做自测。把另一个CAN节点或CAN分析仪接到总线上只用最简单的自测方式发送端周期发一帧接收端看能不能收到。如果手边没有分析仪先在芯片内部做Self-Test回环仍然是更稳的起点——把CAN控制器的回环模式打开自发自收如果自己能收到自己发的报文说明控制器、中断、HOH映射、滤波这部分逻辑基本没问题剩下才是驱动收发器芯片和总线布线的事。我这里特别强调回环自测的原因它能一次性把软件配置问题和硬件通路问题分开。如果回环能收说明软件侧OK问题在硬件如果回环都不收那问题肯定在软件配置或芯片本身。这个排查思路帮我省下了大量时间。4. 常见问题与排查实录4.1 配置了但完全收不到数据这种问题排在第一位原因也最多。按我的排查顺序来先确认物理层示波器或者逻辑分析仪探一下CAN_H和CAN_L之间的差分波形正常空闲电平是2.5V对2.5V差分0V。没波形就往收发器供电、模式控制引脚查。再看回环模式把控制器切到回环自发自收确认软件通路是否正常。然后查滤波用4.2节里提到的公式手算一遍FilterCode和FilterMask确认要收的ID确实能通过。最后查中断如果用的是中断模式打断点在ISR入口看是否进来过。这四步里滤波配置出错占的比例最高。Mask和Code搞反、ID类型配错、标准帧扩展帧搞混都是常见低级错误。我可以负责任地说刚接触CAN配置的人踩的坑十有八九都在滤波。4.2 发送一直Pending或超时发送时Can_Write返回OK但上层迟迟收不到发送完成事件大概率是以下原因Can_Transmit调用的HOH号不对写到了不存在的硬件对象上。Tx中断没开发送完成标志一直在硬件里挂起。CanControllerTxPduCleanupTime设得过大导致同一个HOH被占住后续报文排队超时。外部收发器处于休眠模式请求发上总线了但没人收到控制器侧因为ACK保护一直重发。排查发送问题时可以看CAN控制器的状态寄存器——如果一直有“发送未完成”或者错误计数器在涨优先查收发器引脚配置和总线是否真的连了其他正常节点。很多人忽略了一个细节CAN协议要求发送节点必须从总线上收到至少一个ACK位如果总线上一个其他节点都没有某些控制器会一直重发直到超时。这在单节点调试时极其常见别误判成软件问题。4.3 多节点波特率不一致的现象总线上两个节点波特率不一致时不会像串口那样出现纯乱码而是会出现持续的Error Frame和总线错误计数增长。现象是接收节点偶尔能收到几个正确报文但大多数时候都在报错。这是因为CAN的位时序对波特率误差非常敏感误差超过1.5%具体取决于SJW和采样点就会频繁报错。排查的时候用分析仪直接解出总线波特率再把两边的BRP、TSEG1、TSEG2算出来对比。这里要特别注意两个芯片即使波特率名义值一样只要时钟源精度不同比如一个来自外部晶振16MHz一个来自内部RC 40MHz±2%都会出问题。high-speed CAN总线设计要求两侧位时间误差控制在0.5%以内所以内部RC时钟做CAN通信有时候就是会莫名丢帧换外部晶振就一切正常。4.4 中断里耗时过长导致漏帧中断模式下如果ISR里做了太多业务处理导致下一个报文来时上一个还没处理完就会丢中断。很多工程师喜欢在Can_RxIsr里直接解析报文、更新状态机、甚至调用上层回调这是大忌。正确做法是ISR里只做最小必要操作把完整报文拷贝到接收缓冲区置个标志位然后迅速退出把真正的解析工作留给主循环。如果报文频率确实很高考虑启用FIFO加DMA的方式让硬件先把报文存起来软件慢慢读。4.5 总线关闭恢复与错误处理CAN控制器在错误计数超过255后会自动进入Bus-Off状态不再参与总线通信。恢复方式有两种一种是软件调用Can_ControllerBusOff后重新初始化另一种是硬件自动恢复等待128次总线空闲。在EB的Can模块里可以通过配置错误中断和BusOff恢复相关参数来决定行为模式。实际项目里我建议捕获BusOff事件记录日志再主动请求恢复而不是完全依赖硬件自动恢复——因为硬件自动恢复虽然简单但如果你不知道节点为什么进入BusOff等它恢复后再次进入的循环会持续存在无法定位根因。5. 最后分享几个我实际配置中的习惯文章最后分享几个我踩过不少坑之后形成的固定动作。这些谈不上高科技但确实能在关键时刻救你一命。第一每次配置完成生成代码后第一件事是diff一下Can_Cfg.h和上次能正常工作的版本。EB的图形界面操作容易让人眼花但生成的配置头文件是纯文本用diff工具一眼就能看出这次改动动了哪些参数。很多莫名其妙的问题都是界面操作时不小心把哪个参数改回去了。第二给每个HOH建立硬件映射文档。我在项目里维护一个Excel表横轴是芯片邮箱号纵轴是HOH序号、ObjectId、PDU ID、帧ID、收发方向、滤波值。每次在EB里动配置之前先在这个表上改改完再回EB操作。这样做的原因是EB的HOH排序逻辑和芯片邮箱物理编号不一定一致没有这个映射表排查问题时候找邮箱找半天。第三波特率相关参数不要只记在EB配置里要把时钟链路一起记录下来。我见过太多工程换了一版board bring-up代码PLL配置变了CAN时钟从40MHz变成80MHz但CanControllerClockMhz还停在40结果整条总线都废了。这种问题如果有时钟链路文档五分钟就能定位。第四调试初期把所有验收滤波先放宽先用回环模式把收发主链路跑通再逐步收窄滤波范围。一上来就配严格的Mask和Code出了问题根本分不清是滤波的问题还是中断的问题。我习惯的顺序永远是回环全收→回环滤波→外部回环接分析仪→严格滤波。CAN驱动配置说难不难说简单也不简单本质上就是一个“参数和硬件一一对应”的体力活。但只要理解了每个参数背后的硬件逻辑配置起来就会顺畅很多。希望这篇文章能帮你在EB里少走几条弯路把更多时间留到真正需要动脑子的上层业务开发上。
返回列表