单片机开发应用经验总结
本文最后更新于:2022年9月18日 凌晨
Debug调试
STM32CubeIDE Debug时现场表达式live expressions不准确问题
Debug时,有三种方法监测变量,如下,从左到右
- Variables 可以自动监测断点所在空间的变量,不可自定义添加:例如断点在函数内,只能看到该函数内部变量,断点不在函数内,则可以查看所有全局变量。另外若断点只要在类的.c文件中,就可以查看全部类成员变量(非成员变量和前面规则一样)
- expressions 只可以查看全局变量,需要自己手动添加。只能打断点监测,无法在运行时看不到数据变化
- live expressions 现场表达式:和expressions 类似,但可以在Debug运行时,实时监测
以下时在实际项目测试时遇到的问题,监测ADS1256的通道采集值,可以看到左侧现场表达式监测的0通道是没有数据的,1通道有数据567。但此时右侧的expressions监测可以看到0通道是有数据567。expressions和live expressions现场表达式监测错了一个通道数据,这里还使用串口打印通道值,输出和expressions监测一致
由此判断live expressions现场表达式在使用时会存在监测错误。以后遇到类似问题,建议使用expressions和串口打印验证,不要直接断定是硬件或程序错误。
STM32CubeIDE Debug时通信问题
在Dubug时,凡是遇到数据通信的语句,在其前后打断点,不要在该语句上打断点,可能导致数据通信错误
如下图所示,在132和134行打断点没问题。但在133行打断点后,发现id的数据就会出现问题。所以不要在改行打断点。类似的,其它涉及通信的也要注意这点
调试直接进 HardFault_Handler 错误
如果在调试刚运行或者运行一段时间进入以下错误中,有几类可能原因
- 结构体没有分配内存
- 数组寻址越界
- 指针没有分配空间,野指针
- 还是指针,检查所有指针,看赋值、寻址、初始化等等有没有问题
1 |
|
GPIO_Analog 引脚模式-STM32CubeMX-2019-05-17
修正日期:2021-03-15
最近开始学习使用STM最新的编译器STM32cubeIDE,直接从Keil转移过来的。之前也没用过CubeMX。
这里在配置引脚模式时,遇到了一个问题:GPIO_Analog 是什么模式?之前似乎从没遇见过。
上网搜了一通,找到ST官方社区的两个问答,才解决了疑惑。
- 1、Question about ADC versus GPIO Analog
- 2、What pins can I use for Analog Input/Output? STM32CubeMX allows every GPIO to be set to ‘’GPIO_Analog’’?
再结合参考手册描述:
总结起来就两个:
1、模拟配置会关闭引脚的一切内部相关联设施,此时普通 I/O 操作失效(不能读也不能输出)。因此引脚功耗为0。因此可以通过将引脚配置为该模式来降低芯片功耗。
2、模拟配置另外好处就是保证了这个引脚是 “干净” 的,如果和外部连接,那个该引脚就完全反映了外部引脚状态。因此将该引脚内联到A/D 片上外设,就可以精确测量引脚的模拟值了。实际上在我们将引脚复用为 A/D 功能时,就会默认配置为 Analog 模式。
结构体使用前必须分配内存-2019-5-18
最近再将原Keil5中的STM32工程移植到Atollic TrueSTDIO for STM32上,顺便使用STM32CubeMX简化初始化配置,减小工作量。更具体的原因则是涉及到版权和商业化问题,另外Keil所有版本的破解版都是2020年到期,我很慌啊。。。
但移植就以为这一堆问题,工程文件配置什么的都好解决,今天遇到的是程序上的问题。那就是:结构体使用前必须分配内存
原Keil函数里使用用到结构体的,但我在一个函数中申明了它却没有申请内存,关建是编译没有错误和警告,而且实机测试也是成功的。而今天原模原样照搬到TrueSTDIO上,编译也是没有错误和警告的,但实机测试情况是能跑,但不正常。最后一点点在线调试,才发现是结构体的问题,遂申请内存空间,问题解决。最后为了解答心中疑惑,我又测试了一下:
TrueSTDIO调试,出错输出信息:
硬故障HardFault
硬故障详细信息
总线,存储器管理或使用失败(FORCED)
总线故障详细信息
不精确的数据访问冲突(IMPRECISERR)
故障发生时,堆栈指针的值。请确认这个值指向一个有效的堆栈内存区域。
MSP = 主堆栈指针
PSP = 进程堆栈指针
编译测试
在线代码编译:(经常用来跑测试)
https://www.onlinegdb.com/
测试代码:
1 |
|
上面将内存分配注释掉,运行时直接报错编译不通过,输出结果:Segmentation fault (core dumped)
去掉注释后,就正常了,输出结果:b = 5
同时我也在C++环境下测试,同样的结果。
结论
至此得出结论:结构体在使用时是必须要分配内存的;Keil 5在编译时,可能对结构体会有优化,使得不分配内存也不会出错。
补充备忘
另外还涉及到另一个知识:字节对齐 _packed 问题,这里自己并不是很懂,能看明白啥意思,但究其原因还是不行。下面内容作为备忘,以后再来解答。
https://blog.csdn.net/lafengxiaoyu/article/details/53032963
http://bbs.pfan.cn/post-284115.html
https://blog.csdn.net/lanzhihui_10086/article/details/44353381# https://blog.csdn.net/u014717398/article/details/55511197
https://www.cnblogs.com/King-Gentleman/p/5940480.html
IO部分引脚不工作
测试环境
- STM32G031G8 芯片
- SWD下载接口
- Micro-USB 硬件接口(SWD接在数据引脚上)
描述
micro-usb 为手工焊接,导致接触不良,使得程序调试下载时,一会可以一会报错(无法下载)。但正常下载后,发现部分引脚无输出(测试程序令所有引脚输出高电平),部分有输出。检查了硬件设计没有问题,程序也没问题。重新焊接了 MCU,问题依旧未解决。遂根据下载不正常判断是不是 usb 焊接问题。重新焊接,下载程序不再故障,IO 输出也都正常。
结论
一开始下载不正常时就应该判断出 usb 没焊好,但心存侥幸、懒。没去在意和解决。
事出离奇必有妖。不能容得半点马虎。
至于为何接触不良会导致程序执行不正常,猜测是下载数据传输错误。具体原因无法深究查明。
程序下载、下载器连接问题
芯片低功耗模式 ST-Link 无法下载
测试环境
- STM32G031G8 芯片
- SWD下载接口
描述
一只在测试芯片的软件低功耗功能,启用了停止模式。开始下载调试一切正常,第二天再下载调试,就提示无法下载,提示如下错误信息:
1 |
|
之后再网上找到一种解决办法,重新擦除 MCU 的内部 flash,才能继续正常下载。
使用软件 ST-LINK utility
连接,并擦除,后可正常下载程序
实测H750这里直接连接无法连接,需要先将boot0 置高,再连接,擦除后。再将boot0恢复置低。
Keil 无法下载,但STM32CubeIDE可以下载
使用 Keil 下载程序时,出现以下错误。
同时查看 下载配置,会发现 ST-Link并未被识别到。但是我使用 STM32CubeIDE下载时却可以识别并调试下载。
查看资料
是ST-Link固件太新了,因为我之前一直使用 STM32CubeIDE,使得 ST-Link 固件一直保持在最新状态,但是我安装的 Keil 是 5.15 版本的,属于很老的版本了。所以 Keil 并未u识别。
解决办法:
进入 Keil 的安装目录,我的是
1 |
|
点击 ST-LinkUpgrade.exe
文件运行
重新插拔 ST-Link,点击 Device Connect,然后再点击 Yes,就完成了固件的下载。这里的固件是 Keil 安装自带的,也就是适配你安装的这个 Keil 软件的,所以一定是可以识别并使用的。
之后就可以正常下载了。
ST-LINK 突然无法连接设备下载
突然无法下载,于是尝试使用 ST-LINK utility
连接下载,依然无法连接失败。又尝试使用ST-LINK upgrade
连接,弹窗显示报错 “the content of STLink is corrupt” ,意思说是仿真器损坏,貌似遇到这个问题的人不多,用windows版程序升级固件的时候报这个错,解决办法是用 java 版的升级程序来升级固件。
在 官网 下载 STSW-LINK007
,解压文件中找到 STLinkUpgrade.jar
,双击运行即可(需提前安装JAVA)。之后再使用ST-LINK upgrade
更新一次固件
但我这里更新了固件之后依然是无法使用的,连接不上,于是使用 ST-LINK utility
连接下载器,从该软件内再更新一次固件,就好了。必须从这个软件中更新???
参考链接
ST-LINK utility 去除芯片读保护
问题:
芯片使用离线下载器,下载时设置了读保护。这次使用ST-Link连接无法下载代码,提示芯片程序存储空间无法擦除
以下是STM32CubeIDE控制台输出的信息。
解决方法:
- 使用ST-Link连接到STM32芯片,点击Connect
- 软件会弹出以下警告,提示无法读取内存,存在读保护
- 进入修改选项字节
- 将读保护等级修改为Level 0。取消所有扇区保护勾选。单击
Apply
重新写入选项字节。
- 等待写入完成。
- 写入完成
之后就可以正常的下载、调试程序了。
参考连接
- 使用ST-Link Utility去除STM32芯片读写保护
- 使用ST-Link Utility对STM32单片机读写保护设置与去除
ST-LINK utility擦除设备后无法连接
经过测试,如果你的芯片之前没有设置过
读保护
,是不会出现该问题,也不需要阅读后续内容。
在使用 ST-LINK utility 连接 之前设置了读保护的芯片,并使用该软件擦除了flash用于删除读保护配置,可删除之后就怎么也无法连接设备了,显示
“Can not connect to target!
Please select “Connect Under Reset” mode from Target->Settings menu and try again.
Can’t reset the core”
具体状态:
- 擦除 flash 后,ST-LINK utility 无法连接设备,也就无法下载程序
- 使用脱机下载器,正常连接、下载程序。
- 使用 IDE(STM32CubeIDea) 仿真调试,可以正常连接、下载程序。
- 使用上述两种方法下载程序之后再使用 ST-LINK utility 擦除 flash,ST-LINK utility 依旧无法连接设备
总之就是 ST-LINK utility 擦除 flash 之后,,ST-LINK utility 就无法连接设备。
解决方法:
- ST-LINK utility 菜单栏中点击
Target
->Settings...
。按照下图修改,并点击OK
保存。
实测修改配置后,无论芯片之前有没有设置读都保护,ST-LINK utility 都可以正常擦除 flash,并连接下载程序
参考链接
ST-LINK 能连接设备但无法下载、擦除芯片
出现问题原因:
芯片使能了读保护。在使用 ST-LINK utility
连接设备后,没有先取消保护,直接点击下载程序,提示错误(有读保护无法下载)后
在 ST Link->Target->Option Bytes 中将读保护去除,再重新连接设备,擦除芯片,显示擦除失败,也无法下载新程序
解决办法:
- 进入ST Link->Target->Option Bytes.
我们可以看到经过上面的操作,这里的读保护等级竟然变成了0(原本应该是1或2)
将保护等级改为1,并勾选PCROP_RDP
!勾选PCROP_RDP
!勾选PCROP_RDP
!。然后单击apply应用更改,成功后软件弹窗提示芯片有读保护。
- 重新连接芯片。将保护等级改为0,保持勾选
PCROP_RDP
!。然后单击apply应用更改,成功后软件自动退出Option Bytes。
此时我们再重新打开Option Bytes。保护等级仍为0,但PCROP_RDP
勾选已经自动消失了。
这时候我们就可以正常擦除芯片,下载程序了。
提醒:对于有读保护的芯片,一定要先去除读保护,才能下载程序。不可直接硬刚直接下载,否则就会导致这里的可以连接但无法擦除、下载的错误。
以上错误出现的根本原因是我们强行下载,导致PCROP保护启动。PCROP保护应该是下载器设置读保护时添加的,
PCROP是闪存中IP-code的读写保护。PCROP应用于扇区(0至7),保护专利代码不被最终用户代码、调试器工具或RAM Trojan代码修改或读取。
通过ITCM或AXI总线对PCROP扇区的任何读访问(获取操作除外)都会触发:
- 给定总线上出现总线错误
- FLASH_SR状态寄存器中RDERR标志置位。如果FLASH_CR寄存器中读错误中断使能位(Read Error Interrupt Enable,RDERRIE)置位,也会生成一个中断。
任何对PCROP扇区的编程/擦除操作都会触发WRPERR标志错误。受保护的IP-code可以很容易地被最终用户应用程序所调用,并且仍能受到保护,不可直接访问IP-code本身。PCROP不会阻止执行受保护的代码。
如何禁止PCROP
根据RDP级别,如果RDP级别为1或0,则PCROP保护可被禁用,但是如果RDP设置为级别2,PCROP不能被禁用。当RDP设为级别2,所有选项字节都会被冻结,不能修改。因此,PCROP保护的扇区不能再被擦除或修改,这样就成为永久性保护。
禁用受保护扇区上PCROP的唯一方式是:
- 清除对应扇区的PCROPi位(多个扇区可同时可进行)
- 实现从级别1退回到级别0•
- 将PCROP_RDP位置位
如果PCROP_RDP位被置位,则执行主闪存的批量擦除,并根据PCROPi值,对应扇区的PCROP保护保持使能或禁用。
如果PCROP_RDP位被清零,则完全批量擦除由部分批量擦除所代替,该部分页面擦除是对PCROP激活的存储区内进行连续页面擦除(PCROP保护的页面除外)。这样做是为了保持PCROP代码
参考资料
- STM32F72xxx和STM32F73xxx微控制器上的专有代码读取保护- AN4968
- Unable to program using ST-Link
Keil 使用问题
Keil 打开闪退
之前装过 Keil 软件,卸载了。现在 又重新安装。但是当安装完成后,点击图标打开软件,软件界面显示几秒钟后,就自动推出了。怎么也打不开软件。每次点击都是闪退。
后来尝试安装了很多版本,最新的,旧的。都试过,问题依旧。
然后我尝试点击了一下 一个 keil 工程文件(自动使用 keil 打开),然后 Keil 就打开了。。。难道keil打开需要先加载一个工程文件吗?
不同型号单片机SPI通信时序不同
采用STM32F103RCT6,设置为单向主模式,通信时序如下:
采用STM32F401CCU6,设置为单向主模式,通信时序如下:
橙色是时钟 SCK,蓝色是数据发送 MOSI。其中红框部分为一个主程序循环,每个循环发送两次数据。可以看到 103 的时序似乎有些问题,其中一个数据的发送看似是平的,而 401 的则正常。但两者都可以驱动设备正常工作(屏幕显示)。一开始怀疑是硬件问题或者底层配置问题,纠结一天没有解决。然后,当我把这两个图放在一起对比时,忽然明白:那个看似时平的数据时序其实也是在发送数据,不过他的数据全是1。查看程序,果然,103 驱动屏幕显示的颜色在白色和红色之间切换,而白色对应的数据为 0xFFFF,导致波形数据是平的。401的则是在蓝色和红色之间切换。
所以这并不是问题,只是再次提醒自己,遇到问题应冷静分析,使用数据说话,而不是在哪瞎猜或者瞎尝试。
IO映射偏移
https://ebf-stm32f429-tiaozhanzhe-std-tutorial.readthedocs.io/zh_CN/latest/book/GPIO_bit.html
https://msd.misuland.com/pd/4146263742822225282
从Flash读取bin图片显示
- 一开始调试时,始终显示错误,查看读取的数据 移植为0.发现再初始化时程序进行了flash的读写操作,导致bin文件变成了空文件。
SAME54-J-Link-SWD下载错误”
测试环境
J-Link:淘宝购买的J-Link V9.5(非官方)
设备:SAME54P20A MCU(自制)
软件IDE:Atmel Sudio 7
下载模式:SWD三线(CLK,DIO,GND)
错误类型
以下皆为在IDE中单击调试下载按钮 Debugging之后,出现的弹窗错误。
错误1:
1 |
|
错误2:
1 |
|
错误3:
1 |
|
解决方案
一开始我是各种搜索问题答案,但是资料是在太少,且基本是没有解决问题。自己整了2小时,才解决。
问题竟是出在杜邦线上,我是使用杜邦线连接J-Link和设备的,且下载速率设为了4MHz。这就导致两个问题:
- 杜邦线接触不良,会导致错误1或错误2
- 杜邦线下载速率太高,会导致错误2或错误3
解决方法:
- 更换杜邦线,选择接头紧的,不要出现松动
- 降低下载速率,1MHz以下
错误补充
- 一个程序两次下载,一次正常,一次死机,死机时:Debug发现系统执行直接报错。此时重新插拔J-Link,重新下载,问题解决,也是无语。。。
RT_Thread
STM32串口程序printf突然不能用
今天重新打开串口程序下载,发现printf不能使用了(printf使用重定义实现)。但自己并没有更改什么啊?
于是重新建立工程,并将原来的程序一模一样复制过来,下载执行却可以了。推测时工程文件除了问题,对比二者的文件内容,发现原来的工程文件 Core -> Src 下少了两个文件:syscalls.c 和 sysmem.c 。于是复制过去,重新编译下载,一切正常。
printf重定义使用的 _write 就是在该文件中。