常见问题集

发布时间:2026/7/31 21:19:36
常见问题集 16.烧录不进去问题描述jlink 不插板子上的烧录口的时候电脑还能识别到 jlink, 插上就识别不到了拔掉过会儿就又能识别到了猜测原因是因为 clk 和 dio 电平被影响了jlink 和上位机就没法正常通信了豆包回答现象根源不是单纯 SWDIO/SWCLK 信号电平干扰调试链路真实机理目标板侧漏电 / 短路 / 负载异常把 J-Link 内部接口电路拉得异常 → 导致 J-Link USB 链路死机、电脑直接丢失 J-Link 设备断开负载内部电路恢复USB 重新枚举识别。ps:如果仅仅连不上芯片但电脑始终能看到 J-Link那就是单纯 SWD 通信问题就是一开始想的 CLK/DIO 电平、速率、接线问题。15.HardFault前提修改放电逻辑使用中断函数回调的方式启动的时候把脉冲的回调函数改成现在的正常放电函数放电时改成新的控制放电次数和时间。问题描述开机后进Timer5Init函数执行到NVIC_Init函数的时候进入HardFault死循环。问题分析我看了你的修改内容和你的描述就猜到大概会是什么问题了。①可能是进中断了中断服务函数没有②或者回调是空尝试执行③还可能栈溢出分析验证这里使能后进入脉冲定时器了然后里面这个中断服务函数里面用到的回调函数是Null解决办法使能前先把中断挂起清了防护进阶①回调赋初值写个空函数。但空函数要执行一次调用而且麻烦②回调里执行前先判断回调函数是不是空有日志的话如果是空可以在判断里加个错误日志或者警告日志。判断的时候直接if(!pFun)也行或者如图和空函数比较。14.CAN通讯异常问题描述用周立功的USB-CAN适配器CAN卡连接控制板发现CAN调试工具CAN上位机上既没有接收信息也发送信息失败。分析过程万用表测了一下发现CAN_H 2VCAN_L 3V差分电压 2V - 3V -1V极性完全反了正常情况下 CAN_H 应该比 CAN_L 高显性时 HL隐性时接近相等这里 L 反而比 H 高 1V这是典型的总线接反 / 芯片损坏 / 终端电阻异常的表现。解决处理对调两根线的位置再测电平CAN_H 2.5VCAN_L 2.5Vps自己只需要写8位数据位CAN控制器会自动封装解析帧头、帧尾、CRC、位填充、ACK 等只要帧头、帧尾、CRC、位填充、ACK任何一项不对CAN 控制器会直接丢弃这一帧 → 不交给用户 → 不计入正常接收 → 同时报错误计数。** 你在代码 / 上位机里能收到的 CAN 数据100% 是正确无误的。错误帧、坏帧、残缺帧CAN 硬件会帮你全部过滤掉。**13.CAN通讯异常万用表测了一下发现CAN_H≈1.5VCAN_L≈1.5V电压不正常。TJA1050和1042的电路设计不一样焊的1042通信不了换成1050就正常了⑤引脚不一样1050的⑤引脚是悬空的1042的⑤引脚需要提供一个参考电压值接一个3.3V电。12.ntc开路电阻阻值检测异常修复问题描述未连接ntc时设备本应异常却偶尔会变正常分析过程按理说做了滤波不应该出现这个问题。下拉电阻且ntc开路的时候电压为0采集到的ADC值也为0此时返回的ntc电阻值也为0本应该是无穷大的ntc阻值0再通过查表法可得温度被定义为最高温度最高温度设置为150。此时一切正常但弱下拉下拉不稳定有可能共模干扰或者地之间本来就有电平差采集到的adc值变为1此时返回的ntc阻值10000 *4095-1/1 40940000. 此时通过查表法可得温度被定义为最低温度最低温度设置为-273线圈未连接的判断是温度为最高温则判定异常此时-273就会被判定为正常导致设备在异常情况下弱下拉干扰作用下偶尔显示正常。上拉就不会有这种问题。/** * brief adc值转换为ntc电阻值__原代码 */staticuint32_tget_ntc_r_val(uint16_tadc_val){adc_valadc_val4095?4095:adc_val;uint32_trsNTC_SERIES_R;returnrs*(4095-adc_val)/adc_val;}/* -20~100摄氏度对应的电阻阻值 ntc10k 3950 */uint32_tntc10k_neg20to100[]{105385,99109,93252,87783,82674,77898,73432,69253,65341,61678,//-20~-11摄氏度58246,55028,52011,49179,46522,44026,41681,39477,37405,35455,33621,31893,30266,28733,27288,25925,24639,23425,22279,21197,20175,19208,18294,17430,16612,15837,15104,14409,13751,13127,12535,11974,11441,10936,10456,10000,9567,9155,8764,8391,8037,7700,7379,7074,6783,6506,6241,5989,5749,5520,5301,5093,4894,4703,4522,4348,4182,4024,3872,3727,3588,3455,3328,3207,3090,2978,2871,2769,2671,2577,2486,2399,2316,2237,2160,2086,2016,1948,1883,1820,1760,1702,1646,1593,1541,1492,1444,1398,1354,1311,1270,1231,1193,1156,1121,1087,1054,1022,992,962,934,906,880,854,829,805,782,760,738,718,698,};解决办法程序改为如下增加adc_val adc_val0 ? 1 : adc_val;使开路时计算的ntc阻值总为无穷大。/** * brief adc值转换为ntc电阻值__修改后代码 */staticuint32_tget_ntc_r_val(uint16_tadc_val){adc_valadc_val4095?4095:adc_val;adc_valadc_val0?1:adc_val;// adduint32_trsNTC_SERIES_R;returnrs*(4095-adc_val)/adc_val;}总结分析需考虑特殊值情况、最大值、最小值。不过这段代码原本也是给上拉电阻的测温写的所以只写了最大值的判断。后来移植的时候没考虑到这部分。ps突然发现我的上拉是这么写的return rs*adc_val/(4095-adc_val1);直接1有点绝对但有考虑到分母是0的情况11.部分代码无法打断点如图所示红框里的代码不能打断点众所周知一共有两种原因1.编译器优化该段代码没有用到被优化了该代码没有对应的机器码。2.代码未被编译这是刚写好的代码未编译生成对应的机器码。最开始以为是没编译狂按F7但不行还是不能打断点。苦苦思索一中午后发现if条件有问题我太习惯等号的顺向思维了不等号的逆向思维一时没搞清晰把 || 换成 问题得已解决10.PB4引脚输出异常因默认功能非普通GPIO口PB4连接的阀不能正常工作换了块儿芯片依旧是这样问了AI发现是STM32F1系列的经典坑PB4‌ 是JTAG调试链路的一部分系统上电后默认启用JTAG调试模式此时即使正确配置了GPIO模式和时钟该引脚仍处于调试功能优先状态无法作为普通GPIO使用。9.负压风机负压风机降温正压不降温8.上电水泵不工作因为没检测到线圈的温度传感器我觉得得上整机测试了但怎么会有人这么聪明啊思路打开格局打开7.CAN卡在初始化问题描述can通信收发异常。can调试器的CANL接CANL但CANH不小心接了12Vcan芯片会被烧坏吗会在这里卡很久但发现这两句话其实在CAN_Init函数里有写出来完全多余。但为什么没卡在CAN_Init里面啊这个很难解释先说结论是CAN芯片TJA1042 高速can收发器坏了换了一个CAN芯片后一切正常当时就是测了一下CANH、CANL的电压正常应该都是2.5V但测到1.2V所以断定的芯片坏了。接下来说说问题排查思路首先得接12V电源因为之前只接3.3V电源的时候程序能跑起来但没有CAN的收发而CAN是5V供电所以只有3.3V是不行的。接上12V之后就卡在can的初始化了一开始会觉得可能是因为裸板没接收发器接上收发器果然正常了但下一次重新上电又不正常了这可真奇怪跟收发器其实没有关系就是个随机bug有时候卡几秒有时候又会卡几分钟。后来意识到AI说的外部CAN收发器不是CAN调试器是指TJA1042芯片因为是TJA1042连接的TX、RX引脚。因为TJA1042芯片坏了所以信号不稳定导致初始化时卡时不卡偶尔收到信号会退出初始化收不到就一直卡在初始化不接TJA1042芯片的话就一直卡在初始化。应该是这个意思。终端一般加一个120V的电阻就是CANH CANL之间加一个120R的电阻可以增强抗干扰保证通信稳定性但是这个终端电阻和能否通讯上没有关系CAN收发异常时不需要考虑是否为缺失终端电阻导致的。6.逻辑分析仪参数主要参数带宽、采样率采样率单位时间内的采样次数带宽能测量并保存显示的最大频率采样步进是采用速度采完要处理转化成波形能测量并保存显示的最大频率就是带宽采样率决定带宽的上限。采样步进是硬件层面的采样间隔频率步进/扫频步进是软件层面的波形显示间隔。起因一个50us的输出测出来实际输出是40us有时候测出来是60us40us和60us是一半一半的概率偏偏就不是50us分析不论是单次脉冲还连续脉冲都是这样单次脉冲用的系统滴答阻塞式延迟50us连续脉冲是定时器设置50us完全不同的两种50us设置方式却有一样的显示结果怀疑是硬件问题所以换了一块控制板但仍有该问题最后怀疑是逻辑分析仪有问题因为拿示波器测试就是正常的。结论逻辑分析仪带宽50kHz步进20us所以无法显示50us二更逻辑分析仪的参数只有采样深度和采样率带宽是示波器的参数因为逻辑分析仪是数字信号所以没有带宽。带宽‌是示波器的核心参数定义为输入正弦波信号幅度衰减至原值的70.7%-3dB时的频率‌采样深度‌存储深度表示逻辑分析仪能够保存的采样点数量。5.函数指针如何让函数在不同场景下表现不同的行为1.函数指针通过定义函数指针变量在运行时指向不同的函数实现从而动态改变调用行为2.参数控制分支逻辑通过参数决定函数执行路径4.串口DMA循环缓冲区我的疑问1.中断里一定要加rt_interrupt_enter和rt_interrupt_leave吗 2.为什么MTCircleBufferWriteMulti之前要失能DMA答案1.一定要加‌RTOS中断上下文保护‌在RT-Thread等实时操作系统中rt_interrupt_enter用于标记中断上下文防止调度器误判当前处于中断状态而错误调度任务rt_interrupt_leave则恢复中断状态确保后续任务调度正常。‌临界区保护‌若中断服务程序ISR中调用了RTOS的API如信号量释放rt_sem_release必须通过这两函数确保操作原子性避免竞态条件。‌例外情况‌若ISR仅操作硬件寄存器且不调用RTOS API可省略但需确保代码永不扩展至需要RTOS功能。2.①在读取DMA接收数据前需先DMA_Cmd(DISABLE)暂停DMA传输防止DMA控制器在读取过程中修改接收缓冲区内容避免数据竞争。②通过DMA_GetCurrDataCounter获取已接收数据长度时DMA必须处于静止状态否则计数器值可能不准确。但这个时候我又有疑问了它一进串口的空闲中断就把DMA失能了紧接着就把数据放进循环缓冲区了怎么就能确定这时候DMA已经转运完了呢万一这帧数据还没转运完呢失能DMA不就是为了防止数据正在转运导致计数器值不准的嘛。且在地址递增模式的时候重新失能使能也可以使得(DMA_SxNDTR寄存器的值恢复置我们最开始设定的。查完资料后发现DMA转运速度很快只需要几个时钟周期而串口传输速率很慢拿115200bps举例单个字节传输时间约87us1s传输115200个bit一个字节有8个bit的数据位还要加上1bit的开始位和1bit的停止位没有校验位的话那就是10bit1s传输11520个字节那么一个字节就是1/11520s ≈ 87us而空闲中断是1.5个字节没有接收到新数据就触发的此时DMA通常已经当前帧数据的转运。防止的应该是下个帧数据正在转运导致的计数器不准。而DMA转运又是怎么触发的呢是硬件检测触发一般是串口的RXNERXNE不需要软件进行USART_ITConfig的配置。RXNE标志在UART接收到数据时自动置位触发DMA搬运后由硬件清除3.git指纹验证电脑重装系统后用vscode上传代码会跳git指纹验证的弹窗点击选项后弹出来另一个弹窗不管点击是还是否都会反复弹百度一下发现是因为重装系统后电脑里存储的公钥丢失需要重新生成并将 SSH 公钥添加到 Gitee 账户中所以其实参考文章里面的步骤并不需要完全按顺序操作完执行到第二步就可以了。参考文章https://blog.csdn.net/cnzzs/article/details/1445734232.keil调试无外设keil调试的时候想看一下GPIO的输出值但我的peripherals里面的system viewer里面什么也没有应该是因为重装电脑之后重新下载keil导致之前的配置数据丢失需要重新配置。办法Peripherals无外设寄存器修改Debug选项中的Dialog DLL中的内容为DARMSTM.DLL修改Parameter中的内容为-pSTM32F103VC。这里因为我建工程时选的MCU是STM32F103VC所以改成这个。这个参数要和建工程时选的MCU一致。发现还是不行查资料说是新版keil的问题keil更新迭代导致的。还需要在魔法棒的target里添加.SFR文件框选use custom file添加.sfr文件。新版是没有自带SFR文件的需要自己生成最新发现安装pack的步骤 打开keil—打开pack installer—file—import pack—选择pack离线包貌似可以自动生成sfr文件。就是用keil手动安装离线pack包不是双击安装是要到keil里面导入。tips参考文章里的原方法中需要右键点击终端中打开去生成sfr文件但有的电脑并没有终端中打开这个选项按shift键再点右键其中打开powershell窗口也是和终端一样的功能。同时拓展一下在没有keil的debug调试没有外设寄存器的时候如何调试可以直接搜寄存器名放到监控里看手册找寄存器名因为标准库都封装好了直接看对应的结构体里面的值就行了。例如查看GPIOB的引脚输出在监控里放GPIOB-ODR即可。参考文章https://blog.csdn.net/weixin_71155468/article/details/1495751101.数组越界导致bug发送命令使motor0转动用500ms 的定时器让motor运行500ms后自动停止。motor0开始之后直接卡死首先想到的就是定时器没初始化成功遂加上创建成功的输出显示定时器是创建成功了的那还能是什么原因呢进debug调试发现是进了断言错误问题还是在定时器这里这个时候有点一筹莫展问了ai看到错误根源分析几乎瞬间我就有答案了数组越界造成的排除掉1和3剩下的2就是真相。在watch里发现motor的值果然是不正常的在.map里找了一下上个值果然是个数组至此问题定位完毕问题出在adc_buf上adc_buf数组越界导致motor0的定时器地址异常变为不可访问的地址执行到motor0的定时器时就会出现断言错误。俩宏定义位置互换问题解决​