yh1634803087 发表于 2023-6-11 17:16

AT32F421使用内部低速时钟如何每5分钟一次唤醒,可以有偿

目前我如图配置只能实现进入一次时钟中断,如何配置ertc_alarm_value_set(3)这个函数实现每5分钟进一次ERTC闹钟中断,有没有大神指点一下。
1、
static void ERTC_AlarmConfig(void)
{
EXTI_InitType EXTI_InitStructure;
//ERTC_AlarmType ERTC_AlarmStructure;
NVIC_InitType NVIC_InitStructure;

/* EXTI configuration */
EXTI_ClearIntPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineEnable = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Enable the ERTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ERTC_IRQn;//ERTCAlarm_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Set the alarm A Masks */
ERTC_AlarmStructure.ERTC_AlarmMask = ERTC_AlarmMask_DateWeek | ERTC_AlarmMask_Hours | ERTC_AlarmMask_Seconds;
ERTC_AlarmStructure.ERTC_AlarmDateWeekSel = ERTC_AlarmDateWeekSel_Date;
ERTC_AlarmStructure.ERTC_AlarmDateWeek = ERTC_Week_MON;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Hours = 0X0;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Minutes = 0X5;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Seconds = 0X0;
ERTC_SetAlarmValue(ERTC_Format_BCD, ERTC_AlA, &ERTC_AlarmStructure);

/* Enable alarm A interrupt */
ERTC_INTConfig(ERTC_INT_ALA, ENABLE);

/* Enable the alarmA */
ERTC_AlarmCmd(ERTC_AlA, ENABLE);
}

2、static void ERTC_Config(void)
{
/* Enable the PWR clock */
//RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR, ENABLE);
/* Allow access to ERTC */
PWR_BackupAccessCtrl(ENABLE);
/* Reset ERTC Domain */
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
/* Enable the LSE OSC */
//RCC_HSEConfig(RCC_HSE_ENABLE);//启用HSE
    RCC_LSICmd(ENABLE);             //启用LSI
/* Wait till LSE is ready */
while(RCC_GetFlagStatus(RCC_FLAG_LSISTBL) == RESET)
{
}
/* Select the ERTC Clock Source */
RCC_ERTCCLKConfig(RCC_ERTCCLKSelection_LSI);


/* Enable the ERTC Clock */
RCC_ERTCCLKCmd(ENABLE);
/* Deinitializes the ERTC registers */
ERTC_Reset();
/* Wait for ERTC APB registers synchronisation */
ERTC_WaitForSynchro();
/* Configure the ERTC data register and ERTC prescaler */
/* ck_spre(1Hz) = ERTCCLK(LSI) /(AsynchPrediv + 1)*(SynchPrediv + 1)*/
ERTC_InitStructure.ERTC_AsynchPrediv = 0x7F;
ERTC_InitStructure.ERTC_SynchPrediv= 0x13F;//0xFF;
ERTC_InitStructure.ERTC_HourFormat   = ERTC_HourFormat_24;
ERTC_Init(&ERTC_InitStructure);

/* Set the time to 00h 00mn 00s AM */
ERTC_TimeStruct.ERTC_AMPM   = ERTC_H12_AM;
ERTC_TimeStruct.ERTC_Hours   = 0;
ERTC_TimeStruct.ERTC_Minutes = 0;
ERTC_TimeStruct.ERTC_Seconds = 0;
ERTC_SetTimeValue(ERTC_Format_BCD, &ERTC_TimeStruct);
}



3、
int main(void)
{
    __IO uint32_t systick_index = 0;
      System_Init();                                                               //硬件初始化
    Init_Function();               //功能部件初始化
      init_sucess_flag = 1;
//    bsp_StartAutoTimer(3, 30000);          //50ms定时器
                            //初始化看门狗,时间3S左右
    //stop      
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR, ENABLE);

    ERTC_Config();
    ERTC_AlarmConfig();   
    EXTI9_Config();
    EXTI15_Config();
      //进入主程序循环体
//    _IWDG_Init();
      while (1)
      {
                //UpdateJudge();               //判断是否有更新程序
                bsp_Idle();                                                         //调用MODS_Poll()
                Modbus_Data_P();
                RCC_GetClocksFreq(&get_rcc_clock);
                PLC_Function();
                LED_RUN_Function();
//                Sys_Reboot_Count_Function();
      ConfigModuleNoBlock();
//      ertc_alarm_value_set(3);
      len = rbCanRead(&rb_t_usart1_read);//读取数据
      if(len > 0)
      {
            memset(usart1_read_buff_copy, 0, rb_t_usart1_read_buff_len);
            rbRead(&rb_t_usart1_read, usart1_read_buff_copy, len);//!!!!!!!!!!!!!!!!!!!!!!!!!!
            if(ConfigConnectDispose != NULL)
            {
               ConfigConnectDispose((char*)usart1_read_buff_copy, len);
            }

      }
//
      if(Stop_Flag == 0 && SYS_start == 0)
      {
//            systick_index = SysTick->CTRL;
//            systick_index &= ~((uint32_t)0xFFFFFFFE);
//            SysTick->CTRL &= (uint32_t)0xFFFFFFFE;
//            ertc_alarm_value_set(3);
//          ERTC_TimeStruct.ERTC_AMPM   = ERTC_H12_AM;
//          ERTC_TimeStruct.ERTC_Hours   = 0;
//          ERTC_TimeStruct.ERTC_Minutes = 0;
//          ERTC_TimeStruct.ERTC_Seconds = 0;
//          ERTC_SetTimeValue(ERTC_Format_BCD, &ERTC_TimeStruct);
            PWR_EnterSTOPMode(PWR_Regulator_LowPower_Extra, PWR_STOPEntry_WFI);
//            SysTick->CTRL |= 0x1;
//            SysTick->CTRL |= systick_index;
            SYSCLKConfig_STOP();
      }
    }
}

4、
void ertc_alarm_value_set(uint32_t alam_index)
{
//    ERTC_InitTypeERTC_InitStructure;
    ERTC_TimeTypeERTC1_TimeStruct;
//    ERTC_AlarmType ERTC_AlarmStructure;
//ERTC_TimeType ERTC_TimeStruct;

/* disable the alarm */
//ertc_alarm_enable(ERTC_ALA, FALSE);
ERTC_AlarmCmd(ERTC_AlA, DISABLE);

//ertc_calendar_get(&ertc_time_struct);
ERTC_GetTimeValue(ERTC_Format_BCD, &ERTC1_TimeStruct);
//ertc_alarm_set(ERTC_ALA, ertc_time_struct.day, ertc_time_struct.hour, ertc_time_struct.min, (ertc_time_struct.sec + alam_index)% 60, ertc_time_struct.ampm);
ERTC_AlarmStructure.ERTC_AlarmMask = ERTC_AlarmMask_DateWeek | ERTC_AlarmMask_Hours | ERTC_AlarmMask_Seconds;
ERTC_AlarmStructure.ERTC_AlarmDateWeekSel = ERTC_AlarmDateWeekSel_Date;
//ERTC_AlarmStructure.ERTC_AlarmDateWeek = ERTC_Week_MON;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Hours = ERTC1_TimeStruct.ERTC_Hours;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Minutes = (ERTC1_TimeStruct.ERTC_Minutes+alam_index) % 60;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_Seconds = ERTC1_TimeStruct.ERTC_Seconds;
ERTC_AlarmStructure.ERTC_AlarmTime.ERTC_AMPM    = ERTC1_TimeStruct.ERTC_AMPM;
ERTC_SetAlarmValue(ERTC_Format_BCD, ERTC_AlA, &ERTC_AlarmStructure);
ERTC_AlarmCmd(ERTC_AlA, ENABLE);
/* disable the alarm */
ERTC_AlarmCmd(ERTC_AlA, ENABLE);
}
void SYSCLKConfig_STOP(void)
{
RCC_HSEConfig(RCC_HSE_ENABLE);
HSEStartUpStatus = RCC_WaitForHSEStable();
if(HSEStartUpStatus == SUCCESS)
{
    RCC_PLLCmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_PLLSTBL) == RESET)
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSelction_PLL);
    while(RCC_GetSYSCLKSelction() != 0x08)
    {
    }
}
}

5、
oid ERTC_IRQHandler(void)
{
    if(ERTC_GetINTStatus(ERTC_INT_ALA) != RESET)
    {
      /* Clear ERTC AlarmA Flags */
      Stop_Flag = 1;
      Report_5min_flag = 1;
      ERTC_ClearINTPendingBINT(ERTC_INT_ALA);

    }
    /* Clear the EXTI line 17 */
    EXTI_ClearIntPendingBit(EXTI_Line17);
}

chenqianqian 发表于 2023-6-11 22:19

定时器计时中断唤醒。

yh1634803087 发表于 2023-6-12 08:50

chenqianqian 发表于 2023-6-11 22:19
定时器计时中断唤醒。

你好,请问有例程吗?我这个ertc_alarm_value_set()的函数是看最新的库里有个调整闹钟时间的函数仿写的。我这个库怎么才能进入低功耗前重新设置闹钟时间+5分钟?

muyichuan2012 发表于 2023-6-12 16:08

参考BSP中如下案例
AT32F421_Firmware_Library/ project / at_start_f421 / examples / pwc / standby_ertc_alarm
调用如下函数将对应Hour/data进行mask即可。
ertc_alarm_mask_set(ERTC_ALA, ERTC_ALARM_MASK_DATE_WEEK | ERTC_ALARM_MASK_HOUR | ERTC_ALARM_MASK_MIN);
对应RTC应用指南第2.58章节有描述原理
https://www.arterytek.com/download/APNOTE/AN0047_AT32_ERTC_Application_Note_ZH_V2.0.2.pdf

Henryko 发表于 2023-6-12 22:58

直接用定时器计数不就行了

yh1634803087 发表于 2023-6-16 08:46

谢谢各位关注,问题解决了,老版本的库STOP模式是有问题的,加上我图上那段后也能用,但还是建议使用STANDBY模式吧。

qcliu 发表于 2023-7-1 15:50

楼主的意思是 现有代码可以进入中断 但是只能进入一次 不能再次进入了是吗

drer 发表于 2023-7-1 16:05

楼主的代码里边使能的是哪个模块的中断啊

coshi 发表于 2023-7-1 16:45

yh1634803087 发表于 2023-6-16 08:46
谢谢各位关注,问题解决了,老版本的库STOP模式是有问题的,加上我图上那段后也能用,但还是建议使用STANDB ...

楼主有没有对比 新老版本 他们的差别在哪里啊

kxsi 发表于 2023-7-1 17:04

yh1634803087 发表于 2023-6-16 08:46
谢谢各位关注,问题解决了,老版本的库STOP模式是有问题的,加上我图上那段后也能用,但还是建议使用STANDB ...

也就是说在老版本下 这个定时器的中断是不支持的是吗

wiba 发表于 2023-7-1 17:23

也就是说得明确各种模式下那么模块是可以正常工作的吧

tpgf 发表于 2023-7-1 17:38

内部时钟在停止模式下是不是已经完全不能正常工作了啊

yh1634803087 发表于 2023-7-10 09:03

tpgf 发表于 2023-7-1 17:38
内部时钟在停止模式下是不是已经完全不能正常工作了啊

内部低速时钟可以工作的。

yh1634803087 发表于 2023-7-10 09:04

wiba 发表于 2023-7-1 17:23
也就是说得明确各种模式下那么模块是可以正常工作的吧

嗯,合理选择模式,我这个是因为库太老了,可能有点问题,好在解决了,都能实现的。

yh1634803087 发表于 2023-7-10 09:06

kxsi 发表于 2023-7-1 17:04
也就是说在老版本下 这个定时器的中断是不支持的是吗

支持的,只不过要在进入之前再清一下ERTC的初始值,具体啥原因不清楚,自己一直一直试出来的。

yh1634803087 发表于 2023-7-10 09:06

coshi 发表于 2023-7-1 16:45
楼主有没有对比 新老版本 他们的差别在哪里啊

我一开始发的就是没解决的版本,后面发的就是解决了修改的地方

yh1634803087 发表于 2023-7-10 09:08

qcliu 发表于 2023-7-1 15:50
楼主的意思是 现有代码可以进入中断 但是只能进入一次 不能再次进入了是吗 ...

嗯,之前是这个问题,后面加入我最新的修改,就好了,就达到了我的目的,每5分钟唤醒进入一次中断。

chenjun89 发表于 2023-7-11 08:12

中断后有没有重新对定时器进行赋值
页: [1]
查看完整版本: AT32F421使用内部低速时钟如何每5分钟一次唤醒,可以有偿