🛠 Sommeil profond Stop et réveil par RTC
Objectives
Divide consumption by a thousand: put the GD32F103 into Stop mode (core and APB clocks stopped, SRAM retained) and wake it up periodically using the RTC. The datasheet gives an order of magnitude: approximately 5.6 to 5.8 µA in standby with the RTC active, and a wake-up in a few microseconds from sleep. You will learn the Sleep/Stop/Standby hierarchy, the role of VBAT and IRC40K (or LXTAL 32.768 kHz), and the pitfall of returning to IRC8M after wake-up.
Hardware
- GD32F103C8T6 / CBT6 Blue Pill compatible board; to measure µA, remove the LED and regulator from the board (or use a bare core board) and a microammeter in series with the 3.3 V supply
- RTC continuously powered: internal IRC40K source (no crystal required) or LXTAL 32.768 kHz if populated; VBAT 1.8-3.6 V possible with a coin cell battery
- LED PC13 (active-LOW) to visualize wake-ups; USART0 console for messages
- SPL V2.2.x + OpenOCD compatible with GD32
Complete Code
/* stop_rtc.c — GD32F103C8, SPL V2.2.x : Stop + reveil RTC chaque seconde. */
#include "gd32f10x.h"
static bool led_on = false;
void RTC_IRQHandler(void)
{
if (rtc_flag_get(RTC_FLAG_SECOND) == SET) {
rtc_flag_clear(RTC_FLAG_SECOND);
led_on = !led_on; /* la LED ne clignote qu'aux reveils */
gpio_bit_write(GPIOC, GPIO_PIN_13, led_on ? RESET : SET);
}
}
static void rtc_source_irc40k(void)
{
/* 1) source RTC = IRC40K interne (pas de quartz externe requis) */
rcu_osci_on(RCU_IRC40K);
rcu_osci_stab_wait(RCU_IRC40K);
rcu_rtc_clock_config(RCU_RTCSRC_IRC40K);
/* 2) horloge de la RTC et de la interface backup */
rcu_periph_clock_enable(RCU_PMU);
rcu_periph_clock_enable(RCU_BKPI);
pmu_backup_write_enable;
/* 3) RTC : prescaler 32768 -> 1 Hz, interruption « seconde » */
rtc_init;
rtc_interrupt_enable(RTC_INT_SECOND);
rtc_enable;
while (rtc_flag_get(RTC_FLAG_INITS) != SET) { } /* sync. registres */
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
nvic_irq_enable(RTC_IRQn, 1, 0);
}
int main(void)
{
rcu_periph_clock_enable(RCU_GPIOC);
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
rtc_source_irc40k;
while (1) {
/* Entree en Stop : WFI, le reveil se fait par l'IRQ RTC.
En Stop, le systeme repart sur IRC8M (8 MHz) au reveil :
reconfigurer le PLL 108 MHz si le code en a besoin. */
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD, STOP_MODE_ENTRY);
/* ... ici, on revient a chaque seconde ... */
}
}
Expected Verification
The LED PC13 pulses once per second (each RTC wake-up), and the microammeter drops significantly during Stop phases compared to run mode (on the scale of hundreds of µA versus 34-45 mA in run mode at 108 MHz according to the datasheet; the standby floor is approximately 5.6-5.8 µA with RTC active). In SWD debug mode, the connection may drop during Stop: this is normal, regain control just after a wake-up.
Common Errors
- No wake-up: RTC interrupt enabled but NVIC RTC_IRQn forgotten, or the SECOND flag not cleared in the handler (the wake-up then occurs only once).
- The program does not restart at the correct speed: after Stop, the system clock returns to IRC8M; any code calibrated for 108 MHz (delays, UART) drifts until the PLL is restarted.
- RTC stops counting after power-off: without retention (VBAT or continuous power), the RTC resets to zero; the internal IRC40K is less accurate than an LXTAL 32.768 kHz.
- Confusing Stop and Standby: in Standby, SRAM is lost (complete reset upon wake-up, minimal consumption ~5.6 µA); in Stop, SRAM is retained but consumption is higher.
- Board regulator and LED: on a complete Blue Pill, the regulator and LED consume more than the MCU in Stop; your µA measurements will be dominated by the board, not the chip.
- Unwanted wake-up: a floating pin on a wake-up line can wake the core; set unused inputs to a defined pull state.
Other tutorials for this board
Code examples for this board
clignotante.inoArduinobouton-led.inoArduinorespiration.inoArduinopotentiometre.inoArduinopont-uart.inoArduinooled-i2c.inoArduino