1.1. GPIO
GPIO例程对GPIO模块的output、interrupt、以及RTC域PC13的interrupt进行测试,代码解读如下:
1.1.1. GPIO_OUTPUT:
- 输出GPIO_OUTPUT信息。
- 设置PA0/PA1/PA2/PA3四个引脚的推挽输出、上拉、复用功能0。
- 将四个引脚设置为高电平、延时1ms,然后设置为低电平,再延时1ms,如此循环往复。
编译下载调试运行后,观察到串口输出如下(由于串口TX接到PA2,因此PA2输出的波形被误识别为字符 “␀” ):
用示波器观察这几个引脚,可发现输出频率为493Hz的波形(采用的时钟是内部RCH,误差较大,而且设置引脚函数运行指令,也需要耗费一定的时间,因此偏离预期的1/2ms=500Hz):
1.1.2. GPIO_INT:
- 此段代码应当有误,与后面一段的GPIO_PC的代码相同,重复测试此功能明显不对(ModulesDemo_V2.0.2, GPIO/demo/Source_Code/APP/APP.c)。
- 注意到GPIOAB_IRQHandler函数中是清除PB9的中断标志位,因此推测此段代码应当为测试PB9的输入中断功能,修改代码如下:
- 设置PB9引脚为下降沿输入中断,电阻上拉、复用功能0。
- 清除GPIOAB_IRQn对应的NVIC中断标志位,并使能该中断。
- 在GPIOAB_IRQHandler中断服务例程中,设置中断状态变量 gu32_GPIOIRQ_Flag = true 。
- 在main函数主循环中,不停地检查该中断状态变量 gu32_GPIOIRQ_Flag ,一旦值为true,则重新设置其为false(防止再次进入该if判断语句,重复打印输出中断信息),随后打印输出中断信息;
- gu32_GPIOIRQ_Flag 为false之后,只有在PB9上的上升沿再次触发中断,才会进入中断服务例程将其再次设置为true,然后main函数检测到该值为true后才会再次执行前述操作。
caseGPIO_INT:
{
printfS("This is GPIO interrupt TEST. Please press user button to generate interrupt! \r\n");
GPIOB_Handle.Pin=GPIO_PIN_9;
GPIOB_Handle.Mode=GPIO_MODE_IT_FALLING;
GPIOB_Handle.Pull=GPIO_PULLUP;
GPIOB_Handle.Alternate=GPIO_FUNCTION_0;
HAL_GPIO_Init(GPIOB,&GPIOB_Handle);
NVIC_ClearPendingIRQ(GPIOAB_IRQn);
NVIC_EnableIRQ(GPIOAB_IRQn);
while(1)
{
if(gu32_GPIOIRQ_Flag)
{
gu32_GPIOIRQ_Flag=false;
printfS("Get interrupt flag!!! \r\n");
}
}
}break;
编译下载调试运行后,观察到串口输出如下(通过短接PB9和GND之后,可以触发中断,并在串口观察到相应的输出):
1.1.3. GPIO_PC13:
此段代码与前段代码功能接近,都是测试GPIO引脚的输入中断功能,区别点在于PC13/PC14/PC15位于RTC电源域,其设置与其他GPIO引脚稍有差异。具体如下:
- 设置PC13引脚为下降沿,复用功能0。
- 使能RTC域的读写。
- 设置PC13的GPIO功能,上拉,数字模式。
- 清除NVIC的GPIOCD_IRQn中断标志位,并使能该中断。
- 在main函数主循环中,不停地检查该中断状态变量 gu32_GPIOIRQ_Flag ,一旦值为true,则重新设置其为false(防止再次进入该if判断语句,重复打印输出中断信息),随后打印输出中断信息;
caseGPIO_PC13:
{
printfS("This is GPIO PC13 interrupt TEST \r\n");
GPIOC_Handle.Pin=GPIO_PIN_13;
GPIOC_Handle.Mode=GPIO_MODE_IT_FALLING;
GPIOC_Handle.Alternate=GPIO_FUNCTION_0;
HAL_GPIO_Init(GPIOC,&GPIOC_Handle);
System_Enable_Disable_RTC_Domain_Access(FUNC_ENABLE);
__HAL_RTC_PC13_SEL(0);
__HAL_RTC_PC13_PULL_UP_ENABLE();
__HAL_RTC_PC13_DIGIT();
NVIC_ClearPendingIRQ(GPIOCD_IRQn);
NVIC_EnableIRQ(GPIOCD_IRQn);
while(1)
{
if(gu32_GPIOIRQ_Flag)
{
gu32_GPIOIRQ_Flag=false;
printfS("Get PC13 interrupt flag!!! \r\n");
}
}
}break;
1.1.4. LED_BLINK:
- 设置PF3引脚为推挽输出、电阻上拉、复用功能0。
- 设置PF3为高电平,延时500ms,然后设置PF3为低电平,再延时500ms,如此循环往复。
执行后串口输出如图:
电路板上运行效果如下:
1.2. EXTI:
1.2.1. EXTI_PB9
- 设置PB9引脚作为输入、电阻上拉、复用功能0。
- 设置EXTI为9号线,中断模式,下降沿,GPIOB。
- 最后在循环中进入stop模式;
void APP_EXTI_Test(void)
{
printfS("This is EXTI Test \r\n");
System_Delay_MS(3000);
System_Module_Enable(EN_EXTI);
GPIO_PB9_Handle.Pin = GPIO_PIN_9;
GPIO_PB9_Handle.Mode = GPIO_MODE_INPUT;
GPIO_PB9_Handle.Pull = GPIO_PULLUP;
GPIO_PB9_Handle.Alternate = GPIO_FUNCTION_0;
HAL_GPIO_Init(GPIOB, &GPIO_PB9_Handle);
EXTI_Line9_Handle.u32_Line = EXTI_LINE_9;
EXTI_Line9_Handle.u32_Mode = EXTI_MODE_INTERRUPT;
EXTI_Line9_Handle.u32_Trigger = EXTI_TRIGGER_FALLING;
EXTI_Line9_Handle.u32_GPIOSel = EXTI_GPIOB;
HAL_EXTI_SetConfigLine(&EXTI_Line9_Handle);
while (1)
{
printfS("MCU Enter Lowpower, Press User Button To Wakeup MCU!\n");
HAL_EXTI_ClearAllPending();
System_Enter_Stop_Mode(STOPENTRY_WFI);
printfS("MCU is Runing \r\n");
System_Delay_MS(1000);
printfS("MCU is Runing \r\n");
System_Delay_MS(1000);
printfS("MCU is Runing \r\n");
System_Delay_MS(1000);
}
}
执行效果如图(需要使用杜邦线触碰短接GND和PB9):
.. image:: image/EXTI_Test.png
1.2.2. EXTI_PC13:
由于板载的User-Button连接在PC13上,因此可以修改代码为使能EXTI的PC13引脚中断。注意PC13引脚由RTC电源域管理,需要额外设置,参考GPIO_PC13例程代码。
voidAPP_EXTI_Test(void)
{
printfS("This is EXTI Test \r\n");
System_Delay_MS(3000);
System_Module_Enable(EN_EXTI);
GPIO_PB9_Handle.Pin=GPIO_PIN_13;
GPIO_PB9_Handle.Mode=GPIO_MODE_INPUT;
GPIO_PB9_Handle.Pull=GPIO_PULLUP;
GPIO_PB9_Handle.Alternate=GPIO_FUNCTION_0;
HAL_GPIO_Init(GPIOC,&GPIO_PB9_Handle);
System_Enable_Disable_RTC_Domain_Access(FUNC_ENABLE);
__HAL_RTC_PC13_SEL(0);
__HAL_RTC_PC13_PULL_UP_ENABLE();
__HAL_RTC_PC13_DIGIT();
EXTI_Line9_Handle.u32_Line=EXTI_LINE_13;
EXTI_Line9_Handle.u32_Mode=EXTI_MODE_INTERRUPT;
EXTI_Line9_Handle.u32_Trigger=EXTI_TRIGGER_FALLING;
EXTI_Line9_Handle.u32_GPIOSel=EXTI_GPIOC;
HAL_EXTI_SetConfigLine(&EXTI_Line9_Handle);
此时按键即可触发EXTI中断
1.2.3. EXTI_EVENT:
同样可以尝试WFI和WFE的差别,将 System_Enter_Stop_Mode(STOPENTRY_WFI); 改为
System_Enter_Stop_Mode(STOPENTRY_WFE);
观察效果类似。