STM32F105 -- FreeRTOS 软件定时器

1. FreeRTOS 创建一个任务 BeepSoftwareTimers

#define BEEP_NOTIFICATION_SOFTWARE_TIMERS_TASK_STACK_SIZE    128
#define BEEP_NOTIFICATION_SOFTWARE_TIMERS_TASK_PRIORITY    6

xTaskCreate((TaskFunction_t)BeepSoftwareTimers, \
            (const char *)"beep_software_timers", \
            (uint16_t)BEEP_NOTIFICATION_SOFTWARE_TIMERS_TASK_STACK_SIZE, \
            (void *)NULL, \
            (UBaseType_t)BEEP_NOTIFICATION_SOFTWARE_TIMERS_TASK_PRIORITY, \
            (TaskHandle_t *)&g_beepSoftwareTimersTask_Handler);

2. 在任务里面创建定时器队列, 创建了 7 个软件定时器,创建完定时器后将该任务删除,只保留定时器队列,在未启动定时器之前,定时器是处于休眠状态的,功耗很低

static void BeepSoftwareTimers(void)
{
    g_beepNotifyTimer_BeepOn_2ms = xTimerCreate((const char *)"beepNotification_beep_on_2ms",
                                                (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_2ms), // timer period
                                                (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                (void *)BeepSoftwareTimer_ID_1, // software timer id
                                                (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOn_2ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOn_2ms)
    {
        // TODO
    }
    g_beepNotifyTimer_BeepOn_100ms = xTimerCreate((const char *)"beepNotification_beep_on_100ms",
                                                  (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_100ms), // timer period
                                                  (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                  (void *)BeepSoftwareTimer_ID_2, // software timer id
                                                  (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOn_100ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOn_100ms)
    {
    }
    g_generalNotify_BeepOn_100ms = xTimerCreate((const char *)"generalNotification_BeepOn_100ms",
                                                  (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_100ms), // timer period, please do not set to too small
                                                  (UBaseType_t)pdTRUE, // pdTRUE - period mode, pdFALSE - one times mode
                                                  (void *)BeepSoftwareTimer_ID_3, // software timer id
                                                  (TimerCallbackFunction_t)GeneralNotificationSoftwareTimer_BeepOn_100ms_Callback);
    if (NULL == g_generalNotify_BeepOn_100ms)
    {
    }
    g_beepNotifyTimer_BeepOff_20ms = xTimerCreate((const char *)"beepNotification_beep_off_20ms",
                                                  (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_20ms), // timer period
                                                  (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                  (void *)BeepSoftwareTimer_ID_4, // software timer id
                                                  (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOff_20ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOff_20ms)
    {
    }
    g_beepNotifyTimer_BeepOff_100ms = xTimerCreate((const char *)"beepNotification_beep_off_100ms",
                                                   (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_100ms), // timer period
                                                   (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                   (void *)BeepSoftwareTimer_ID_5, // software timer id
                                                   (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOff_100ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOff_100ms)
    {
    }
    g_beepNotifyTimer_BeepOff_200ms = xTimerCreate((const char *)"beepNotification_beep_off_200ms",
                                                   (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_100ms), // timer period
                                                   (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                   (void *)BeepSoftwareTimer_ID_6, // software timer id
                                                   (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOff_200ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOff_200ms)
    {
    }
    g_beepNotifyTimer_BeepOff_500ms = xTimerCreate((const char *)"beepNotification_beep_off_500ms",
                                                   (TickType_t)pdMS_TO_TICKS(beepDelayTimeToTick_100ms), // timer period
                                                   (UBaseType_t)pdFALSE, // pdTRUE - period mode, pdFALSE - one times mode
                                                   (void *)BeepSoftwareTimer_ID_7, // software timer id
                                                   (TimerCallbackFunction_t)beepNotificationSoftwareTimer_BeepOff_500ms_Callback);
    if (NULL == g_beepNotifyTimer_BeepOff_500ms)
    {
    }
    vTaskDelete(g_beepNotificationSoftwareTimersTask_Handler); // 创建完定时器后将该任务删除
}

3. 需要在FreeRTOS 的配置文件FreeRTOSConfig.h 中打开FreeRTOS 软件定时器宏开关,并配置最多可以创建多少个软件定时器

// FreeRTOS related to soft timer configuration options
#define configUSE_TIMERS    1 // 1 - enable soft timer, 0 - disable soft timer
#define configTIMER_TASK_PRIORITY    (configMAX_PRIORITIES - 1) // soft timer priority
#define configTIMER_QUEUE_LENGTH    10 // soft timer queue len
#define configTIMER_TASK_STACK_DEPTH    (configMINIMAL_STACK_SIZE * 2) // soft timer task stack size

4. 在创建软件定时器的时候可以选择定时器的模式,由xTimerCreate() 第三个参数决定

4.1 (UBaseType_t)pdFALSE: 定时器只启动一次

4.2 (UBaseType_t)pdTRUE: 每隔一段时间启动一次定时器

5. 定时器回调函数,启动定时器后,到了时间点就会进一次回调函数,然后你就可以在回调函数里面做你想做的事情了,xTimerCreate() 第五个参数

// IO port operation macro definition, refer to <<Corterx-M3/M4 authoritative guide>> chapter 5, page 87 ~ 92
#define BITBAND(addr, bitnum)    ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))
#define MEM_ADDR(addr)    (*((volatile unsigned long  *)(addr)))
#define BIT_ADDR(addr, bitnum)    MEM_ADDR(BITBAND(addr, bitnum))

#define PAout(n)    BIT_ADDR(GPIOA_ODR_Addr, n)

#define BUZZER_GPIO_PORT    8
#define BEEP_CTRL    PAout(BUZZER_GPIO_PORT)

#define EVEN_NUMBER    0
#define ODD_NUMBER    1
#define PARITY_OPERATION    2

static void GeneralNotificationSoftwareTimer_BeepOn_100ms_Callback(void *parameter)
{
    UNUSED(parameter);

    static uint8_t g_notificationCounter = BeepSoftwareTimerCounters_Min;

    g_notificationCounter++;
    if (g_notificationCounter < BeepSoftwareTimerCounters_3) // you can set 3, 5, 7 ... (BeepSoftwareTimerCounters_3)
    {
        if (EVEN_NUMBER == (g_notificationCounter % PARITY_OPERATION))
        {
            BEEP_CTRL = BEEP_OFF;
        }
        else if (ODD_NUMBER == (g_notificationCounter % PARITY_OPERATION))
        {
            BEEP_CTRL = BEEP_ON;
        }
    }
    else
    {
        xTimerStop(g_generalNotify_BeepOn_100ms, BeepSoftwareTimerTicksToWait_Min);
        g_notificationCounter = BeepSoftwareTimerCounters_Min;
    }
}

我这里配置的是循环启动定时器,每隔100ms启动一次定时器,启动定时器后,过100ms 就会进回调函数,然后在回调函数里面判断进来回调函数次数是奇数次还是偶数次,奇数次进回调就把蜂鸣器打开,偶数次就会把蜂鸣器关闭,同时计数蜂鸣器打开的次数,可以控制蜂鸣器响几次

6. 关闭定时器

xTimerStop(g_generalNotify_BeepOn_100ms, BeepSoftwareTimerTicksToWait_Min); // BeepSoftwareTimerTicksToWait_Min = 0,

6.1 第一个参数是创建定时器函数的第一个参数xTimerCreate(),定时器句柄

6.2 第二个参数,调用关闭函数xTimerStop的时候,什么时候真正关闭定时器,我这里是调用xTimerStop() 的就立即把定时器关了

7. 创建定时器

TimerHandle_t xTimerCreate(const char * const pcTimerName,
                           const TickType_t xTimerPeriod,
                           const UBaseType_t uxAutoReload,
                           void * const pvTimerID,
                           TimerCallbackFunction_t pxCallbackFunction);

7.1 参数说明:

7.1.1 pcTimerName:定时器的名称,以字符串形式表示。
7.1.2 xTimerPeriod:定时器的周期时间,单位是 tick, 系统时钟节拍,一般是1ms
7.1.3 uxAutoReload:指示定时器是否自动重载的标志。如果设置为 1,则定时器将在每次触发后自动重新启动;如果设置为 0,则定时器只会触发一次。
7.1.4 pvTimerID:用户自定义的定时器 ID,可以作为回调函数的参数传递给用户使用。
7.1.5 pxCallbackFunction:定时器触发时要执行的回调函数。
7.1.6 该函数返回一个 TimerHandle_t 类型的定时器句柄,可以在后续操作中使用该句柄进行定时器的修改、启动、停止等操作。
7.1.7 需要注意的是,使用 xTimerCreate 创建的定时器需要在合适的时机通过 xTimerStart 函数启动,才能开始计时。

8. 启动定时器

/*
 * startup the timer, which create by xTimerCreate()
 * xTimer: software timer handle, xTimerCreate() first parameter
 * xTicksToWait: when you want to startup the timer, usually set 0
 * startup success: return pdPASS
 * startup failure: return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY, errQUEUE_BLOCKED, errQUEUE_YIELD
 */
#define xTimerStart(xTimer, xTicksToWait)    xTimerGenericCommand((xTimer), tmrCOMMAND_START, (xTaskGetTickCount()), NULL, (xTicksToWait))

8.1 xTimer 第一个参数,是创建定时器函数xTimerCreate() 的第一个参数,定时器句柄

8.2 xTicksToWait 调用启动函数xTimerStart() 之后,什么时候真正启动定时器,开始计数

9. 在中断服务函数里面只能用专门的启动函数,这是FreeRTOS 的特性,所有中断服务只能用专门的API

#define xTimerStartFromISR(xTimer, pxHigherPriorityTaskWoken)    xTimerGenericCommand((xTimer), tmrCOMMAND_START_FROM_ISR, (xTaskGetTickCountFromISR()), (pxHigherPriorityTaskWoken), 0U)

猜你喜欢

转载自blog.csdn.net/weixin_50212044/article/details/132143121
今日推荐