关于STM32G474芯片有规律的自动重启的问题

各位,我正在做一个板子,将以前的软件移植过来,并修改相关的电机驱动,以期赶上今年6月的光伏展。这个新板子还是用我一直使用的STM32G474芯片。相关的电路,除了电机驱动的部分外,其他的都没变,还是沿用以前的经过长时间检验的电路。

板子外发打板回来之后,我就来进行软件的移植,移植得差不多的时候,我就接上电机试试看转不转。因为是新板子,没有进行完全的测试和确认,所以,为了防止烧板子,我就将桌面电源的输出设置成1A了,那么这样,即使板子上有短路,或者某些器件选得不对,耐压,耐电流不够的话,最大也就跑1A的电流,不会把板子严重的烧坏。

然后,我就接上电机试试看。接上电机后,我就按了启动按钮,电机缓慢的转起来了。转了几秒钟之后,开始加速的转,可是加速一会儿后,又自动的减速了,减速一会儿后,又自动的加速了,现象就是"呜--嗡--呜--嗡"这样的转,像一个摆轮一样,一会儿快,一会儿慢。我操,这可使我吃了一惊,我设计的电路和软件,可没有给电机这个一会儿快,一会儿慢的指令呀。很奇怪,不得其解。搞得我头上都要冒汗了。

赶紧关了电源,将所有的接线再仔细的检查了一遍,觉得没有问题,再重新打开电源上电,让电机反转,发现还是这样一会儿快,一会儿慢,搞得我一头雾水。仔细想了想硬件设计和软件设计,觉得应该没有问题,为什么会这样呢?

忽然脑袋里面灵光一闪,莫不是设置的电源电压是1A,电机转起来,加速之后,电流超过1A,就将电源的电压拉低,导致加到电机上的电压也低,就使得电机转起来,一会儿快,一会儿慢。于是,将电源的电流设成4A,因为刚刚用1A电流已经跑过了,除了电机的转动一会儿快,一会儿慢之外,板子并没有什么异常,也没有过热,也没有发烟。设大电流应该没有问题。将电流设大到4A后,重新上电,电机按照预定的设计转动起来了,先是缓慢启动,几秒钟之后加速到一个相对的高速就稳定在这个速度。看来,问题就是电源的电流设成1A限流了,才导致的这个问题。搞定。

想着让电机好好转一会儿,看看会怎么样。结果,转了几分钟之后,电机忽然不转了,停了,电机转的指示灯也不亮了。这又是什么问题呢?我这代码是移植过来的,移植前的代码是经过长时间检验,没有问题的。唯一改的地方就是电机的驱动,但是电机的正传,反转和停,我刚刚都试了一下,都没有问题,为什么转了几分钟就停了呢?我可没有发指令让它停呀,百思不得其解。赶紧看看log,有没有发BRK指令,将有BRK指令的地方,都用printf打印输出,并将当时的tick也打印出来,做记录。调试器也在BRK指令的地方打断点,开着调试器,重新运行程序。重新启动程序后,电机还是能转,几分钟之后,还是停了,也没有进入我打的断点,也没有打印BRK的命令的信息,这就怪了,没有经过BRK命令怎么就停了呢?重新启动程序,等电机转了之后,自己按BRK按钮,发现程序果然运行到BRK指令的断点处,单步运行也确实能够打印BRK命令的信息。连续运行之后,发现几分钟之后,还是会停。

这时,会想,莫不是系统重启了吧?赶紧找log,看系统重启的记录,搜索"system", 果然发现了系统重启的记录。如下:

看来果然是系统重启了,那么是什么原因呢?是喂狗不及时导致看门狗超时重启了吗?检查了所有的喂狗程序,发现基本上每3ms就喂一次狗,不应该是看门狗的问题。但是,还是不知道,就把看门狗取消掉吧,整个系统不用看门狗,看看会怎么样。

取消看门狗之后,还是会重启。而且,仔细看重启的时间,发现差不多10分钟会重启一次。如下:

这个就奇怪了,很规律的间隔10分钟就重启一次。什么原因呢?

是电路板设计得有问题,导致有干扰或者怎么样,自动10分钟重启?还是哪里有什么指令让系统重启?看来得找出系统重启的原因了。

于是,在网上找了一下,加上问AI,得出下列指令可以看出系统重启的原因。如下:

复制代码
uint32_t reset_flag = 0;

reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_BORRST); usb_printf("BORRST: 0x%08lX\r\n", reset_flag);
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST); usb_printf("SFTRST: 0x%08lX\r\n", reset_flag);
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST); usb_printf("IWDGRST: 0x%08lX\r\n", reset_flag);
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST); usb_printf("WWDGRST: 0x%08lX\r\n", reset_flag);
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST); usb_printf("LPWRRST: 0x%08lX\r\n", reset_flag);
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_PINRST); usb_printf("PINRST: 0x%08lX\r\n", reset_flag);

// Clear reset flags
  __HAL_RCC_CLEAR_RESET_FLAGS();
  reset_flag = __HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) | __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) | __HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) | __HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) | __HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST) | __HAL_RCC_GET_FLAG(RCC_FLAG_PINRST);
  usb_printf("Reset flags: 0x%08lX\r\n", reset_flag);

就是声明一个reset标志,读RCC寄存器的跟reset相关的每个标志位,并将结果打印出来,那么就能看出是什么原因导致reset了。读完RCC寄存器的reset相关的标志位后,用指令将reset标志都清掉,看看清掉的结果,确保都清掉了。这样,下次发生重启时,就能反应真实的重启的原因。运行的结果为:

可以看到,系统重启了,在软件重启和外部NRST重启的2个标志位上有结果。那么说明,要么是软件重启了,要么是外部NRST按键/管脚重启了。但是,我没有按NRST按键,这个NRST按键电路也是久经考验的电路,自己产生误操作或者信号干扰导致NRST重启的可能性很小,最大的可能性是软件重启。将我写的软件重启的函数注释掉,那么应该就不会触发软件重启了。注释掉之后再运行,发现还是会重启。再检索整个项目,发现在同事写的网络通信的代码里有重启的指令,

看来是同事写的这个代码导致了系统重启。

于是,跟同事沟通了一下,同事也同意跟他这段代码有关,看来这就是原因了。

这样,一块悬而未决的石头落地了。搞定。

大功告成,亲个嘴儿。

相关推荐
时空自由民.2 小时前
BLDC无刷直流电机作为发电机的波形图
单片机
yong99902 小时前
基于 STM32 的 4×4 矩阵键盘源码
stm32·矩阵·计算机外设
JSMSEMI112 小时前
JSM63006 5A 28V三相无刷电机驱动电路
单片机·嵌入式硬件
国产芯片设计2 小时前
【LCD驱动实战】单颗YL1621脚位不足?双芯片联动驱动方案详解
stm32·单片机·mcu·51单片机·硬件工程
不怕犯错,就怕不做2 小时前
RK3562的CPU如何降频及关闭硬件编解码
linux·驱动开发·嵌入式硬件
Hical_W3 小时前
Hical 踩坑实录五部曲(二):MSVC / GCC / Clang 三平台 C++20 编译差异
linux·windows·经验分享·嵌入式硬件·macos·开源·c++20
bubiyoushang8884 小时前
基于 Freescale S12 单片机的 Bootloader 开发
单片机·嵌入式硬件·mongodb
笨笨小乌龟115 小时前
单片机的半主机模式与 MicroLib 机制(Keil UseMicroLIB)
stm32·单片机·嵌入式硬件
非鱼䲆鱻䲜5 小时前
数模电数控电源(0—9.9v)
嵌入式硬件·multisim·数模电·嘉立创