slytherinsun 发表于 2025-8-29 17:38

【APM32F402R Micro-EVB开发板测评】8、FreeRTOS外部中断触发任务通过PWM调整亮度

本帖最后由 slytherinsun 于 2025-8-29 23:55 编辑

1.简介
本次测评在前两篇的FreeRTOS的基础上,通过开发板的Key1按键触发外部中断,在中断中给Led_Thread任务发送事件。Led_Thread任务等待事件,并在事件发生后改变LED2的状态,同时通过调整定时器4的比较值来改变PWM的占空比。定时器4的PWM的输出连接到LED3,根据正弦序列从0 - 100%生成了11个占空比,通过按键触发不同的占空比来实现调整亮度的目的,同时可用于PWM风扇的调速控制。
2.定时器4通道2输出PWM
通过查阅原理图可知APM32F402R开发板的LED3连接的是PB7引脚,在数据手册中此引脚的其中一个默认复用功能是TMR4_CH2,

通用定时器4支持PWM输出,由此可以实现基于PWM占空比的亮度或速度调节。其周期由自动重装载寄存器(TMR4_AUTORLD)的值决定,
信号脉宽由比较寄存器(TMR4_CC2)的值决定。其向上、向下计数和中央对齐模式及PWM模式1/2对亮度调整影响不大,本次测试使用PWM模式1向上计数。
根据数据手册的时钟树及频率配置可知,TMR4时钟为APB1 x 2 = 120MHz。PWM的配置基于官方例程PWM输出代码进行修改。

当前配置PWM为10KHz,按照正弦序列将亮度从0 - 100%分了10份共11个比较寄存器值。具体代码如下:
void TMR_Config(void)
{
    TMR_BaseConfig_T tmrBaseConfig;
    TMR_OCConfig_T tmrOCConfig;

    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4);

    /* TMR4 clock source frequency = 120MHz */
    tmrBaseConfig.countMode = TMR_COUNTER_MODE_UP;
    tmrBaseConfig.clockDivision = TMR_CLOCK_DIV_1;
    tmrBaseConfig.period = 999;//tmr update rate = 10M / (999 + 1) = 10K
    tmrBaseConfig.division = 19; //tmr4 clk 10M
    tmrBaseConfig.repetitionCounter = 0;
    TMR_ConfigTimeBase(TMR4, &tmrBaseConfig);

    /* 50% PWM */
    tmrOCConfig.mode = TMR_OC_MODE_PWM1;
    tmrOCConfig.outputState = TMR_OC_STATE_ENABLE;
    tmrOCConfig.outputNState = TMR_OC_NSTATE_DISABLE;
    tmrOCConfig.polarity = TMR_OC_POLARITY_HIGH;
    tmrOCConfig.nPolarity = TMR_OC_NPOLARITY_HIGH;
    tmrOCConfig.idleState = TMR_OC_IDLE_STATE_RESET;
    tmrOCConfig.nIdleState = TMR_OC_NIDLE_STATE_RESET;
    tmrOCConfig.pulse = PWM_Arry;
    TMR_ConfigOC2(TMR4, &tmrOCConfig);

    TMR_EnablePWMOutputs(TMR4);
    TMR_Enable(TMR4);
}3.按键触发中断
通过查阅原理图可知用户按键连接到了PA1上,按下时为低电平。在用户手册中查到PA1内部连接到了EINT1,可以在程序中配置PA1为上拉输入,开放EINT_LINE_1的中断请求,并设置为下降沿触发,然后设置中断优先级,开启中断。最后在中断处理函数中清除中断标志位,并给Led_Thread任务发送事件。

按键中断的配置使用例程中的void BOARD_BUTTON_Config(BOARD_BUTTON_T button, BOARD_BUTTON_MODE_T mode)函数,为适应FreeRTOS环境,需要把配置NVIC的代码修改为支持RTOS的接口:
void BOARD_BUTTON_Config(BOARD_BUTTON_T button, BOARD_BUTTON_MODE_T mode)
{
    GPIO_Config_T GPIO_ConfigStruct = {0U};
    EINT_Config_T EINT_ConfigStruct = {0U};
   
    /* Enable the BUTTON Clock */
    RCM_EnableAPB2PeriphClock(BUTTON_CLK | RCM_APB2_PERIPH_AFIO);
   
    /* Configure Button pin as input floating */
    GPIO_ConfigStruct.mode = GPIO_MODE_IN_PU;
    GPIO_ConfigStruct.pin = BUTTON_PIN;
    GPIO_Config(BUTTON_PORT, &GPIO_ConfigStruct);
   
    if (mode == BUTTON_MODE_EINT)
    {
      /* Connect Button EINT Line to Button GPIO Pin */
      GPIO_ConfigEINTLine(BUTTON_PORT_SOURCE, BUTTON_PIN_SOURCE);

      /* Configure Button EINT line */
      EINT_ConfigStruct.line = BUTTON_EINT_LINE;
      EINT_ConfigStruct.mode = EINT_MODE_INTERRUPT;
      EINT_ConfigStruct.trigger = EINT_TRIGGER_FALLING;
      EINT_ConfigStruct.lineCmd = ENABLE;
      EINT_Config(&EINT_ConfigStruct);

      /* Enable and set Button EINT Interrupt to the lowest priority */
      // NVIC_EnableIRQRequest(BUTTON_IRQn, 0x0F, 0x0F);
      NVIC_SetPriority (BUTTON_IRQn, 1U);
      NVIC_EnableIRQ(BUTTON_IRQn);
    }
}并在apm32f402_403_int.c中编写中断服务函数:
void EINT1_IRQHandler(void)
{
    if (EINT_ReadIntFlag(EINT_LINE_1))
    {
      EINT_ClearIntFlag(EINT_LINE_1);
      osEventFlagsSet(testEveGroupID, 0x1);
    }
}
为使中断服务函数能够调用RTOS接口,需要包含cmsis_os2.h头文件,并把调用到的任务和事件相关变量声明为外部变量。

4.PWM调光任务
PWM调光任务修改自FreeRTOS例程中的Led_Thread,任务中等待按键中断的事件,收到事件后切换LED2的状态,并打印按键消息,之后根据接收到的事件次数依次调用PWM_Arry数组中预定义的值切换PWM占空比来实现亮度调节的目的。具体代码如下:
uint16_t PWM_Arry = {999, 712, 590, 493, 409, 333, 262, 194, 128, 64, 0};
void Led_Thread(void *argument)
{
    UNUSED(argument);
    uint32_t cnt = 0;
    while (1)
    {
      /* Toggle LED2 */
      osEventFlagsWait(testEveGroupID, 0x1, osFlagsWaitAll, osWaitForever);
      BOARD_LED_Toggle(LED2);
      // osDelay(600);
      printf("get key push\r\n");
      cnt++;
      if(cnt > 11) {
            cnt = 0;
      }
      TMR_ConfigCompare2(TMR4, PWM_Arry);
    }
}
5.演示
代码编译完成烧录后,可以在日志中看到环境信息采集任务定时打印的气压、温湿度数据,按下Key1后可以看到获取按键消息的打印,开发板上的LED3随着按下次数循环改变亮度。



页: [1]
查看完整版本: 【APM32F402R Micro-EVB开发板测评】8、FreeRTOS外部中断触发任务通过PWM调整亮度