SN_STOP.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "SN_STOP.h"
  2. /*
  3. 文件名:SN_STOP.c/.h
  4. 作者: SN_FAE_黄泽洪
  5. 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证
  6. 本人不担负商业使用上带来的风险。
  7. */
  8. /*
  9. 方法一:使用LPTIMER唤醒休眠
  10. //在SN_STOP.c的文件中添加用户的关闭函数和初始函数
  11. //退出休眠后,要重新开启的片上设备函数列表,将函数添加到此列表中
  12. static void OPEN(void){
  13. SN_SYSCLK_set(SYSCLK_48MHZ); //休眠退出后重新初始系统时钟
  14. std_delay_init();
  15. return;
  16. }
  17. //进入休眠前,要关闭的片上设备函数列表,将函数添加到此列表中
  18. static void CLOSE(void){
  19. //暂时没有
  20. return;
  21. }
  22. //在main.c文件里面
  23. uint8_t stop = 1;
  24. uint8_t k = 0 ;
  25. int main(void){
  26. SN_SYSCLK_set(SYSCLK_48MHZ);
  27. std_delay_init();
  28. std_delayms(3000);
  29. SN_GPIO_PIN_init(GPIOA ,GPIO_PIN_5 , GPIO_MODE_OUTPUT ,GPIO_PULLUP ,GPIO_OUTPUT_OPENDRAIN);
  30. SN_GPIO_PIN_toggle(GPIOA, GPIO_PIN_5);
  31. SN_LPtim_Rouse( 3000 ); //范围0x0000 - (0xffff-1) 使用lptimer唤醒
  32. while(1){
  33. if(stop){
  34. SN_STOP_EN(); //进入休眠
  35. SN_GPIO_PIN_toggle(GPIOA, GPIO_PIN_5); //退出休眠后翻转io
  36. SN_LPtim_ARR(3000+k*100); //修改下一次的休眠时间
  37. }
  38. k++;
  39. }
  40. }
  41. 方法二:使用触发唤醒
  42. //在SN_STOP.c的文件中添加用户的关闭函数和初始函数
  43. //退出休眠后,要重新开启的片上设备函数列表,将函数添加到此列表中
  44. static void OPEN(void){
  45. SN_SYSCLK_set(SYSCLK_48MHZ); //休眠退出后重新初始系统时钟
  46. std_delay_init();
  47. return;
  48. }
  49. //进入休眠前,要关闭的片上设备函数列表,将函数添加到此列表中
  50. static void CLOSE(void){
  51. //暂时没有
  52. return;
  53. }
  54. //在main.c文件里面
  55. uint8_t stop = 1;
  56. uint8_t k = 0 ;
  57. void LED(void){ //空的回调函数
  58. return;
  59. }
  60. int main(void){
  61. SN_SYSCLK_set(SYSCLK_48MHZ);
  62. std_delay_init();
  63. std_delayms(3000);
  64. SN_GPIO_PIN_init(GPIOA ,GPIO_PIN_5 , GPIO_MODE_OUTPUT ,GPIO_PULLUP ,GPIO_OUTPUT_OPENDRAIN);
  65. SN_GPIO_PIN_toggle(GPIOA, GPIO_PIN_5);
  66. SN_EXIT_set(GPIOA,GPIO_PIN_1,GPIO_PULLUP,LED,EXTI_TRIGGER_FALLING,NVIC_PRIO_3); //使能IO触发
  67. while(1){
  68. if(stop){
  69. SN_STOP_EN(); //进入休眠
  70. SN_GPIO_PIN_toggle(GPIOA, GPIO_PIN_5); //退出休眠后翻转io
  71. SN_LPtim_ARR(3000+k*100); //修改下一次的休眠时间
  72. }
  73. k++;
  74. }
  75. }
  76. */
  77. //休眠时间
  78. __IO uint16_t STOP_ARR = 0;
  79. //LPTIME标志
  80. __IO uint8_t LPTIME_FLG = 0;
  81. /*========================================================================================================== */
  82. /* 用户要将设备关闭和启动的接口放到下面的列表里面 |*/
  83. /*========================================================================================================== */
  84. //进入休眠前,要关闭的片上设备函数列表,将函数添加到此列表中
  85. static void CLOSE(void){
  86. return;
  87. }
  88. //退出休眠后,要重新开启的片上设备函数列表,将函数添加到此列表中
  89. static void OPEN(void){
  90. SN_SYSCLK_set(SYSCLK_48MHZ); //休眠退出后重新初始系统时钟
  91. std_delay_init();
  92. return;
  93. }
  94. /*==========================================================================================================*/
  95. /*
  96. 函数名称:SN_STOP_IN()
  97. 函数功能:进入休眠,M0内核进入休眠
  98. 参数:无
  99. 返回:无
  100. */
  101. void SN_STOP_EN(void){
  102. //进入休眠前关闭片上外设
  103. CLOSE();
  104. //进入休眠链接CMSIS接口,进入stop模式-------------------------------------------------------------------------in stop
  105. std_lptim_interrupt_enable(LPTIM_INTERRUPT_ARRM);
  106. std_lptim_enable(); //使能LPTIM
  107. if((STOP_ARR>0) && LPTIME_FLG){
  108. std_lptim_set_auto_reload(STOP_ARR);/* 启动LPTIM1计数 */
  109. std_lptim_start_counter(LPTIM_COUNT_SINGLE); //单次
  110. }
  111. std_pmu_enter_stop(PMU_MODE, PMU_ENTRY_LOWPOWER_MODE_WFE); //进入stop模式
  112. //----------------------------------------退出休眠继续执行下面的代码------------------------------------------out stop
  113. if(LPTIME_FLG){ std_lptim_disable(); } //关闭LPTIM
  114. //推出休眠重新开启的片上外设与系统时钟
  115. OPEN();
  116. }
  117. /*
  118. 函数名称:SN_LPtim_Rouse()
  119. 函数功能:使用系统时钟唤醒,初始化一次
  120. 参数:唤醒的计数值
  121. (周期和频率,在SN_STOP.h里面的宏定义修改,LPTIM定时器的工作参数)
  122. 返回:无
  123. 注意:RCL的时钟是32Khz
  124. 休眠时间计算公式: (32k/LPTIM_PRESCALER_DIV_x )*CNT = 休眠时间
  125. */
  126. void SN_LPtim_Rouse( uint16_t cnt ){
  127. STOP_ARR = cnt;
  128. SN_LPtim_SN_LPtim_EN();
  129. /* 使能RCL时钟并等待时钟稳定 */
  130. std_rcc_rcl_enable();
  131. while(std_rcc_get_rcl_ready() != RCC_CSR2_RCLRDY);
  132. /* 选择LPTIM1的时钟源为RCL */
  133. std_rcc_set_lptim1clk_source(RCC_LPTIM1_ASYNC_CLK_SRC_RCL);
  134. /* 使能LPTIM1时钟 */
  135. std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_LPTIM1);
  136. std_lptim_disable(); //关闭LPTIM
  137. /* 设置LPTIM1预分频器 */
  138. std_lptim_set_prescaler(LPTIM_PRESCALER_DIV_x);
  139. /* 禁止LPTIM1中断唤醒*/
  140. std_exti_interrupt_disable(EXTI_LINE_LPTIM1);
  141. /* 使能LPTIM1事件唤醒 */
  142. std_exti_event_enable(EXTI_LINE_LPTIM1);
  143. // NVIC_SetPriority(LPTIM1_IRQn, NVIC_PRIO_0);
  144. // NVIC_EnableIRQ(LPTIM1_IRQn);
  145. }
  146. /*
  147. 函数名称:SN_LPtim_ARR
  148. 函数功能:更新使用系统时钟唤醒时间
  149. 参数:唤醒的计数值
  150. 返回:无
  151. 注意:
  152. */
  153. void SN_LPtim_ARR(uint16_t cnt){
  154. STOP_ARR = cnt;
  155. }
  156. /*
  157. 函数名称:SN_LPtim_Stop
  158. 函数功能:停用LPtim唤醒
  159. 参数:无
  160. 返回:无
  161. 注意:
  162. */
  163. void SN_LPtim_SN_LPtim_Stop(void){
  164. LPTIME_FLG = 0; //不使用lptime唤醒
  165. std_lptim_disable(); //关闭lptime
  166. }
  167. /*
  168. 函数名称:SN_LPtim_EN
  169. 函数功能:重新使用LPtim唤醒
  170. 参数:无
  171. 返回:无
  172. 注意:
  173. */
  174. void SN_LPtim_SN_LPtim_EN(void){
  175. LPTIME_FLG = 1; //使用lptime唤醒
  176. }