rtthread studio与正点原子apollo(3)--硬件定时器HTIMER


前言

本文介绍RT-Thread中如何使用硬件定时器。通过硬件定时器的中断实现LED周期控制的示例,说明硬件定时器的配置及相关API函数的使用。


一、软件定时器和硬件定时器?

1、软件定时器

关于软件定时器的使用可以参考官方文档
RT-Thread时钟管理

软件定时器是RT-Thread提供一类系统接口,优势是定时器的数量不受限制,缺点是定时的精确度相比于硬件定时器要低。
RT-Thread 的定时器提供两类定时器机制:单次触发和周期性触发。
RT-Thread 的软件定时器有两种模式:HARD_TIMER模式和SOFT_TIMER模式。

注意:软件定时的两种模式的区别是--超时函数执行时所处的上下文环境,SOFT_TIMER模式的定时器超时函数在都会在 timer 线程的上下文环境中执行,而HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行
软件定时器的模式默认为**HARD_TIMER 模式**

2.硬件定时器
Apollo使用的STM32F767芯片内部包含15个定时器,有高级定时器、通用定时器、基本定时器和低功耗定时器,可以根据需要选择使用。一般应用中,通用定时器使用较多,STM32F767的通过用定时器有TIM2 ~ TIM5,TIM9 ~ TIM14。

关于RT-Thread中硬件定时器的使用说明可以参考官方文档
HTIMER设备管理

二、HTIMER使用详解

1.RT-Thread studio配置

在使用硬件定时器前需要在RT-Thread studio环境中启动硬件定时器并做相应的配置:
(1)首先,启动硬件定时器功能,按下图配置:
在这里插入图片描述
(2)打开board.h文件,根据提示配置定时器,如下图:
在这里插入图片描述
定时器的配置按提示进行:
第一步:在(1)中已经完成;
第二步:取消宏定义BSP_USING_TIM的注释,并根据实际需求启动相应的定时器,本例中使用定时器3,因此宏定义BSP_USING_TIM3
第三步:在stm32cubemx配置定时器,并将生成的HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)函数拷贝到board.c文件中
在这里插入图片描述

第四步:将stm32xxxx_hal_config.h文件中的#define HAL_TIM_MODULE_ENABLED的宏定义功能开启
在这里插入图片描述

注意事项
在配置定时器时,由于RT-Thread并未将所有的资源进行配置,因此需要手动添加代码以实现相应的功能。
例如,在使用定时器时,我们需要打开tim_config.h文件,根据代码添加自己的功能代码,如下图所示:
在这里插入图片描述
另外,在设置中断入口函数名时,名称是有区别的,如果不清楚该如何修改,可以右键根据引导找到相应的定义
在这里插入图片描述

2.功能代码实现

根据官方文档,调用相关API函数实现硬件定时器的使用

参考代码如下:

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

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

#define LED0 GET_PIN(B,0)

#define HWTIMER_DEV_NAME "timer3"//定义定时器名称
rt_device_t hwtim_dev;//设备句柄
static struct rt_semaphore hwtim3_sem;

static rt_err_t timeout_cb(void)
{
    rt_sem_release(&hwtim3_sem);
    return RT_EOK;
}

static int hwtimer_sample(void)
{
    rt_err_t ret=RT_EOK;
    rt_hwtimerval_t timeout_s;
    rt_hwtimer_mode_t mode;
    rt_uint32_t freq=10000;

    hwtim_dev=rt_device_find(HWTIMER_DEV_NAME);//查找定时器
    if(hwtim_dev==RT_NULL)
    {
        rt_kprintf("hwtimer sample run failed! can't find %s device!\n",HWTIMER_DEV_NAME);
        return RT_ERROR;
    }
    ret=rt_device_open(hwtim_dev, RT_DEVICE_OFLAG_RDWR);//读写方式开启定时器
    if(ret!=RT_EOK)
    {
        rt_kprintf("open %s device failed!\n",HWTIMER_DEV_NAME);
        return RT_ERROR;
    }
    rt_device_set_rx_indicate(hwtim_dev, timeout_cb);//设置中断回调函数
    ret=rt_device_control(hwtim_dev, HWTIMER_CTRL_FREQ_SET, &freq);//设置定时器工作频率
    if(ret!=RT_EOK)
    {
        rt_kprintf("set frequency failed! ret is :%d\n", ret);
        return ret;
    }
    mode=HWTIMER_MODE_PERIOD;
    ret=rt_device_control(hwtim_dev, HWTIMER_CTRL_MODE_SET,&mode);//设置定时器为周期性
    if(ret!=RT_EOK)
    {
        rt_kprintf("set mode failed! ret is :%d\n", ret);
        return ret;
    }

    timeout_s.sec=1;
    timeout_s.usec=0;//设置定时器中断时间
    if(rt_device_write(hwtim_dev, 0, &timeout_s, sizeof(timeout_s))!=sizeof(timeout_s))
    {
        rt_kprintf("set timeout value failed\n");
        return RT_ERROR;
    }
    return RT_EOK;
}

int main(void)
{
    rt_uint8_t i=0;
    rt_pin_mode(LED0, PIN_MODE_OUTPUT);
    rt_pin_write(LED0, PIN_HIGH);
    rt_sem_init(&hwtim3_sem,"timer3_sem" ,0, RT_IPC_FLAG_FIFO);
    hwtimer_sample();
    while (1)
    {
        if(rt_sem_take(&hwtim3_sem, RT_WAITING_FOREVER)==RT_EOK)
        {
           i++;
           if(i%2==0)
           {
               rt_pin_write(LED0, PIN_HIGH);
               i=0;
           }
           else
           {
               rt_pin_write(LED0, PIN_LOW);
           }
        }
    }

    return RT_EOK;
}

总结

本文介绍了RT-Thread中硬件定时器的配置使用方法,及使用时的注意事项。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值