PWC — 深度睡眠 + RTC 唤醒
固件库: AT32F403A_407_Firmware_Library V2.2.2
芯片: AT32
源文件: AT32/AT32F403A_407_Firmware_Library_V2.2.2/project/at_start_f403a/examples/pwc/deepsleep_rtc/src/main.c
功能简介
本示例演示睡眠(Sleep)低功耗模式。CPU 停止运行,但外设继续工作。任何中断都能唤醒 CPU,唤醒后立即恢复执行。
完整代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#include "at32f403a_407_board.h"
#include "at32f403a_407_clock.h"
void rtc_config(void)
{
exint_init_type exint_init_struct;
/* config the exint line of the rtc alarm */
exint_init_struct.line_select = EXINT_LINE_17;
exint_init_struct.line_enable = TRUE;
exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
exint_init(&exint_init_struct);
/* enable the battery-powered domain write operations */
pwc_battery_powered_domain_access(TRUE);
/* reset battery-powered domain register */
bpr_reset();
/* enable the lick */
crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
/* wait lick is ready */
while(crm_flag_get(CRM_LICK_STABLE_FLAG) == RESET);
/* select the rtc clock source */
crm_rtc_clock_select(CRM_RTC_CLOCK_LICK);
/* enable rtc clock */
crm_rtc_clock_enable(TRUE);
/* wait for rtc registers update */
rtc_wait_update_finish();
/* set rtc divider: set rtc period to 1sec */
rtc_divider_set(32767);
/* wait for the register write to complete */
rtc_wait_config_finish();
/* enable alarm interrupt */
rtc_interrupt_enable(RTC_TA_INT, TRUE);
/* wait for the register write to complete */
rtc_wait_config_finish();
/* configure and enable rtc alarm interrupt */
nvic_irq_enable(RTCAlarm_IRQn, 0, 0);
}
int main(void)
{
crm_clocks_freq_type crm_clocks_freq_struct = {0};
__IO uint32_t systick_index = 0;
/* congfig the system clock */
system_clock_config();
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* init at start board */
at32_board_init();
/* config priority group */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
/* turn on the led light */
at32_led_on(LED2);
at32_led_on(LED3);
at32_led_on(LED4);
/* enable pwc and bpr clock */
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
/* config rtc */
rtc_config();
while(1)
{
/* clear second flag */
rtc_flag_clear(RTC_TS_FLAG);
/* wait for the second flag to be set */
while(rtc_flag_get(RTC_TS_FLAG) == RESET);
/* set the wakeup time to 3 seconds */
rtc_alarm_set(rtc_counter_get() + 3);
/* wait for the register write to complete */
rtc_wait_config_finish();
at32_led_off(LED2);
/* save systick register configuration */
systick_index = SysTick->CTRL;
systick_index &= ~((uint32_t)0xFFFFFFFE);
/* disable systick */
SysTick->CTRL &= (uint32_t)0xFFFFFFFE;
/* congfig the voltage regulator mode */
pwc_voltage_regulate_set(PWC_REGULATOR_LOW_POWER);
/* enter deep sleep mode */
pwc_deep_sleep_mode_enter(PWC_DEEP_SLEEP_ENTER_WFI);
/* restore systick register configuration */
SysTick->CTRL |= systick_index;
/* wait 3 LICK(maximum 120us) cycles to ensure clock stable */
/* when wakeup from deepsleep,system clock source changes to HICK */
if((CRM->misc3_bit.hick_to_sclk == TRUE) && (CRM->misc1_bit.hickdiv == TRUE))
{
/* HICK is 48MHz */
delay_us(((120 * 6 * HICK_VALUE) /crm_clocks_freq_struct.sclk_freq) + 1);
}
else
{
/* HICK is 8MHz */
delay_us(((120 * HICK_VALUE) /crm_clocks_freq_struct.sclk_freq) + 1);
}
/* wake up from deep sleep mode, congfig the system clock */
system_clock_recover();
at32_led_on(LED2);
delay_ms(500);
}
}
|
代码讲解
系统时钟初始化:配置 MCU 的主频和时钟树。不同芯片的时钟配置不同,一般由工具生成。
板级初始化:初始化开发板上的 LED、按键等基础外设。
中断优先级配置:NVIC 设置中断的抢占优先级和子优先级。数字越小优先级越高。
延时:使用系统延时函数控制 LED 翻转间隔。