RT-Thread Studio硬件定时器hwtimer在stm32f411上的使用笔记

创建基于F411的芯片空工程。

启用hwtimer:
在这里插入图片描述
拷贝以下三个文件到drivers目录,路径分别为
C:\RT-ThreadStudio\download\rt-thread-sdk\rt-thread-src\v4.0.2\bsp\stm32\libraries\HAL_Drivers\config\f4
C:\RT-ThreadStudio\download\rt-thread-sdk\rt-thread-src\v4.0.2\bsp\stm32\libraries\HAL_Drivers
在这里插入图片描述
注释掉drv_hwtimer.c中的#include "drv_config.h"
取消注释stm32f4xx_hal_conf.h中的#define HAL_TIM_MODULE_ENABLED
tim_config.h添加#include <board.h>
drv_hwtimer.c添加#include <rtdevice.h>
drv_hwtimer.c添加#include <tim_config.h>

在board.h中定义需要使用的定时器:
在这里插入图片描述
根据要使用的定时器,修改tim_config.h

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-12-11     zylx         first version
 */

#ifndef __TIM_CONFIG_H__
#define __TIM_CONFIG_H__

#include <rtthread.h>
#include <board.h>
#ifdef __cplusplus
extern "C" {
#endif

#ifndef TIM_DEV_INFO_CONFIG
#define TIM_DEV_INFO_CONFIG                     \
    {                                           \
        .maxfreq = 1000000,                     \
        .minfreq = 3000,                        \
        .maxcnt  = 0xFFFF,                      \
        .cntmode = HWTIMER_CNTMODE_UP,          \
    }
#endif /* TIM_DEV_INFO_CONFIG */


#ifdef BSP_USING_TIM1
#ifndef TIM1_CONFIG
#define TIM1_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM1,                    \
       .tim_irqn                = TIM1_UP_TIM10_IRQn,  \
       .name                    = "timer1",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */



#ifdef BSP_USING_TIM2
#ifndef TIM2_CONFIG
#define TIM2_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM2,                    \
       .tim_irqn                = TIM2_IRQn,  \
       .name                    = "timer2",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */



#ifdef BSP_USING_TIM3
#ifndef TIM3_CONFIG
#define TIM3_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM3,                    \
       .tim_irqn                = TIM3_IRQn,  \
       .name                    = "timer3",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */




#ifdef BSP_USING_TIM4
#ifndef TIM4_CONFIG
#define TIM4_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM4,                    \
       .tim_irqn                = TIM4_IRQn,  \
       .name                    = "timer4",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */

#ifdef BSP_USING_TIM5
#ifndef TIM5_CONFIG
#define TIM5_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM5,                    \
       .tim_irqn                = TIM5_IRQn,  \
       .name                    = "timer5",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */

#ifdef BSP_USING_TIM9
#ifndef TIM9_CONFIG
#define TIM9_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM9,                    \
       .tim_irqn                = TIM1_BRK_TIM9_IRQn,  \
       .name                    = "timer9",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */

#ifdef BSP_USING_TIM10
#ifndef TIM10_CONFIG
#define TIM10_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM10,                    \
       .tim_irqn                = TIM1_UP_TIM10_IRQn,  \
       .name                    = "timer10",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */

#ifdef BSP_USING_TIM11
#ifndef TIM11_CONFIG
#define TIM11_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM11,                    \
       .tim_irqn                = TIM1_TRG_COM_TIM11_IRQn,  \
       .name                    = "timer11",                \
    }
#endif /* TIM11_CONFIG */
#endif /* BSP_USING_TIM11 */



#ifdef __cplusplus
}
#endif

#endif /* __TIM_CONFIG_H__ */

drv_hwtimer.h中增加CubeMX生成的底层代码:

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
    if (htim_base->Instance == TIM1)
    {
        __HAL_RCC_TIM1_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM2)
    {
        __HAL_RCC_TIM2_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM4)
    {
        __HAL_RCC_TIM4_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM5)
    {
        __HAL_RCC_TIM5_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM9)
    {
        __HAL_RCC_TIM9_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM10)
    {
        __HAL_RCC_TIM10_CLK_ENABLE();
    }
    else if (htim_base->Instance == TIM11)
    {
        __HAL_RCC_TIM11_CLK_ENABLE();
    }
}

修改drv_hwtimer.hHAL_TIM_PeriodElapsedCallback,为使用的定时器添加回调函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
#ifdef BSP_USING_TIM1
if (htim->Instance == TIM1)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM1_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM2
if (htim->Instance == TIM2)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM2_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM3
if (htim->Instance == TIM3)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM3_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM4
if (htim->Instance == TIM4)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM4_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM5
if (htim->Instance == TIM5)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM5_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM9
if (htim->Instance == TIM9)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM9_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM10
if (htim->Instance == TIM10)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM10_INDEX].time_device);
}
#endif
#ifdef BSP_USING_TIM11
if (htim->Instance == TIM11)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM11_INDEX].time_device);
}
#endif
}

添加中断函数入口:

#ifdef BSP_USING_TIM2
void TIM2_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM2_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM3
void TIM3_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM3_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM4
void TIM4_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM4_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM5
void TIM5_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM5_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM11
void TIM1_BRK_TIM9_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM9_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif

#if defined( BSP_USING_TIM1) ||defined(BSP_USING_TIM10)
void TIM1_UP_TIM10_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
#ifdef BSP_USING_TIM1
if (__HAL_TIM_GET_FLAG(&stm32_hwtimer_obj[TIM1_INDEX].tim_handle,TIM_IT_UPDATE) != RESET)
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM1_INDEX].tim_handle);
#endif
#ifdef BSP_USING_TIM10
if (__HAL_TIM_GET_FLAG(&stm32_hwtimer_obj[TIM10_INDEX].tim_handle,TIM_IT_UPDATE) != RESET)
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM10_INDEX].tim_handle);
#endif

/* leave interrupt */
rt_interrupt_leave();
}
#endif

#ifdef BSP_USING_TIM11
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM11_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif

新建一个usertimer.c,添加示例代码,通过msh调用即可看到效果:

/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-03-23     ShineRoyal       the first version
 */
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>

#define DBG_TAG "user"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define LED0_PIN    GET_PIN(C, 0)
#define LED1_PIN    GET_PIN(C, 1)
#define LED2_PIN    GET_PIN(C, 2)
#define LED3_PIN    GET_PIN(C, 3)
#define LED4_PIN    GET_PIN(C, 4)
#define LED5_PIN    GET_PIN(C, 5)
#define LED6_PIN    GET_PIN(C, 6)
#define LED7_PIN    GET_PIN(C, 7)


static int rt_hw_pin_init()
{
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED4_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED5_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED6_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED7_PIN, PIN_MODE_OUTPUT);
    return 0;
}
INIT_BOARD_EXPORT(rt_hw_pin_init);

/* 定时器超时回调函数 */
static rt_err_t timeout_cb1(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED0_PIN, PIN_LOW);
    else
        rt_pin_write(LED0_PIN, PIN_HIGH);
    LOG_D("%d",i);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb2(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED1_PIN, PIN_LOW);
    else
        rt_pin_write(LED1_PIN, PIN_HIGH);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb3(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED2_PIN, PIN_LOW);
    else
        rt_pin_write(LED2_PIN, PIN_HIGH);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb4(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED3_PIN, PIN_LOW);
    else
        rt_pin_write(LED3_PIN, PIN_HIGH);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb5(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED4_PIN, PIN_LOW);
    else
        rt_pin_write(LED4_PIN, PIN_HIGH);
    return 0;
}


/* 定时器超时回调函数 */
static rt_err_t timeout_cb9(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED5_PIN, PIN_LOW);
    else
        rt_pin_write(LED5_PIN, PIN_HIGH);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb10(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED6_PIN, PIN_LOW);
    else
        rt_pin_write(LED6_PIN, PIN_HIGH);
    return 0;
}

/* 定时器超时回调函数 */
static rt_err_t timeout_cb11(rt_device_t dev, rt_size_t size)
{
    static int i = 0;
    i++;
    if (i % 2)
        rt_pin_write(LED7_PIN, PIN_LOW);
    else
        rt_pin_write(LED7_PIN, PIN_HIGH);
    return 0;
}


static int hw1timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer1");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb1);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw1timer_sample, hw1timer_sample);

static int hw2timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer2");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb2);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw2timer_sample, hw2timer_sample);

static int hw3timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer3");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb3);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw3timer_sample, hw3timer_sample);

static int hw4timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer4");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb4);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw4timer_sample, hw4timer_sample);

static int hw5timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer5");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb5);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw5timer_sample, hw5timer_sample);

static int hw9timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer9");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb9);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw9timer_sample, hw9timer_sample);

static int hw10timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer10");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb10);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw10timer_sample, hw10timer_sample);

static int hw11timer_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
    rt_hwtimer_mode_t mode;         /* 定时器模式 */

    /* 查找定时器设备 */
    hw_dev = rt_device_find("timer11");
    /* 以读写方式打开设备 */
    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb11);
    /* 设置模式为周期性定时器 */
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return ret;
}
MSH_CMD_EXPORT(hw11timer_sample, hw11timer_sample);

注意,定时器1的定时会快一倍(这里是1s的间隔,但定时器1会500ms进一次中断),尚不清楚是rt-thread的库造成的还是硬件本身时钟相关的原因,后续在研究。

完整工程下载

第二天找到了具体原因,查看RT-Thread Studio部分定时器时钟不正确的解决方案

发布了339 篇原创文章 · 获赞 78 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/qq_27508477/article/details/105040617