Hello everyone, today we will discuss a classic problem that causes countless engineers to lose their hair—microcontroller program malfunction. Just like a novice driver suddenly losing control of a car, when a program malfunctions, the microcontroller may suddenly freeze, restart, or execute strange actions. Last week, I encountered a funny case: the customer’s production line equipment would start dancing mechanically every afternoon at three o’clock, and it turned out that a relay was interfering with the power supply (details at the end)!
unsetunset1. Stack Overflow: The Most Insidious “Memory Killer”unsetunset
1.1 Everyday Understanding
Imagine your home storage warehouse (memory), where each function call is like throwing a cardboard box (local variable) into the warehouse. When the nested calls go too deep (for example, recursion without a termination condition), and the warehouse piles up to the ceiling… “Boom!” The entire warehouse collapses, and the program crashes.
1.2 Classic Case
void recursive_demo(){
int buffer[50]; // Each recursion consumes 200 bytes
recursive_demo(); // Infinite recursion
}
Phenomenon: Crashes after running for 2 minutes, repeats after restartTroubleshooting Tool: IDE’s built-in stack analysis tool (Check Stack Usage in Keil’s .map file)
1.3 Practical Tips
- Increase the stack size by 20% in the startup file (for example, change from 0x400 to 0x500)
- Avoid declaring large arrays in interrupt service functions
- Important: When using FreeRTOS, be sure to use
<span>uxTaskGetStackHighWaterMark()</span>
to check task stack
unsetunset2. Interrupt Conflicts: The Invisible “Road Rage”unsetunset
2.1 Real Crash Scene
Last year, while working on a temperature controller, the ADC sampling interrupt and PWM interrupt had the same priority. As a result, when the motor speed suddenly changed, the ADC data mixed into the PWM waveform! Later, I solved it usinginterrupt nesting:
NVIC_SetPriority(ADC_IRQn, 0); // Highest priority
NVIC_SetPriority(TIM1_IRQn, 1); // Second priority
2.2 Pitfall Guide
- Set critical interrupts (like watchdog) to the highest priority
- Disable global interrupts before clearing interrupt flags
- Hard Lesson: Do not perform complex calculations in I2C communication interrupts (which once caused I2C to lock up)
unsetunset3. Power Interference: The Most Easily Overlooked Culpritunsetunset
3.1 Classic Fault Phenomena
- Screen glitches when the motor starts
- Microcontroller restarts when the relay engages
- ADC sampling values show regular fluctuations
3.2 Hardware Improvement Solutions
Measured Data:
Filtering Solution | Ripple Peak-to-Peak Value |
---|---|
No Filtering | 300mV |
Add Capacitor | 50mV |
LC Filtering | 10mV |
3.3 On-Site Diagnostic Techniques
Use an oscilloscope probe to connect to the power pin, set the trigger to falling edge. When the device exhibits abnormal behavior, if a voltage drop is captured, immediately check:
- Whether the power line is too long (add a ferrite bead if over 15cm)
- Whether the digital ground and analog ground are connected at a single point
- Whether high-power devices share ground with the MCU
unsetunset4. Infinite Loops: A Pitfall for Beginnersunsetunset
4.1 Typical Error Code
while(UART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); // Waiting indefinitely for serial data
4.2 Optimization Solutions
Solution 1: Add a timeout check
uint32_t timeout = 100000;
while(timeout--){
if(UART_GetFlagStatus(...)) break;
}
if(timeout == 0) Error_Handler();
Solution 2: Use DMA + Interrupt
HAL_UART_Receive_DMA(&huart1, rx_buf, 256);
4.3 Debugging Black Technology
Use the Live Watch feature in STM32CubeIDE to monitor the loop variable values in real-time
unsetunset5. Watchdog: A Lifesaver Turned Killerunsetunset
5.1 Real Case
A fire-fighting device restarted in a fire scene due to:
void main(){
IWDG_Init(); // Initialize watchdog
while(1){
do_something(); // May take 2 seconds
// Forgot to feed the dog!
}
}
5.2 Correct Watchdog Feeding Method
- Feed the watchdog in the timer interrupt (with a period shorter than the watchdog timeout)
- Segment complex tasks, feeding the watchdog at the end of each segment
- Key: Disable the watchdog during debugging!
unsetunset6. Comprehensive Troubleshooting Flowchartunsetunset
Program Malfunction -> Check Reset Flags ->
If it is a watchdog reset: Check watchdog feeding logic
If it is a hard error: Connect debugger to locate crash address
If there is no abnormal reset: Check power/clock/stack
unsetunset7. Essential Tool List for the Laboratoryunsetunset
- Oscilloscope (must have single-shot trigger function)
- Logic Analyzer (to check timing conflicts)
- Thermal Imaging Camera (for quickly locating short circuit hotspots)
- Homemade debugging tool: Use LED + resistor to create a “program heartbeat light”
unsetunsetPractical Suggestionsunsetunset
- Intentionally write an infinite loop program and observe the PC pointer changes with the debugger
- Connect a 10Ω resistor in series on the power line and measure the voltage drop with an oscilloscope
- Modify the stack settings in the startup file and observe changes in program stability
- Use GPIO toggling method to measure interrupt response time
Finally, let me share that mechanical dance case: The factory’s packaging machine would twitch every afternoon, and it was eventually found that workers were simultaneously turning on multiple high-power fans, causing a sudden drop in grid voltage. The solution was to install a voltage regulator at the 380V incoming line and add a voltage anomaly holding mechanism in the PLC program. So friends, never underestimate the impact of environmental factors on microcontrollers!