GD32 RTC 调试之NVIC设置

 一:设置NVIC组,使能 RTC irq,设置RTC优先级(抢占优先级和响应优先级)

void nvic_configuration(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
    nvic_irq_enable(RTC_IRQn,1,0);
}

 

nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);

设置中断向量控制器组

这里设置为GROUP2    => NVIC_PRIGROUP_PRE2_SUB2

GROUP2意味着最高2位用于抢占式优先级,最低2位用于响应优先级,也就是说可以设置2^2 = 4个抢占式优先级,每个抢占式优先级中可以有2^2=4个响应优先级。其实通过不同的排列组合可以构成2^4 = 16个优先级

这些级别意味着什么呢?

抢占式优先级顾名思义是说定义了这些级别,是可以抢占其他优先级,当然是级别高的抢占级别低的了。

如果2个中断的抢占优先级相同呢?那响应优先级就用上了,2个中断抢占优先级相同,则响应优先级高的先响应了。

那要是两个中断设置了相同的抢占优先级和相同的响应优先级呢?同时中断的情况下,谁先响应呢?

答案:会先响应中断通道号低的中断处理函数(比如RTC的中断通道号是19,DMA0 Channel0的是27)

先响应RTC的

;               /* external interrupts handler */
                DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
                DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
                DCD     TAMPER_IRQHandler                 ; 18:Tamper through EXTI Line detect
                DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
                DCD     FMC_IRQHandler                    ; 20:FMC
                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
                DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
                DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
                DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
                DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
                DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
                DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel0
                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
                DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
                DCD     CAN0_TX_IRQHandler                ; 35:CAN0 TX
                DCD     CAN0_RX0_IRQHandler               ; 36:CAN0 RX0
                DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
                DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
                DCD     EXTI5_9_IRQHandler                ; 39:EXTI5 to EXTI9
                DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8
                DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9
                DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
                DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
                DCD     TIMER1_IRQHandler                 ; 44:TIMER1
                DCD     TIMER2_IRQHandler                 ; 45:TIMER2
                DCD     TIMER3_IRQHandler                 ; 46:TIMER3
                DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
                DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
                DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
                DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
                DCD     SPI0_IRQHandler                   ; 51:SPI0
                DCD     SPI1_IRQHandler                   ; 52:SPI1
                DCD     USART0_IRQHandler                 ; 53:USART0
                DCD     USART1_IRQHandler                 ; 54:USART1
                DCD     USART2_IRQHandler                 ; 55:USART2
                DCD     EXTI10_15_IRQHandler              ; 56:EXTI10 to EXTI15
                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
                DCD     USBFS_WKUP_IRQHandler             ; 58:USBFS Wakeup
                DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break and TIMER11
                DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update and TIMER12
                DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
                DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare
                DCD     0                                 ; 63:Reserved
                DCD     EXMC_IRQHandler                   ; 64:EXMC
                DCD     0                                 ; 65:Reserved
                DCD     TIMER4_IRQHandler                 ; 66:TIMER4
                DCD     SPI2_IRQHandler                   ; 67:SPI2
                DCD     UART3_IRQHandler                  ; 68:UART3
                DCD     UART4_IRQHandler                  ; 69:UART4
                DCD     TIMER5_IRQHandler                 ; 70:TIMER5 
                DCD     TIMER6_IRQHandler                 ; 71:TIMER6
                DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
                DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
                DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
                DCD     DMA1_Channel3_IRQHandler          ; 75:DMA1 Channel3
                DCD     DMA1_Channel4_IRQHandler          ; 76:DMA1 Channel4
                DCD     0                                 ; 77:Reserved
                DCD     0                                 ; 78:Reserved
                DCD     CAN1_TX_IRQHandler                ; 79:CAN1 TX
                DCD     CAN1_RX0_IRQHandler               ; 80:CAN1 RX0
                DCD     CAN1_RX1_IRQHandler               ; 81:CAN1 RX1
                DCD     CAN1_EWMC_IRQHandler              ; 82:CAN1 EWMC
                DCD     USBFS_IRQHandler                  ; 83:USBFS
nvic_irq_enable(RTC_IRQn,1,0);

这个就是设置中断号,和对应的抢占和响应优先级了。

 

贴下剩余的RTC设置

void rtc_configuration(void)
{
    /* enable PMU and BKPI clocks */
    rcu_periph_clock_enable(RCU_BKPI);
    rcu_periph_clock_enable(RCU_PMU);
    /* allow access to BKP domain */
    pmu_backup_write_enable();

    /* reset backup domain */
    bkp_deinit();

    /* enable LXTAL */
    rcu_osci_on(RCU_LXTAL);
    /* wait till LXTAL is ready */
    rcu_osci_stab_wait(RCU_LXTAL);
    
    /* select RCU_LXTAL as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    /* 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 second and alarm interrupt*/
    rtc_interrupt_enable(RTC_INT_SECOND);
    rtc_interrupt_enable(RTC_INT_ALARM);
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();

    /* set RTC prescaler: set RTC period to 1s */
    rtc_prescaler_set(32767);

    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
}
rcu_periph_clock_enable(RCU_BKPI);

注释上说了,这是打开BKPI时钟。

这里说下BKPI

BKP位于备份域中的备份寄存器可以在Vdd电源关闭时候由Vbat供电,备份寄存器有42个16位(84字节)寄存器可用来存储并保护用户应用数据,从待机模式唤醒或系统复位也不会对这些寄存器造成影响

 从上面就可以看出“PMU”对BKP的影响,所以代码中要做这样的设置

    rcu_periph_clock_enable(RCU_PMU);
    /* allow access to BKP domain */
    pmu_backup_write_enable();

 

在操作BKP 之前要先做下复位动作,这个很容易想到,你要操作某组寄存器先要把它恢复到一个初始的状态

    /* reset backup domain */
    bkp_deinit();

接下来看RTC所用时钟的配置

    /* enable LXTAL */
    rcu_osci_on(RCU_LXTAL);
    /* wait till LXTAL is ready */
    rcu_osci_stab_wait(RCU_LXTAL);
    
    /* select RCU_LXTAL as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

 

这里我们要实现RTC功能。。。。哦,不,不能这样说,不应该说要实现RTC功能。

是要实现系统能够准确的显示时间,或者说让我们的系统能知道当前的时间功能,我们需要借助RTC(real time clock)来做秒计数,要借助BKP来保存这个时间,

 

    /* select RCU_LXTAL as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

 

void rcu_rtc_clock_config(uint32_t rtc_clock_source)
{
    uint32_t reg;
    
    reg = RCU_BDCTL; 
    /* reset the RTCSRC bits and set according to rtc_clock_source */
    reg &= ~RCU_BDCTL_RTCSRC;
    RCU_BDCTL = (reg | rtc_clock_source);
}

 

/* RTC clock entry selection */
#define BDCTL_RTCSRC(regval)            (BITS(8,9) & ((uint32_t)(regval) << 8))
#define RCU_RTCSRC_NONE                 BDCTL_RTCSRC(0)                     /*!< no clock selected */
#define RCU_RTCSRC_LXTAL                BDCTL_RTCSRC(1)                     /*!< RTC source clock select LXTAL  */
#define RCU_RTCSRC_IRC40K               BDCTL_RTCSRC(2)                     /*!< RTC source clock select IRC40K */
#define RCU_RTCSRC_HXTAL_DIV_128        BDCTL_RTCSRC(3)                     /*!< RTC source clock select HXTAL/128 */

 上面的LXTAL,IRC40K,HXTAL_DIV 分别是1,2,3从clock  tree上就可以看出来

提供给CK_RTC 的有三路选择,11 就是HXTAL的128分频

01就是直接32.768K,10就是 IRC40K 

 

/* RTC clock entry selection */
#define BDCTL_RTCSRC(regval)            (BITS(8,9) & ((uint32_t)(regval) << 8))

    /* wait for RTC registers synchronization */
    rtc_register_sync_wait();

 

    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();

等待RTC寄存器写操作完成

 

    /* enable the RTC second and alarm interrupt*/
    rtc_interrupt_enable(RTC_INT_SECOND);
    rtc_interrupt_enable(RTC_INT_ALARM);

使能秒中断和闹钟中断

    /* set RTC prescaler: set RTC period to 1s */
    rtc_prescaler_set(32767);

设置RTC预分频的值32767

初始化的工作做完了。

 

之后就可以在RTC寄存器中设置时间值了。

 

/*!
    \brief      set RTC counter value
    \param[in]  cnt: RTC counter value
    \param[out] none
    \retval     none
*/
void rtc_counter_set(uint32_t cnt)
{
    rtc_configuration_mode_enter();
    /* set the RTC counter high bits */
    RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
    /* set the RTC counter low bits */
    RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
    rtc_configuration_mode_exit();
}

RTC_CNTH 和 RTC_CNTL就对应前面的SPEC 

 

 

 

 

  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GD32芯片的RTC模块是一个实时时钟计时器,用于提供精确的日期和时间信息。下面是GD32RTC配置步骤: 1. 开启RTC时钟:使能PWR和BKP模块时钟,然后设置RTC时钟源为LSE或者LSI。 ```c RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); RCC_LSEConfig(RCC_LSE_ON); // 开启LSE while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); // 等待LSE稳定 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 选择RTC时钟源 ``` 2. 初始化RTC设置RTC的分频系数、时间格式、并清除RTC计数器。 ```c RTC_InitTypeDef RTC_InitStructure; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; // 24小时格式 RTC_InitStructure.RTC_AsynchPrediv = 0x7F; // 异步分频系数为0x7F RTC_InitStructure.RTC_SynchPrediv = 0xFF; // 同步分频系数为0xFF RTC_InitStructure.RTC_OutPut = RTC_Output_Disable; // 输出禁止 RTC_Init(&RTC_InitStructure); RTC_WriteProtectionCmd(DISABLE); // 取消写保护 RTC_SetCounter(0); // 清除RTC计数器 RTC_WriteProtectionCmd(ENABLE); // 使能写保护 ``` 3. 启用RTC中断:使能RTC中断,然后在中断服务函数中处理RTC事件。 ```c NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; // RTC中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RTC_ITConfig(RTC_IT_SEC, ENABLE); // 使能RTC秒中断 RTC_ClearITPendingBit(RTC_IT_SEC); // 清除RTC秒中断标志位 ``` 以上是GD32 RTC的基本配置步骤,具体配置还需要根据实际需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值