RT-Thread Studio学习(二)HWTIMER

RT-Thread Studio学习(二)HWTIMER

简介

本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用HWTIMER设备。

新建项目并使用外部时钟

打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习之使用外部时钟系统

启用HWTIMER

根据board.h文件中的描述,启用HWTIMER需要完成如下四个步骤:

/*-------------------------- HARDWARE TIMER CONFIG BEGIN --------------------------*/

/** if you want to use hardware timer you can use the following instructions.
 *
 * STEP 1, open hwtimer driver framework support in the RT-Thread Settings file
 *
 * STEP 2, define macro related to the hwtimer
 *                 such as     #define BSP_USING_TIM  and
 *                             #define BSP_USING_TIM1
 *
 * STEP 3, copy your hardwire timer init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
 *                 such as     void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
 *
 * STEP 4, modify your stm32xxxx_hal_config.h file to support hardwere timer peripherals. define macro related to the peripherals
 *                 such as     #define HAL_TIM_MODULE_ENABLED
 *
 */
  1. 打开HWTIMER驱动框架
    RT-Thread Setting 文件中借助图形化配置工具打开软件 HWTIMER的驱动框架,如下图所示
    在这里插入图片描述
  2. 定义HWTIMER相关的宏
    board.h中定义需要使用的定时器:
#define BSP_USING_TIM
#ifdef BSP_USING_TIM
#define BSP_USING_TIM1
#define BSP_USING_TIM10
/*#define BSP_USING_TIM15*/
/*#define BSP_USING_TIM16*/
/*#define BSP_USING_TIM17*/
#endif
  1. 复制HWTIMER初始化函数
    打开STM32CubeMX软件,根据实际情况完成对应TIM的配置。在本文中,使用了TIM1和TIM10,这两个TIM的Clock Source都使用Internal Clock,具体如下图:在这里插入图片描述
    在这里插入图片描述
    从生成后的工程文件stm32xxxx_hal_msp.c中复制函数void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)到board.c的末尾。
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(htim_base->Instance==TIM1)
    {
    /* USER CODE BEGIN TIM1_MspInit 0 */

    /* USER CODE END TIM1_MspInit 0 */
      /* Peripheral clock enable */
      __HAL_RCC_TIM1_CLK_ENABLE();

      __HAL_RCC_GPIOE_CLK_ENABLE();
      /**TIM1 GPIO Configuration
      PE9     ------> TIM1_CH1
      */
      GPIO_InitStruct.Pin = GPIO_PIN_9;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
      HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* USER CODE BEGIN TIM1_MspInit 1 */

    /* USER CODE END TIM1_MspInit 1 */
    }
    else if(htim_base->Instance==TIM10)
    {
    /* USER CODE BEGIN TIM10_MspInit 0 */

    /* USER CODE END TIM10_MspInit 0 */
      /* Peripheral clock enable */
      __HAL_RCC_TIM10_CLK_ENABLE();
    /* USER CODE BEGIN TIM10_MspInit 1 */

    /* USER CODE END TIM10_MspInit 1 */
    }

}
  1. 定义stm32xxxx_hal_config.h中的相关宏
    stm32f4xx_hal_conf.h中定义需要使用的模块:
#define HAL_TIM_MODULE_ENABLED

另外,还需要修改tim_config.hdrv_hwtimer.c文件。项目中tim_config.h文件的路径为drivers\include\config\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>

#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_TIM10
#ifndef TIM10_CONFIG
#define TIM10_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM10,                    \
       .tim_irqn                = TIM1_UP_TIM10_IRQn,  \
       .name                    = "timer10",                \
    }
#endif /* TIM10_CONFIG */
#endif /* BSP_USING_TIM10 */

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

#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 BSP_USING_TIM13
#ifndef TIM13_CONFIG
#define TIM13_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM13,                    \
       .tim_irqn                = TIM8_UP_TIM13_IRQn,       \
       .name                    = "timer13",                \
    }
#endif /* TIM13_CONFIG */
#endif /* BSP_USING_TIM13 */

#ifdef BSP_USING_TIM14
#ifndef TIM14_CONFIG
#define TIM14_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM14,                    \
       .tim_irqn                = TIM8_TRG_COM_TIM14_IRQn,  \
       .name                    = "timer14",                \
    }
#endif /* TIM14_CONFIG */
#endif /* BSP_USING_TIM14 */

#ifdef __cplusplus
}
#endif

#endif /* __TIM_CONFIG_H__ */

修改drv_hwtimer.h文件:
注释掉drv_hwtimer.c中的#include "drv_config.h"
drv_hwtimer.c添加#include <rtdevice.h>
drv_hwtimer.c添加#include <tim_config.h>
修改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_TIM10
if (htim->Instance == TIM10)
{
    rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM10_INDEX].time_device);
}
#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

测试

main.c测试代码如下:

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-01-16     RT-Thread    first version
 */

#include <rtthread.h>
#include <stdlib.h>
#include <rtdevice.h>
#include "drv_common.h"

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

#define LED_PIN    GET_PIN(F, 9)
#define LED0_PIN    GET_PIN(F, 10)


static int rt_hw_pin_init()
{
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED0_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++;
    rt_pin_write(LED_PIN, i % 2);
    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);
    /* 设置定时器超时值为2s并启动定时器 */
    timeout_s.sec = 2;      /* 秒 */
    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);

int main(void)
{
    int count = 1;

    while (count++)
    {
        /* set LED0 pin level to high or low */
        rt_pin_write(LED0_PIN, count % 2);
//        LOG_D("Hello RT-Thread!");
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

通过msh运行hw1timer_sample即可看到效果。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值