拿到一块TC397开发板很少有人能忍住不去碰板子上那几个“大件”CAN FD接口、彩色LCD、SD卡槽。这三个外设基本对应了车载嵌入式里最常见的三件事——通信、人机交互、数据存储。但实际挨个跑一遍的时候你会发现教程非常碎官方例程偏向底层库函数怎么调社区帖子又各说各话尤其采样点怎么设、LCD接口是RGB还是SPI、SD卡格式化为什么识别不了文件这些坑不真正踩一遍很难讲清楚。这篇文章我把折腾TC397板载资源的完整过程按顺序写下来从环境搭建到三个模块的调试细节外加最后一张排查速查表。适合刚拿到AURIX开发板、想快速上手CAN FD和文件系统的朋友也适合从STM32这类MCU转过来、想看英飞凌iLLD库和传统HAL库差别的人。1. 项目概述为什么这三个模块最值得先吃透1.1 TC397的硬件底子三核300MHz外设资源其实很够用TC397属于英飞凌AURIX TC3xx家族片上集成了三个TriCore内核主频最高能到300MHz。它的定位是汽车域控制器、BMS主控、底盘控制器这类场景所以外设设计上处处透着“要跑实时控制、要过功能安全”的味道。我手里这块板子除了最小系统外板载资源恰好覆盖了日常调试最常用的三样。CAN FD对应的是车控网络通信TC397的MultiCAN模块扩展了CAN FD能力可以通过移位预设支持最高8Mbps的数据段速率这对BMS的刷写、诊断、大数据量报文交互来说非常关键。LCD是给人看的调试状态、波形、参数用屏幕直接输出比串口直观得多。SD卡则是给系统加了一块“硬盘”跑数采、存日志、刷字库都靠它。这三个外设放在一起还有一个隐形好处它们共同构成了一个最小但完整的嵌入式应用闭环——采集到CAN报文分析后显示在屏上再把关键数据落到SD卡。这个闭环可以扩展成很多实际项目的雏形。1.2 这篇保姆级教程的路线图我从一个真实项目开发者的视角来拆解不照着芯片手册念。整条路线分四步先把编译下载环境跑通再单独调通CAN FD接着搞定LCD显示最后用SD卡和FatFS做日志存储。每部分都会给出实际配置和可复用的代码思路。这个过程适合谁参考一是刚从STM32、RT1052这类MCU转向AURIX平台的人你会发现TC397的外设库思想跟HAL库差异很大初始化顺序和中断机制需要重新适应二是已经有CAN调试经验、但对CAN FD采样点、BRS位切换、数据段速率设置还不太清楚的朋友三是在做数据采集类产品想把LCD、SD卡、CAN FD三者真正跑在一起的工程人员。2. 环境准备先把编译、下载和调试这条线打通2.1 工具链选择ADS、TASKING与调试器怎么配英飞凌官方提供了一套免费的AURIX Development Studio基于Eclipse加自研插件内部集成了TASKING编译器。对TC397来说这套工具完全够用你不需要再额外购买许可证。初次安装时要注意版本新版本ADS对TC3xx的支持更完整如果手头芯片比较新尽量下载最新版。很多从TC264转过来的人会问编译器到底选TASKING还是HighTec还是GCC。我的建议是如果只是学习或原型验证直接用ADS自带的TASKING就行因为它与IDE的调试配置深度绑定下载、断点、变量查看都是一键完成。如果你之后要量产、要做编译器认证再考虑HighTec或者GreenHills。没必要在入门阶段被工具链选择拖住。调试器方面常见的支持AURIX的调试器有Lauterbach TRACE32、PLS UDE以及英飞凌自家基于DAP接口的调试器。多数开发板上会集成一个mini DAP下载器直接通过USB连接到电脑新手从这种板载调试器入手最省心。初次连接时如果提示找不到设备先检查USB驱动再看板子是否单独供电很多下载失败都是供电不稳定造成的。2.2 创建工程与管脚映射先理解开发板的资源分配在ADS里新建工程时选择芯片型号TC397注意后缀不同会影响外设端口数量和Flash大小选错型号会导致链接时地址溢出或者外设寄存器地址错误。工程生成后会有一个Cpu0_Main.c入口文件AURIX默认是每核一个main函数你没用到的核也要保留入口不能删除。接下来最重要的一步是查开发板原理图把用到的功能与引脚对应起来。我以常见开发板的分配为例外设模块片内外设常用引脚信号备注CAN FDCAN0_NODE0P20.7 / P20.8 或 P02.0 / P02.1需板载CAN收发器LCD SPIQSPI2P15.3 (SCLK), P15.4 (MISO), P15.5 (MOSI), P15.1 (CS)具体看屏驱动LCD背光PWM / CCU6定时器输出脚控制亮度SD CardQSPI0CS、SCLK、MOSI、MISO注意SD卡SPI引脚上拉注意不同开发板的管脚映射差异很大尤其是LCD接口和SD卡槽的片选引脚。动手写代码前先把原理图对应的引脚表整理出来这能帮你省下至少半天查线时间。2.3 最小系统验证点灯工程跑通心里才有底拿到新开发板我习惯先跑一个GPIO点灯程序验证整个工具链。不要一上来就写CAN和LCD因为变量太多一旦出问题你分不清是代码问题、引脚问题还是调试器问题。点灯工程的实质是配置端口复用功能为GPIO输出然后循环翻转电平。在TC397上端口配置是通过IfxPort_setPinMode和IfxPort_setPinState完成的。代码里要特别注意引脚的上下拉模式和驱动强度TC397的GPIO默认状态是输入即使你把它配置为输出也要确认外部电路没有强下拉把电平拉死。编译后点击调试按钮如果程序能正常下载并停留在main函数说明下载链路、启动文件、链接脚本都没问题。如果下载时报“不能擦除Flash”或者“Device locked”一般是芯片被保护了需要先用调试器执行解锁命令并全擦除一次。这一步做完后面调外设就安心很多。3. CAN FD从寄存器到报文把采样点拿捏死3.1 TC397上的CAN FD硬件MultiCAN模块怎么用TC397的CAN模块不是简单的“两个CAN外设”而是基于MultiCAN架构每个CAN节点都有独立的Message RAM区和过滤器配置支持经典CAN和CAN FD。CAN FD与经典CAN最大的区别是数据段速率可以比仲裁段速率高一帧报文里可能存在两种位时间仲裁段仍用标准速率保证总线冲突检测数据段切到高速率搬运数据。在TC397的iLLD库里CAN配置被拆成模块级、节点级、消息对象级三个层级。模块级需要使能时钟、设置中断优先级节点级需要配置位时间、采样点、收发引脚消息对象级则是配置收发缓冲区的ID、DLC、方向和帧类型。刚开始接触时会觉得层级多但好处是多个节点可以复用同一个底层模块不同速率、不同滤波器互不干扰。实际项目里我习惯把CAN初始化和收发封装成独立文件应用层只关心Can_SendFrame和Can_RxCallback这样后续换芯片、换工程也能快速复用。3.2 位时间与采样点65%不是玄学很多人一谈到CAN FD就卡在采样点设置上。所谓采样点是指节点在接收一位数据时在位的哪个时刻进行电平采样。采样点太靠前可能没等信号稳定就采太靠后容易采到下一位的边沿。经典CAN一般建议采样点设置在75%~80%CAN FD由于数据段位时间较短数据段采样点通常建议65%~75%仲裁段可以保持75%左右。采样点的计算公式是采样点 (SYNC_SEG TSEG1) / (SYNC_SEG TSEG1 TSEG2)。其中SYNC_SEG固定为1个时间量子TSEG1和TSEG2是需要配置的段长度。举例来说如果CAN模块时钟是80MHz想实现仲裁段500kbps、数据段2Mbps那么仲裁段位时间是80MHz / 500kbps 160个时间量子数据段位时间是40个时间量子。再结合目标采样点算出TSEG1和TSEG2的比例写入节点配置结构体的nominalBitTime和dataBitTime字段。速率段波特率位时间(tq)采样点TSEG1TSEG2仲裁段500k16075%11940数据段2M4070%2712注意实际采样点还要受SJW同步跳转宽度影响。SJW解决的是总线时钟偏差带来的相位漂移一般设为1到4个tq。不要追求极端速率组合CAN FD数据段超过5Mbps后对收发器和PCB要求都很高普通开发板布线和接插件质量不一定撑得住。3.3 iLLD库配置CAN FD节点的完整流程下面给出一段精简但完整的CAN FD发送配置流程用的是官方iLLD库接口。核心步骤是初始化模块、配置节点位时间、配置消息对象、发送报文。/* 模块级初始化 */ IfxCan_Can_Config canConfig; IfxCan_Can_initModuleConfig(canConfig, MODULE_CAN0); IfxCan_Can_initModule(canConfig); /* 节点配置 */ IfxCan_Node_Config nodeConfig; IfxCan_Node_initConfig(nodeConfig, canConfig); nodeConfig.baudRate 500000; /* 仲裁段波特率 */ nodeConfig.baudRateData 2000000; /* 数据段波特率 */ nodeConfig.samplePoint 7500; /* 75.00% */ nodeConfig.samplePointData 7000; /* 70.00% */ nodeConfig.pins.rx IfxCan_RXD0A_P20_7_IN; nodeConfig.pins.tx IfxCan_TXD0_P20_8_OUT; IfxCan_Node_init(nodeConfig); /* 消息对象配置 */ IfxCan_Node_MessageObjectConfig msgObjConfig; IfxCan_Node_initMessageObjectConfig(msgObjConfig, nodeConfig); msgObjConfig.messageId 0x123; /* 标准帧ID */ msgObjConfig.control IfxCan_MessageObjectControl_transmit; msgoObjConfig.frameType IfxCan_FrameType_transmitFd; IfxCan_Node_initMessageObject(msgObjConfig); /* 发送一帧CAN FD报文 */ IfxCan_Frame frame; frame.messageId 0x123; frame.data[0] 0x01; frame.frameType IfxCan_FrameType_transmitFd; frame.dlc IfxCan_DataLengthCode_8; IfxCan_Node_transmitMessage(nodeConfig, msgObjConfig, frame);接收侧一般开启FIFO中断或者单个消息对象中断在中断回调里读取IfxCan_Node_receiveMessage。TC397每个核都有自己的中断系统初始化中断时要明确是挂在CPU0还是CPU1不然中断可能永远不触发。我踩过最典型的坑就是把CAN中断配在CPU0但CPU0跑着IDLE任务看起来像“没收到报文”实际是中断被其他任务优先级压住了。3.4 报文解析与实测用USB-CAN收一帧代码能发出来不代表总线上真的就对。调试CAN FD最实用的工具是带CAN FD功能的USB-CAN分析仪配合上位机可以看到总线上每一帧的ID、DLC、采样点位置以及是否有CRC错误、格式错误。实测发送时重点观察三个标志位FDF位是否为隐性如果FDF位没有拉高说明发送的还是经典CAN帧BRS位是否为隐性如果BRS位没切换说明发送端虽然配置了数据段速率但实际数据段仍然使用仲裁段速率ESI位则标记发送节点是否处于错误被动状态。如果你手头没有CAN FD分析仪用普通示波器看差分信号也能大概判断CAN FD数据段的位宽明显比仲裁段窄波形上会出现一段“突然加密”的区域。如果担心采样点设置不对把CAN收发器出来的CANH/CANL直接并在示波器上看眼图数据段一位的长度是否稳定、有没有明显振铃。遇到发送超时优先检查终端电阻CAN FD对阻抗匹配更敏感两个120Ω终端电阻不能少。4. LCD显示RGB屏和SPI屏分别怎么驱动4.1 先搞清楚开发板上的LCD接口类型TC397虽然性能很强但芯片本身没有集成像STM32 LTDC那种专门的点阵LCD控制器。所以开发板上的LCD接口通常分为两类一类是40pin的RGB接口一组数字并口直接对接TFT屏的RGB数据线需要外部LCD控制器或FPGA配合另一类是SPI接口直接驱动带控制器的IPS屏幕比如常用的ILI9341、ST7789。判断一块开发板的LCD接口属于哪种类型最直接的方法是看原理图上有没有RGB数据线。出现LCD_R0、LCD_G5、LCD_B7、LCD_DE、LCD_VSYNC、LCD_HSYNC这类信号就是RGB接口如果只有SCLK、MOSI、MISO、CS、DC、RESET那就是SPI屏。本文标题里提到的“40pin LCD接口”绝大多数情况下指的就是RGB888接口。这类屏没有内置控制器MCU要么通过并行总线外挂RA8876这类LCD控制器要么用FPGA从MCU拿命令、再去刷新屏幕。TC397要想直接驱动RGB屏必须用外部存储器接口EBU把像素数据写到外置LCD控制器开发和调试门槛会比SPI屏高一个量级。4.2 40pin LCD接口的引脚与时序要点RGB LCD屏与MCU之间的连接信号大体分为四组电源和背光、像素时钟、行场同步、RGB数据线。咱们按一组典型的40pin RGB接口来拆解引脚类型信号名作用电源VCC(3.3V/5V)、GND屏供电注意背光电流背光LEDA / LEDK背光正负极LEDA常用PWM控制亮度时钟同步LCD_CLK、LCD_VSYNC、LCD_HSYNC、LCD_DE像素时钟、场同步、行同步、数据使能RGB数据LCD_R[7:0]、LCD_G[7:0]、LCD_B[7:0]24bit真彩数据线控制RESET、PWR_CTRL复位和电源控制TC397直接驱动RGB屏时最麻烦的不是数据线本身而是像素时钟的生成。比如一块800×480的屏刷新率60Hz时像素时钟大约在33MHz附近这个频率对GPIO翻转来说完全不可行必须有硬件时钟源配合。如果你的方案是外挂LCD控制器那么控制器负责生成像素时钟和同步信号MCU只需要通过并口或串口把要显示的内容发给控制器。提示RGB屏的极性配置非常关键。VSYNC/HSYNC有正极性和负极性之分DE信号是数据有效标志有的屏要求DE模式下HSYNC/VSYNC被忽略。新手最容易犯的错误是认为所有RGB屏时序都一样结果屏幕要么不亮要么图像错位、颜色分层。4.3 QSPI驱动SPI TFT的实操经验如果你的板载LCD是SPI接口的IPS屏幕驱动起来比RGB屏友好得多。TC397的QSPI模块在SPI主模式下的速率最高能跑到几十MHz刷新一张320×240、16bit色深的小屏足够用。SPI屏的驱动逻辑是通过SPI发送命令和数据先初始化控制器软复位、关显示、设置像素格式、开显示然后周期性把显存里的像素数据通过SPI接口刷新到屏幕上。初始化和画点函数网上有很多现成的这里不重复抄代码我更想强调三个实际经验。第一SPI的时钟极性CPOL和相位CPHA必须和屏幕控制器的数据手册一致。ILI9341通常要求CPOL0、CPHA0但有些ST7789模块需要CPOL0、CPHA1搞错之后屏幕大概率白屏或者花屏。第二DC引脚的切换顺序要严格遵循“写命令之前把DC拉低写数据之前把DC拉高”这个切换通常放在SPI传输函数里和CS、字节发送构成一个原子操作中间不能被中断打散。第三刷新一帧全屏数据量很大如果直接用阻塞式SPI发送画全屏时CPU会被占死。建议把显存放到片内RAM或外部SDRAM再用QSPI的DMA模式刷屏这样CPU可以腾出来处理CAN报文和SD卡写入。背光调节方面SPI屏的背光LEDA引脚通常接一个三极管或MOS开关通过PWM占空比控制亮度。PWM频率不要低于1kHz否则人眼能感觉到闪烁。引脚驱动能力有限不要直接用GPIO灌电流给LED背光会让芯片发热甚至损坏。4.4 中文显示方案点阵字库和常用路径让LCD显示中文是许多新手的“第一座山”因为这些屏本身不认识汉字它只认识点阵或字符编码。要在SPI/RGB屏上显示中文主流有三条路。第一条路使用自带字库的LCD模块。这类模块内置了GB2312/GBK字库芯片比如中景园的1.8寸屏就带字库MCU只需要把汉字的GB2312编码通过指定命令发给模块模块自己完成字模查询和点阵绘制。优点是开发快缺点是不灵活字库大小和字体样式固定。第二条路把字库放到SD卡或者外部Flash里。启动时读取字库文件建立字模索引渲染时根据GB2312编码查表、拷贝点阵到显存。实现起来自由度最高但要注意字库文件格式和编码一致性——字库文件里存的是GB2312点阵你输入的字符串是UTF-8直接查表会乱码需要先做编码转换。第三条路用PCtoLCD2002这类工具把常用汉字预先取模生成C语言数组随固件一起编译进Flash。适合只需要显示固定菜单、少量提示文字的场景比如“电压”、“电流”、“温度”这些恒定词汇。我实际做项目时如果屏幕和SD卡同时存在大概率会用第二种方案把字库做成BIN文件放到SD卡程序启动时任选字体灵活度最高。如果只是临时调试就退回到第三种用取模工具生成几个关键字的点阵数组速度快、依赖最少。5. SD卡与FatFS把数据存下来并且能找得回5.1 SD卡原理图与SPI模式初始化TC397没有SDIO控制器所以驱动SD卡最普遍的方式是SPI模式。SD卡的SPI引脚定义非常规范CS片选、SCLK时钟、MOSI命令/数据输入、MISO数据输出。原理图设计时最关键的是上拉电阻和供电电容。CMD线在SPI模式下对应MOSI和DO线MISO都需要接上拉到3.3V阻值一般选4.7kΩ到10kΩ。原因很简单SD卡协议要求这些信号在空闲状态保持高电平如果引脚悬空卡可能一直收到随机噪声命令。供电端要放一个至少10μF的钽电容或100μF的电解电容SD卡在写入时电流尖峰很大电容能防止瞬间跌落导致写数据出错。初始化SD卡有一个经典时序问题SPI时钟在卡上电后必须先从低速开始一般不超过400kHz发送至少74个时钟脉冲让卡完成内部上电然后依次发送CMD0、CMD8、ACMD41。很多卡在ACMD41阶段会先返回忙状态代码里必须循环重试不能一次失败就报错退出。初始化完成后再把SPI时钟切到高速模式常见的SDHC卡可以跑20MHz。5.2 FatFS移植配置项怎么设才不出幺蛾子SD卡的底层块读写搞定后接下来就是文件系统。嵌入式领域最常用的文件系统是FatFS它把文件操作抽象成f_open、f_read、f_write、f_mount等标准接口底层只需要提供disk_initialize、disk_read、disk_write、disk_status和disk_ioctl这几个函数。移植时容易出问题的不是底层函数本身而是ffconf.h里的配置项。我吃过亏的几个配置必须单独说。_USE_LFN建议设成2使用动态内存来分配长文件名缓冲避免占用大量栈空间。_USE_EXFAT要看实际情况如果SD卡是64GB甚至更大出厂格式多半是exFAT不开启支持就会挂载失败或显示没有文件。_MAX_SS默认512就够了但如果卡是4Kn高级格式化扇区则需要设为4096。_CODE_PAGE建议设成936中文环境下的文件读写才不容易乱码。底层disk_read函数读写单位是扇区FatFS一次读一个或多个扇区。使用SPI方式读取时要注意读取多扇区时要考虑SD卡是否支持多块读命令CMD18如果不支持就需要拆成单扇区循环。我见过不少人初始化正常、单扇区读写正常但文件操作一复杂就死机最后发现是disk_read返回的字节数不对SPI读取函数没用while循环把数据读完。5.3 文件读写、中文长文件名与乱码自救文件系统挂载成功后写日志文件其实很简单FIL fil; FRESULT fr f_mount(fs, , 1); fr f_open(fil, 0:/log.txt, FA_OPEN_ALWAYS | FA_WRITE); f_lseek(fil, f_size(fil)); /* 追加写入 */ f_printf(fil, time%d can_id0x%X\r\n, tick, canId); f_sync(fil); /* 把缓存刷到SD卡 */注意两个细节第一f_printf依赖_USE_STRFUNC配置项不开启的话这个函数不会编译第二写完数据后及时调用f_sync或f_close否则掉电时FatFS缓存在内存里的数据会丢失表现为文件存在但内容是空的。至于“SD卡显示没有文件”这类问题大部分情况不是读写失败而是文件系统类型不匹配。卡是exFAT格式但FatFS没开exFAT支持或者文件名带了中文_CODE_PAGE却设成了437。遇到这个问题先用f_mount返回的错误码定位FR_NO_FILESYSTEM是文件系统不识别FR_NOT_ENABLED是卷没挂载FR_INVALID_NAME是文件名编码有问题。还有一个很容易被忽略的点FatFS的卷号是从0开始但f_open里的路径如果写0:/log.txt这个0指的是物理驱动器号如果你的SD卡被映射为1:/自然打不开。5.4 实战CAN FD日志记录器CAN FD、LCD、SD卡各自跑通后我强烈建议做一个联动实验把CAN FD收到的报文实时显示在LCD上同时每秒批量写入SD卡。实现思路很简单CAN中断收到一帧把报文内容放进循环缓冲区主循环或者低优先级任务定期把缓冲区里的报文格式化、写进SD卡。这里最忌讳的做法是在CAN中断里直接调用f_write因为文件系统写入耗时不可控高优先级中断里做磁盘操作会破坏实时性。正确做法是用生产者-消费者模型中断是生产者写卡任务比如每1秒唤醒一次是消费者。日志格式建议用CSV方便后续在PC上用Excel或者Python分析。例如time_ms,can_id,dlc,data 1000,0x123,8,01 02 03 04 05 06 07 08实际测试中CAN FD数据段跑2Mbps时一秒钟可能收到上千帧报文SD卡SPI模式的写入速度会跟不上。解决办法是多个报文合成一次写入或者用更大容量缓冲、降低写入频率。如果SD卡写入速度和CAN接收速率实在无法匹配就要考虑换SDIO模式或者上eMMC那就是另一个层面的设计了。6. 踩坑实录与排查速查表6.1 开发阶段最常遇到的5类问题我把这段时间折腾TC397遇到的典型问题整理成了五类每一类都对应明确的排查方向。第一类是下载失败、连接不上。绝大多数发生在首次使用新板子或者芯片之前跑过带Flash保护的工程。排查顺序是板卡供电是否正常、调试器USB是否被电脑识别、芯片是否处于保护状态。使用ADS调试器时如果提示“Could not connect”,先手动给目标板断电重启再试一次。第二类是CAN FD收发不通。优先做回环测试把节点配置成loopback模式不依赖外部总线也不依赖对端节点能自发自收就说明节点配置基本没问题。然后再接外部分析仪测试外部回环这时重点检查收发器供电、终端电阻、引脚复用是否配到了正确的收发器通路。第三类是LCD白屏或者花屏。白屏先量背光电压看看屏幕有没有通电花屏则检查数据位连接和初始化序列尤其是SPI屏的RESET拉低时序和初始化命令发送是否正确。RGB屏花屏还要检查时钟极性和DE信号极性。第四类是SD卡挂载失败或者读写不稳定。先排除供电问题再确认SPI速率初始化时降到400kHz很多老卡/接触不良的卡对高时钟非常敏感。再检查disk_initialize返回值和ACMD41的重试次数如果卡在CMD0阶段就卡死大概率是MOSI上拉缺失或者电平不匹配。第五类是文件出现乱码或者内容丢失。乱码优先查_CODE_PAGE和文件名编码内容丢失优先查有没有f_sync以及写入过程中是否有非正常掉电。文件打不开时查看f_open返回值比盲猜更高效。6.2 问题排查速查表现象可能原因排查/解决措施程序无法下载芯片Flash保护、调试器未识别、供电不足执行解锁擦除、换USB口、单独供电CAN FD发送失败波特率不匹配、接收端不支持FD、无终端电阻回环测试、检查收发器供电、加120Ω电阻CAN FD数据段没提速BRS位未置位或数据段采样点错误检查code里的frameType和BRS控制位LCD白屏背光未打开、复位时序错误、供电异常量背光电压、检查RESET拉低时序LCD花屏SPI极性错、初始化命令错、接线松动查数据手册确认CPOL/CPHA、重新初始化SD卡挂载失败exFAT未开启、SPI速率过高、供电跌落开启_USE_EXFAT、降速初始化、加大电容写入数据丢失未f_sync、掉电时缓存未刷每次写完调用f_sync、异常断电前先关闭文件中文乱码字库编码与字符串编码不一致、code page错误统一UTF-8/GBK、修改_CODE_PAGE936文件系统与SD卡不匹配卡为exFAT而FatFS未支持格式化FAT32或开启_USE_EXFAT最后再分享一个小技巧这三个模块全调通之后我强烈建议你在工程里加一个运行时状态面板LCD上同时显示CAN FD发送帧计数、SD卡写入字节数、CPU负载率。这个看起来不起眼的功能能在你后续调试复杂逻辑时省下大量时间。尤其是CPU负载率TC397有内置的系统定时器配合性能计数器可以很方便地统计每个核的占用率。别问我为什么强调这个等到你开始把控制算法和通信协议栈放在同一个核上跑的时候就会感谢这个面板。另外开发阶段给SD卡养成的习惯是每次拔卡前先按一下板上的按键通过软件调用f_mount(NULL)卸载文件系统再断电拔卡。这个动作能避免不少“为什么文件最后几条丢了”的灵异问题。嵌入式开发的真相就是这样原理图、数据手册、库函数文档都摆在那里但真正让你记住的永远是那些踩过的坑。希望这篇教程能让你少踩几个。