ARTICLE DETAIL

资讯详情

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

TC397开发板实战:CAN FD、LCD与SD卡打造车载数据记录仪

TC397开发板实战:CAN FD、LCD与SD卡打造车载数据记录仪 做嵌入式开发这些年英飞凌的AURIX系列一直是我工具箱里最常用的一类车规级芯片。尤其是TC397CAN FD、以太网、LIN、SPI、I2C、SDIO这些接口一次给齐三核TriCore架构跑起来主频直接上到300MHz用来做车载网关、BMS主控或者域控制器都拿得出手。今天这篇不聊虚的就围绕一块TC397开发板上的三个板载资源——CAN FD通信、LCD显示、SD卡存储从原理讲到代码再讲到怎么把三者串成一个能落地的车载数据记录仪。适合刚入手AURIX、被官方例程劝退过、或者想把CAN FD和FATFS整套流程吃透的开发者参考。这篇教程我会把所有关键参数的计算过程、寄存器配置的来龙去脉、以及实际踩坑的经历全部摊开讲。你不需要逐字背但建议把文章里涉及配置的部分对照自己的板子过一遍因为TC397家族内部不同型号、不同开发板的时钟和外设映射是有差异的直接抄配置表容易翻车理解了原理才能举一反三。1. 先认识TC397开发板板载资源与开发环境准备1.1 芯片与板卡定位TC397属于英飞凌AURIX TC3xx系列定位是汽车电子里的中高端主控。它的看家本领是安全岛Safety Island加多核TriCore架构可以在一个芯片上同时跑控制算法、通信协议栈和诊断功能并且满足ISO 26262功能安全要求。对于开发者来说最直观的感受是外设非常齐全MCMCAN模块支持CAN FD、支持多达64字节数据场多个SPI和I2C通道ETH以太网SDIO再加上丰富的定时器和GPIO几乎是一辆车能用到的接口它都给了。我手头这块板子是英飞凌官方风格的TC397开发板板上直接引出了CAN收发器、SD卡卡座和LCD扩展接口。这类板子的最大价值在于你不用自己画原理图、不用纠结电源和时钟树拿到手就能从第一个例子开始跑非常适合作为AURIX入门的跳板。1.2 开发环境安装与第一个工程很多朋友卡在第一步TC397用什么编译器、哪里下载环境。英飞凌官方提供了一套免费IDE叫AURIX Development Studio简称ADS基于Eclipse改的。这个工具最大的优点是完全免费并且内置了Tasking编译器授权不用额外折腾License。如果你喜欢用HighTec或者纯命令行方式也可以只装编译器自己搭工程但建议新手直接从ADS起步省心。装好ADS之后第一次新建工程时选设备型号TC397对应的芯片型号一般是TC39x系列里的某一颗具体看板子丝印。工程模板会自动帮你初始化时钟和几个核心外设编译下载用板载的DAP调试器。这里有一个非常容易踩的坑ADS自带工程模板默认的编译器版本和老工程不一致时打开会报一堆语法错误解决办法不是硬改代码而是右键工程属性在Toolchain栏切换成当前版本。2. CAN FD通信采样点计算、报文解析与工程配置2.1 CAN FD相比经典CAN进步在哪里CAN FDCAN with Flexible Data-rate是博世在经典CAN 2.0基础上扩展出的协议核心变化有两个一是数据场长度从8字节提升到最多64字节二是仲裁段和数据段可以使用不同的波特率数据段最高能跑到5Mbps甚至更高。这意味着同样的总线时间里能塞进去的信息量翻了好几倍。对于TC397的MCMCAN模块来说它原生支持CAN FD不需要额外芯片。但注意总线上的收发器也必须支持CAN FD板载的一般没问题如果是自己外接节点建议选TJA1044或同类CAN FD收发器不要用老款的TJA1050否则高速数据段跑不稳。2.2 采样点原理与位时序计算采样点是CAN通信里最玄乎也最关键的概念。一条CAN总线报文在传输时接收方在每个位时间Bit Time的中点附近采样这个采样时刻在单位时间内的百分比位置就是采样点。采样点太靠前容易采到前一位的尾巴太靠后又可能在位边沿附近采到不确定电平。经典CAN一般推荐87.5%CAN FD的仲裁段推荐80%~85%数据段可以略低75%左右比较稳。位时间的计算与TC397的位时序寄存器直接相关。TC397的MCMCAN模块中每个CAN节点的Nominal Bit Timing仲裁段由NBTP寄存器配置Data Bit Timing数据段由DBTP寄存器配置。核心公式是总线波特率 模块时钟频率 /预分频值 × 总TQ个数 采样点 SYNC_SEG TSEG1/SYNC_SEG TSEG1 TSEG2其中SYNC_SEG固定为1个TQ。这里TQ是Time Quantum即最小时间单元一个位时间由若干个TQ组成TSEG1决定采样点位置TSEG2决定采样点到下一位的时间。以TC397外设时钟fCAN100MHz为例如果想把仲裁段配成500kbps、采样点80%500kbps对应的位时间为100MHz / 500kbps 200个TQ此时预分频BRP1采样点80% → TSEG1 200 × 0.8 - 1 159TSEG2 200 - 1 - 159 40于是NBTP配置为NBRP0、NTSEG1159、NTSEG240这样就能得到几乎精确的80%采样点。数据段2Mbps同理位时间为50 TQ如果目标采样点75%TSEG1约等于36~37TSEG2约等于12~13。网上有些帖子讨论采样点设置6501也就是把采样点算到65.01%说稳定无比我第一反应是分组时钟或者预分频大概率没对齐。CAN FD的仲裁段65%采样点确实偏低了在强干扰环境下容易采到错误电平正常车规项目一般不会这么配。2.3 用代码配置CAN FD并抓包验证在TC397上配置CAN FD建议直接用官方提供的MCAL驱动或iLLD库函数效率高也不容易出错。核心步骤如下// 伪代码示意具体以你的工程库函数为准 // 1. 时钟使能 Can_EnableModuleClock(); // 2. 配置节点参数 CanNodeConfig nodeCfg; Can_NodeInitConfig(nodeCfg); nodeCfg.baudrate 500000; // 仲裁段500kbps nodeCfg.baudrateFD 2000000; // 数据段2Mbps nodeCfg.samplePoint 80; // 仲裁段采样点 nodeCfg.samplePointFD 75; // 数据段采样点 Can_NodeConfigure(CAN0, nodeCfg); // 3. 使能CAN FD功能 Can_NodeEnableFD(CAN0); // 4. 添加接收筛选比如接收ID为0x123的报文 Can_FilterConfig filter; filter.id 0x123; filter.mask 0x7FF; Can_NodeRxFilterConfig(CAN0, filter); // 5. 启动节点 Can_NodeStart(CAN0); // 6. 发送CAN FD报文数据场64字节 uint8_t data[64] {0}; Can_SendFDMessage(CAN0, 0x123, data, 64, true); // true表示BRS数据段加速配置完成后建议用CAN分析仪抓包验证。解析CAN FD报文时注意帧格式和经典CAN的不同CAN FD帧在IDE位之后多了一个FDF位用于标志这是CAN FD帧如果BRS位为1说明数据段切换到了加速波特率ESI位则用来标识发送节点是否处于错误被动状态。抓包软件里如果显示Error Frame十有八九是采样点或波特率没对上。实际调试中我遇到过一种情况用分析仪能正常收到数据但两个TC397板子之间通信却失败。后来排查发现是分析仪默认接收所有波特率而两块板子的数据段采样点一个75%一个80%加上线缆较长立造成了位错误。当时还把终端电阻从120Ω换成了60Ω测试其实问题出在采样点不一致。所以做CAN FD联调一定要先统一采样点表格再统一波特率。3. LCD显示SPI屏驱动、40pin接口引脚与中文字库3.1 选哪种屏幕SPI屏还是RGB屏TC397这类芯片内部并没有专门的RGB LCD控制器很多新手看到开发板上有个40pin LCD接口就以为可以像STM32F429那样直接刷RGB屏这是个常见误区。板子上的40pin接口如果是接SPI屏那就是把屏当作普通SPI外设用如果真接了RGB888/RGB565接口的大屏一般还需要外接一颗显示控制芯片比如RA8876这类来负责显存和时序。我的建议是入门阶段优先选SPI接口的TFT屏幕常见驱动IC是ST7789、ILI9341或ST7262。SPI方案占用引脚少初始化简单刷新率虽然不如RGB方案但用来做仪表数据显示、状态监控完全够用。如果你非要上RGB大屏一定要把屏的时序参数和TC397的GPIO翻转速度评估清楚不然很容易出现花屏、闪烁。3.2 40pin接口/SPI引脚定义与初始化时序拿到一块带40pin FPC座子的LCD屏第一件事不是接上就点而是看懂引脚定义。40pin接口里的引脚通常分这几类电源VCC、GND、LED背光正极通常标注LEDA或BL、LED负极LEDK或BL-SPI信号SCLK时钟、MOSI主出从进、MISO主进从出部分屏没有、CS片选、DC/RS数据命令选择、RST复位触摸信号如果有触摸屏T_CLK、T_DIN、T_DO、T_CS、T_IRQ其他背光PWM亮度控制引脚最常见的坑是背光引脚。有些屏的背光正极直接接3.3V就能亮有些需要额外升压电路还有一些把背光控制引脚和PWM共用代码里不初始化PWM输出高电平屏幕就永远是黑的。我调试时遇到过屏幕初始化成功、但就是黑屏的情况最后发现是背光引脚被配置成了普通GPIO没拉高。SPI屏的初始化序列比较固定以ST7789为例典型流程是// 伪代码 LCD_Reset(); // 拉低RESET脚10ms再拉高 LCD_WriteCmd(0x11); // 退出睡眠 Delay(120); LCD_WriteCmd(0x36); // 内存数据访问控制决定扫描方向 LCD_WriteData(0x00); // 更多初始化序列... LCD_WriteCmd(0x29); // 打开显示初始化完成后先做一次全屏填充比如全部填充红色然后再画点测试。如果你刷完0x29屏幕还是白屏优先查RESET时序和DC/CS引脚有没有接对。我见过有人SPI接线全部正确但就是不出画面后来发现是屏幕FPC座子方向插反了引脚全部错位所以插线前一定看下座子上的1脚标记。3.3 显示中文GB2312字库的原理与实现LCD显示中文字是很多项目的硬需求。实现方案无外乎两种一种是把字库烧进外部Flash按GB2312编码偏移读取另一种是把字模数组直接编进代码。前者适合中文字符多、存储空间有限的产品后者适合快速验证。先说字模是怎么来的。中文字模本质上是点阵数据比如16x16点阵一个汉字占32字节8x16点阵的ASCII字符占16字节。用PCtoLCD2002这类工具可以把汉字转成C语言数组或二进制字库文件。生成字库文件时注意选择合适取模方式常用的有逐行式、行列式还有阴码阳码的区别。取模方式不对显示出来的字就是镜像、倒序或者花点。GB2312编码的查找逻辑是一个汉字由两个字节表示第一个字节是区码范围0xA1~0xFE第二个字节是位码范围也是0xA1~0xFE。字库文件里通常按区码和位码的顺序连续存储。读取某个汉字的字模偏移量计算方法是uint32_t get_font_offset(uint8_t high_byte, uint8_t low_byte, uint32_t font_size) { uint32_t region (high_byte - 0xA1); // 区 uint32_t position (low_byte - 0xA1); // 位 uint32_t bytes_per_char font_size * font_size / 8; return (region * 94 position) * bytes_per_char; }这个公式里乘以94是因为GB2312每个区最多94个汉字。拿到偏移之后从字库文件或Flash里读出字节再逐位判断该在哪个坐标画点就能把中文显示到屏幕上了。字符叠加到LCD上的时候注意处理好半角全角混排的坐标对齐问题不然中文和英文混着显示容易对不齐。4. SD卡存储硬件原理图要点与FATFS文件系统移植4.1 SD卡电路设计与引脚说明SD卡是嵌入式系统里做数据落盘最方便的介质但在TC397开发板上用得不好反而会成为整个系统的阿喀琉斯之踵。SD卡在硬件上主要有两种工作模式SDIO模式和SPI模式。TC397自带SDIO控制器推荐用4bit SDIO模式速率高很多SPI模式胜在通用任何有SPI的芯片都能接但速度慢了一个数量级。看SD卡原理图的时候重点看这几个关键点SDIO模式的CMD、D0~D3都要接上拉电阻典型10kΩ上拉到VDD3.3VCLK时钟线不需要上拉但建议串一个小电阻抑制过冲VDD的3.3V电源要加去耦电容至少一个10uF钽电容加一个100nF陶瓷电容卡检测引脚CD不要悬空接上拉电阻后给GPIO判断走线尽量等长SDIO时钟在高速模式下对布线比较敏感比较经典的坑是电源带载能力不足。SD卡写数据时瞬间电流能达到100mA以上如果用LDO给SD卡供电LDO余量不够就会导致电压跌落表现是初始化正常、读写偶尔失败、或者文件系统挂载后目录损坏。这块TC397开发板的SD卡供电是独立轨还是从3.3V主轨拉的需要看原理图确认。如果是从主轨拉建议不要同时挂太多大电流外设。4.2 移植FATFS的六个接口FATFS是目前最主流的嵌入式文件系统方案在STM32上用得很熟的人到了TC397上一样可以用。它的移植核心在于你提供底层读写接口文件系统逻辑它帮你处理。需要实现的接口主要是disk_initialize、disk_status、disk_read、disk_write、disk_ioctl和get_fattime这六个。以TC397的SDIO驱动为基础disk_read的一个简化实现是DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) { // pdrv盘符一般单卡就是0 // 调用TC397的SDIO块读取函数按4字节对齐要求处理buff // 注意sector在FATFS里是512字节对齐的逻辑扇区 for (UINT i 0; i count; i) { if (SDIO_ReadBlock(sector i, buff i * 512) ! SDIO_OK) { return RES_ERROR; } } return RES_OK; }移植时有一个非常隐蔽的性能大坑FATFS默认每次读写的最小单位是512字节一个扇区如果你的底层驱动是按块读的但buff没有4字节对齐有些SDIO控制器的DMA会直接报错。解决办法有两个要么在ffconf.h里打开_USE_LFN并合理设置缓冲区要么在disk_read里做一次内存拷贝对齐。我当时就是临时用了一个静态对齐缓冲区性能稍微损失一点但稳定性提升明显。另外ffconf.h里的配置项要重点看几个_USE_MKFS如果需要在板子上格式化SD卡必须使能_USE_LFN长文件名支持建议使能但会消耗较多RAM_USE_FSINFO使能后启动挂载更快_VOLUMES挂载盘符数量单卡就设1挂载和写文件的流程是固定的FATFS fs; FIL fil; FRESULT res f_mount(fs, 0:, 1); // 挂载到0号盘 if (res FR_OK) { res f_open(fil, 0:/data.csv, FA_WRITE | FA_CREATE_ALWAYS); // 写入数据 f_write(fil, buffer, len, br); f_sync(fil); // 调用f_sync可以立即落盘不是等到f_close f_close(fil); }很多人在写完文件后不调f_sync就直接断点导致数据丢失。f_sync会把FATFS内部缓存的FAT表和目录信息写回到SD卡虽然会降低一点写入速度但对于记录仪这种对数据完整性要求高的场景一定不要省这一步。4.3 掉电保护与性能优化做车载记录仪最怕的就是突然断电SD卡正在写FAT表的时候断电轻则丢数据重则整个分区损坏。硬件上可以在掉电检测引脚触发中断时紧急调用f_sync把关键数据落盘软件上我倾向于用先写临时文件再改名的方式每次记录结束把临时文件改名为正式文件名这样即使上次记录异常中断也能保证旧数据完好。5. 综合联动基于TC397的CAN FD数据记录仪5.1 功能拆解与任务划分把CAN FD、LCD、SD卡三个资源串起来一个很典型的应用就是CAN FD数据记录仪实时接收总线上发来的报文在LCD上显示车速、转速、电池SOC等关键信号同时把完整的原始报文定时写入SD卡供后续分析。TC397的多核架构让任务划分很舒服。我的方案是Core0跑主循环负责任务调度和LCD刷新Core1跑CAN FD中断接收和协议解析Core2SD卡写入和FATFS维护因为TC397每个核有自己的资源和独立的中断控制器CAN接收和SD卡IO可以通过核间通信机制传递数据互不阻塞。核间通信用TC397自带的陷阱Trap/邮箱机制或者简单的共享内存加信号量都行新手建议直接用共享内存加原子操作简单可靠。5.2 核心代码骨架整体流程可以用下面这段伪代码来概括// Core0 主循环 while (1) { // 检查CAN下发的状态信号 display_update_from_shared_data(); delay_ms(50); // 刷新率20fps即可 } // Core1 CAN接收中断回调 void CanRxCallback(uint32_t msg_id, uint8_t *data, uint32_t len) { parse_signal(msg_id, data, len); // 更新共享信号量 log_to_ringbuffer(msg_id, data, len); // 写入环形缓冲区 } // Core2 定期写卡 void StorageTask() { while (1) { if (ringbuffer_not_empty) { f_open(fil, 0:/can_log.csv, FA_WRITE | FA_OPEN_APPEND); f_write(fil, line, bytes, br); f_sync(fil); f_close(fil); } delay_ms(200); } }这里有个细节值得展开CAN FD报文解析成CSV字符串再写入SD卡这个格式化过程很消耗CPU。如果每帧都调用sprintf再f_writeCore2会忙不过来。优化办法是先用snprintf在内存中构建一行然后一次性f_write而不是多次小写入。实测下来一行64字节数据拼装加写入耗时能控制在几百微秒级别记录仪整体吞吐量完全跑得动满载的总线流量。5.3 实测效果与瓶颈分析我在实际调试中满载接收2Mbps的CAN FD报文并全量记录到SD卡CPU占用率表现如下任务Core0Core1Core2LCD刷新高低低CAN FD解析低中低SD卡写入低低中真正的瓶颈往往出现在SD卡写入和LCD刷新同时争抢总线带宽的时候。TC397虽然有DMA但SPI屏刷新和SD卡写操作如果都走同一个SPI控制器就会互相抢占。如果板子上SD卡和LCD共用了一个SPI那综合项目的刷新率就要适当降下来否则SD卡写入超时会触发FATFS错误。我建议的方案是把两者放到不同的SPI控制器上或者在调度上错峰让LCD刷新和SD卡写入不要同一时刻启动。6. 常见问题排查与避坑指南6.1 CAN FD篇现象可能原因排查和解决分析仪能收板间互收不到采样点不一致统一采样点表格仲裁段80%数据段75%加速段全是错误帧数据段波特率没对上检查DBTP配置确认收发器支持CAN FD收发正常但偶发丢帧消息RAM的FIFO深度不够调大接收FIFO深度打开中断优先级使用6501采样点参数异常位时序计算错误重新按TQ总数反算不要照搬网上参数6.2 LCD篇现象可能原因排查和解决白屏背光未拉高或RESET没释放检查背光引脚初始化前先把RESET拉高花屏SPI速率太快或时序不对降低SPI时钟试一下范围一般1M~10MHz中文显示乱码字库偏移算错确认GB2312区码从0xA1开始偏移公式正确刷新有撕裂没有同步控制在VSYNC期间刷新或者只用局部刷新6.3 SD卡篇现象可能原因排查和解决挂载失败SD卡不是FAT32格式在电脑上格式化为FAT32簇大小16K以下写文件后断电丢数据没有调f_sync重要数据每次写入后调f_sync读写不稳定电源供电不足或上拉电阻缺失确认3.3V供电能力CMD/D0-D3接10k上拉文件系统目录损坏非正常拔出或断电可在挂载失败时尝试f_mkfs格式化但会清空数据7. 最后想说的几句实在话这块TC397开发板的板载资源单拎任何一块出来都有官方例程但把它们组合起来做一套完整的数据记录仪才是真正考验功力的时候。我个人的体会是CAN FD这块一定要把位时序和采样点的原理吃透因为它是硬件层最容易出问题也最难排查的点LCD和SD卡则更多是细节问题引脚定义、上拉电阻、对齐缓冲区这些看起来不起眼却决定了稳定性。最后再分享一个小技巧调试这种外设很多的项目建议自己画一张硬件资源占用表把每个外设用了哪个SPI、哪个DMA通道、哪个中断优先级都记清楚。你永远不知道后面加功能时一个中断冲突会浪费多少时间提前规划能省掉很大一部分痛苦。TC397性能很强但好不好用取决于你对外设资源的管理够不够细致。
返回列表