EXTI15_10_IRQHandler无法唤醒处于standby状态的CH32L103C8T6,何解?

先说实验结论:直接采用官方评估版与评估代码,PA0可以顺利唤醒MCU,但是自己写的外部中断函数无法唤醒


实验内容:


先看参考手册

1721126238824988.png


再贴代码,直接拿CH32L103EVT.ZIP压缩包中的CH32L103EVT.ZIP\EVT\EXAM\PWR\Standby_Mode\修改

/*********************************************************************
 * @fn      EXTI15_10_IRQHandler
 *
 * @brief   This function handles EXTI10~15 Handler.
 *
 * @return  none
 */
void EXTI15_10_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void EXTI15_10_IRQHandler(void)
{
    //KEY2 pressed
    if(EXTI_GetITStatus(EXTI_Line14)!=RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line14);     /* Clear Flag */
        printf("PB14 wakeup!\r\n");
        return;
    }
}


/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    EXTI_InitTypeDef EXTI_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    /* To reduce power consumption, unused GPIOs need to be set as pull-down inputs */
    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOA|RCC_PB2Periph_GPIOB|
            RCC_PB2Periph_GPIOC|RCC_PB2Periph_GPIOD, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    //PB14 is used as wake up key
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    printf("Standby Mode Test\r\n");

    RCC_PB1PeriphClockCmd(RCC_PB1Periph_PWR, ENABLE);

    if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)
    {
        printf("\r\n Standby wake up reset \r\n");
    }
    else
    {
        printf("\r\n Power on reset \r\n");
        PWR_WakeUpPinCmd(ENABLE);
        PWR_EnterSTANDBYMode();
    }

    printf("\r\n ########## \r\n");
    while(1)
    {
        Delay_Ms(1000);
        printf("Run in main\r\n");
    }
}


结果就是没有进入standby状态,在执行while(1)这个循环时,把PB14拉高能触发中断,串口也能看到输出

PB14 wakeup!

但是断电重新上电后,显示:

SystemClk:96000000

ChipID:10310710

Standby Mode Test


 Power on reset 


这时就PB14再没法唤醒MCU了,这时将PA0拉高能唤醒。

这与手册描述的不一致,是不是还需要哪些地方设置?


我已经琢磨出来了,根据手册片段描述,猜测是不是要将自定义的外部中断改成事件?


1721142166646124.png


如下修改:

1721142359108066.png


果然,原来毫无反应的板子直接重启了,符合手册中standby唤醒执行电源复位动作的描述。


看来官方手册还得反反复复仔仔细细去读,去体会(猜)




只有登录才能回复,可以选择微信账号登录