【学习记录】GD32F303深度睡眠+闹钟唤醒

文章详细描述了如何配置RTC时钟源、启用RTC报警中断,以及在闹钟触发后进入深度睡眠模式的过程,包括EXTI线的初始化和中断处理。
摘要由CSDN通过智能技术生成
/*!
    \brief      configure the RTC
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rtc_configuration(void)
{
    /* enable BKPI clock */
    rcu_periph_clock_enable(RCU_BKPI);
	  rcu_periph_clock_enable(RCU_PMU);//使能PMU电源管理单元时钟
    /* allow access to backup domain */
    pmu_backup_write_enable();
    /* reset backup domain */
    bkp_deinit();

    /* enable IRC40K */
    rcu_osci_on(RCU_IRC40K);
    /* wait till IRC40K is ready */
    rcu_osci_stab_wait(RCU_IRC40K);
    /* select RCU_IRC40K as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_IRC40K);
    /* enable RTC clock */
    rcu_periph_clock_enable(RCU_RTC);

    /* wait for RTC registers synchronization */
    rtc_register_sync_wait();
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
    /* enable the RTC alarm interrupt */
    rtc_interrupt_enable(RTC_INT_ALARM);
		
   // rtc_interrupt_enable(RTC_INT_SECOND);
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
    /* set RTC prescaler: set RTC period to 1s */
    rtc_prescaler_set(3999);
		/*注意:这里必须分频,且分频出来的时钟必须小于APB1时钟的四分之一,
		        即rtc时钟不能大于15Mhz
		       这里设置分频3,即PSC=3, 频率SC_CLK = RTCCLK /(PSC[19:0]+1)=40000/(3+1)=10000Hz=10MHZ
					 如此秒中断为1/10000=0.0001s触发一次
					 如果要改时基,按照以上公式修改
		*/
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
    rtc_counter_set(0);
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
    rtc_alarm_config(4);//这里是经过多少个时基触发闹钟
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
    /* clear the RTC alarm flag */
    rtc_flag_clear(RTC_FLAG_ALARM);

    /* enable and set EXTI interrupt to the lowest priority */
		nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
		nvic_irq_enable(RTC_Alarm_IRQn, 0U, 0U);
    /* configure EXTI line */
    exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING);//这里测试过是上升沿触发才行
    //exti_interrupt_flag_clear(EXTI_17);
    exti_interrupt_enable(EXTI_17);

}

void Enter_Deepsleepmode(void){
	pmu_to_deepsleepmode(PMU_LDO_NORMAL, PMU_LOWDRIVER_DISABLE, WFI_CMD);
	//SystemInit();//重新初始化时钟 
}

然后是中断服务函数

void RTC_Alarm_IRQHandler(void)
{     
	if(rtc_flag_get(RTC_FLAG_ALARM))
	{
		SystemInit();//重新初始化时钟 直接调用system_clock_120m_hxtal也行
		//Set_led_off();
	  exti_flag_clear(EXTI_17);
		exti_interrupt_flag_clear(EXTI_17);
		rtc_flag_clear(RTC_FLAG_ALARM);
		
		rtc_register_sync_wait();
		rtc_lwoff_wait();
		rtc_alarm_config(4);//如果修改了闹钟时间,这里记得修改
		rtc_lwoff_wait();
		
		rtc_counter_set(0);
	  rtc_lwoff_wait();
   // fwdgt_counter_reload();如果加了看门狗,这一步写喂狗
	}	
}
好的,以下是配置GD32F303 ADC+DMA采样使用注入模式的代码: ```c #include "gd32f30x.h" #define ADC_GPIO_PORT GPIOA #define ADC_GPIO_PIN GPIO_PIN_0 #define ADC_CHANNEL ADC_CHANNEL_0 #define ADC_SAMPLE_TIME ADC_SAMPLETIME_55POINT5 #define ADC_INJ_SEQ ADC_INSERTED_CHANNEL_1 #define ADC_INJ_SEQ_LEN 1 #define DMA_CHANNEL DMA_CHANNEL_0 #define DMA_PRIORITY DMA_PRIORITY_HIGH #define DMA_MODE DMA_CIRCULAR #define DMA_INC DMA_INC_DISABLE #define DMA_SIZE DMA_SIZE_16BITS void adc_dma_init(void); void adc_gpio_init(void); int main(void) { /* 使能 DMA 和 ADC 时钟 */ rcu_periph_clock_enable(RCU_DMA0); rcu_adc_clock_enable(); /* 初始化 GPIO 和 ADC */ adc_gpio_init(); adc_dma_init(); /* 配置注入序列 */ adc_inserted_channel_config(ADC0, ADC_INJ_SEQ, ADC_CHANNEL, ADC_SAMPLE_TIME, ADC_INJ_SEQ_LEN); /* 配置 DMA 触发源为 ADC 注入完成事件 */ dma_channel_parameter_struct dma_channel; dma_deinit(DMA0, DMA_CHANNEL); dma_channel_init(DMA0, DMA_CHANNEL, &dma_channel); dma_circulation_disable(DMA0, DMA_CHANNEL); dma_periph_address_config(DMA0, DMA_CHANNEL, (uint32_t)&ADC_RDATA(ADC0)); dma_memory_address_config(DMA0, DMA_CHANNEL, (uint32_t)data_array); dma_transfer_direction_config(DMA0, DMA_CHANNEL, DMA_PERIPHERAL_TO_MEMORY); dma_transfer_number_config(DMA0, DMA_CHANNEL, 1); dma_periph_inc_mode_config(DMA0, DMA_CHANNEL, DMA_INC_DISABLE); dma_memory_inc_mode_config(DMA0, DMA_CHANNEL, DMA_INC_ENABLE); dma_periph_data_size_config(DMA0, DMA_CHANNEL, DMA_SIZE); dma_memory_data_size_config(DMA0, DMA_CHANNEL, DMA_SIZE); dma_priority_config(DMA0, DMA_CHANNEL, DMA_PRIORITY_HIGH); dma_circulation_enable(DMA0, DMA_CHANNEL); dma_channel_enable(DMA0, DMA_CHANNEL); /* 启动 ADC 和 DMA */ adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); adc_dma_mode_enable(ADC0); adc_enable(ADC0); while (1) { /* 循环等待 DMA 传输完成 */ while (dma_flag_get(DMA0, DMA_CHANNEL, DMA_FLAG_FTF) == RESET); /* 处理数据 */ // ... /* 清除 DMA 标志 */ dma_flag_clear(DMA0, DMA_CHANNEL, DMA_FLAG_FTF); } } void adc_dma_init(void) { /* 配置 DMA 时钟和中断 */ nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); dma_interrupt_enable(DMA0, DMA_CHANNEL, DMA_INT_FTF); } void adc_gpio_init(void) { /* 配置 GPIO 时钟 */ rcu_periph_clock_enable(RCU_GPIOA); /* 配置 GPIO 为模拟输入 */ gpio_mode_set(ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_GPIO_PIN); } ``` 以上代码实现了 ADC+DMA 采样,使用了注入模式。在代码中,我们使用了 DMA 进行数据传输,并启用了循环模式,使得 DMA 可以不断地将 ADC 采集到的数据传输到内存中。同时,我们还配置了注入序列,并将 DMA 触发源设置为 ADC 注入完成事件,以便 DMA 能够及时地捕获到 ADC 采集完成的事件。在主循环中,我们循环等待 DMA 传输完成,并在传输完成后对数据进行处理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值