RT-Thread HWTIMER设备(学习)

这篇具有很好参考价值的文章主要介绍了RT-Thread HWTIMER设备(学习)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

定时器简介

硬件定时器一般有2种工作模式,定时器模式和计数器模式。不管是工作在哪一种模式,实质都是通过内部计数器模块对脉冲信号进行计数,下面是定时器的一些重要概念。

  • 计数器模式:对外部输入引脚的外部脉冲信号计数。
  • 定时器模式:对内部脉冲信号计数。定时器常用作定时时钟,以实现定时检测,定时响应,定时控制。

计数器:计数器可以递增计数或者递减计数,16位计数器的最大计数值为65535.

计数频率:定时器模式时,计数器单位时间内的计数次数,由于系统时钟频率是定值,所以根据计数器的计数值计算出定时时间,定时时间=计数值/计数频率。
例如计数频率为1MHz,计数器计数一次的时间为1/1000000,也就是没经过1微妙计数器加一,此时16位计数器的最大定时能力为65535微妙,即65.535毫秒。

本定时器设备框架内部会自动处理硬件定时器超时的问题,例如16位定时器在1MHz的频率下最大只能维持65.535ms。
但是本定时器框架下,用户可以将定时器的溢出时间设置为例如500ms,框架内部会自动处理硬件溢出问题。当时间达到500ms后,框架会调用用户预先设置好的回调函数。

访问硬件定时器设备

RT-Thread HWTIMER设备(学习),RT-Thread,学习,单片机,嵌入式硬件,RT-Thread

查找定时器设备

应用程序根据硬件定时器设备名称获取设备句柄,进而可以操作硬件定时器设备。

rt_device_t rt_device_find(const char* name);

一般情况下,注册到系统的硬件定时器设备名称为timer0,timer1等。

#define HWTIMER_DEV_NAME "timer0";
rt_device_t hw_dev;
hw_dev = rt_device_find(HWTIMER_DEV_NAME);

打开定时器设备

通过设备句柄,应用程序可以打开设备。
打开设备时,会检测设备是否已经初始化,没有初始化则会默认调用初始化接口初始化设备。

rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
  • dev:硬件定时器设备句柄。
  • oflags:设备打开模式,一般以读写方式打开,即RT_DEVICE_OFLAG_RDWR

设置超时回调函数

在C语言和C++语言中,将一个函数声明为’static’具有以下含义:

  1. 作用域限制:函数声明为’static’会将其作用域限制在当前文件中,这意味着该函数只能在包含它的源文件中调用,而不能在其他文件中调用。这可以用于隐藏函数的实现细节,避免与其他文件中的同名函数发生冲突。
  2. 链接性:'static’函数具有内部链接性,这意味着它不会被放在全局符号表中,无法被其他文件访问。这有助于减小程序的全局命名空间污染。
rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size))
  • dev:设备句柄。
  • rx_ind:超时回调函数,由调用者提供。
#define HWTIMER_DEV_NAME   "timer0"     /* 定时器名称 */
rt_device_t hw_dev;                     /* 定时器设备句柄 */

/* 定时器超时回调函数 */
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
    rt_kprintf("this is hwtimer timeout callback fucntion!\n");
    rt_kprintf("tick is :%d !\n", rt_tick_get());

    return 0;
}

static int hwtimer_sample(int argc, char *argv[])
{
    /* 查找定时器设备 */
    hw_dev = rt_device_find(HWTIMER_DEV_NAME);
    /* 以读写方式打开设备 */
    rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);

    ...

    /* 设置超时回调函数 */
    rt_device_set_rx_indicate(hw_dev, timeout_cb);

    return 0;
}

控制定时器设备

通过命令控制字,应用程序可以对硬件定时器设备进行配置。

rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void *arg);
  • dev:设备句柄
  • cmd:命令控制字
  • arg:控制的参数
  • 返回:RT_EOK:函数执行成功。-RT_ENSYS:执行失败,dev为空。

硬件定时器设备支持的命令控制字如下:

  • HWTIMER_CTRL_FRQ_SET:设置计数频率(若未设置该项,默认为1MHz或支持的最小计数频率)
  • HWTIMER_CTRL_STOP:停止计时器
  • HWTIMER_CTRL_INFO_GET:获取定时器特征信息
  • HWTIMER_CTRL_MODE_SET:设置定时器模式(若未设置,默认是HWTIMER_MODE_ONESHOT)

获取定时器特征信息参数arg为指向结构体struct rt_hwtimer_info的指针,作为一个输出参数保存获取的信息。

设置定时器模式时,参数arg可取:

  • HWTIMER_MODE_ONESHOT:单次定时
  • HWTIMER_MODE_PERIOD:周期性定时
#define HWTIMER_DEV_NAME   "timer0"     /* 定时器名称 */
rt_device_t hw_dev;                     /* 定时器设备句柄 */
rt_hwtimer_mode_t mode;                 /* 定时器模式 */
rt_uint32_t freq = 10000;               /* 计数频率 */

static int hwtimer_sample(int argc, char *argv[])
{
	hw_dev = rt_device_find(HWTIMER_DEV_NAME);
	rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);

	rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);
	mode = HWTIMER_MODE_PERIOD;
	rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
	return 0;
}

设置定时器超时值

通过如下函数可以设置定时器的超时值,在调用该函数后,定时器更新参数并开启。

rt_size_t rt_device_write(rt_device_t dev, rt_odd_t pos, const void* buffer, rt_size_t size);
  • dev:设备句柄。
  • pos:写入数据偏移量,未使用,可取0值。
  • buffer:指向定时器超时时间结构体的指针。
  • size:超时时间结构体的大小。
  • 返回:写入数据的实际大小,0:失败。

超时时间结构体原型:

typedef struct rt_hwtimerval
{
	rt_int32_t sec;
	rt_int32_t usec;
}

设置定时器超时值的使用示例如下:

#define HWTIMER_DEV_NAME "timer0"
rt_device_t hw_dev; //定时器设备句柄
rt_hwtimerval_t timeout_s; //定时器超时值

static int hwtimer_sample(int argc, char *argv[])
{
	//查找定时器设备
	hw_dev = rt_device_find(HWTIMER_DEV_NAME);
	rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);

	//设置定时器超时值为5s并启动定时器
	timeout_s.sec = 5;
	timeout_s.usec = 0;
	rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s));
	return 0;
	
}

获取定时器当前值

通过如下函数可以获取自定时器开始(rt_device_write)之后的运行时:

rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
  • dev:定时器设备句柄
  • pos:写入数据偏移量,未使用,可取0值
  • buffer:输出参数,指向定时器超时时间结构体的指针
  • size:超时时间结构体的大小
  • return:成功-超时时间结构体的大小,0:失败
rt_hwtimerval_t t;
rt_device_read(hw_dev, 0, &t, sizeof(t));
rt_kprintf("Read: Sec = %d, Usec = %d\n", t.sec, t.usec);

关闭定时器设备

通过如下函数关闭定时器设备:

rt_err_t rt_device_close(rt_device_t dev);
  • dev:定时器设备句柄
  • 返回:RT_EOK-关闭设备成功,-RT_ERROR-设备已经完全关闭,不能重复关闭设备,其它错误码-关闭设备失败。

关闭设备接口和打开设备接口需配对使用,打开一次设备对应要关闭一次设备,这样设备才会被完全关闭,否则设备仍处于未关闭状态。

注:可能出现定时误差。假设计数器最大值0xFFFF,计数频率1MHz,定时时间1s又1us。
由于定时一次最多只能计时到65535us,对于1000001us的定时要求,可以50000us定时20次完成,此时会出现计算误差1us。

硬件定时器设备完整使用示例

硬件定时器设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:文章来源地址https://www.toymoban.com/news/detail-726661.html

  1. 首先根据定时器设备名称“timer0”查找设备获取设备句柄。
  2. 以读写方式打开设备“timer0”。
  3. 设置定时器超时回调函数。
  4. 设置定时器模式为周期性定时器,并设置超时时间为5s,此时定时器启动。
  5. 延时3500ms后读取定时器时间,读取到的值会以秒和微妙的形式显示。
//例程导出了hwtimer_sample命令到控制终端
//程序功能:硬件定时器超时回调函数周期性的打印当前tick值,2次tick值之差换算为时间等同于定时时间

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

#define HWTIMER_DEV_NAME "timer0" //定时器名称

//定时器超时回调函数
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
	rt_kprintf("this is hwtimer timeout callback function\n");
	rt_kprintf("tick is : %d \n",rt_tick_get());

	return 0;
}

static int hwtimer_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; //定时器模式
	rt_uint32_t freq = 10000; //计数频率

	hw_dev = rt_device_find(HWTIMER_DEV_NAME);
	if(hw_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(hw_dev, RT_DEVICE_OFLAG_RDWR);
	if(ret != RT_EOK)
	{
		rt_kprintf("open %s device failed\n",HWTIMER_DEV_NAME);
		return ret;
	}
	rt_device_set_rx_indicate(hw_dev, timeout_cb);

	rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);
	mode = HWTIMER_MODE_PERIOD;
	ret = rt_device_control(hw_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 = 5;
	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;
	}
	rt_thread_mdelay(3500);
	
	rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
	rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);

    return ret;
}
MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);

到了这里,关于RT-Thread HWTIMER设备(学习)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32&RT-Thread零基础入门】 3. PIN设备(GPIO)的使用

    硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 在嵌入式系统中,GPIO是最常用的一种设备,在RT-Thread操作系统中,把GPIO命名为PIN设备。 RT-Thread通过PIN设备对芯片的GPIO引脚进行管理,应用程序可以通过其提供的一组PIN设备

    2024年02月13日
    浏览(46)
  • RT-Thread(学习)

    RT-Thread是一款完全由国内团队开发维护的嵌入式实时操作系统(RTOS),具有完全的自主知识产权。经过16个年头的沉淀,伴随着物联网的兴起,它正演变成一个功能强大、组件丰富的物联网操作系统。 RT-Thread,全称是Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作

    2024年02月07日
    浏览(41)
  • RT-Thread 中断管理学习(二)

    RTT不对中断服务程序所需要的处理时间做任何假设、限制,但如图其它实时操作系统或非实时操作系统一样,用户需要保证所有的中断服务程序在尽可能短的时间内完成(中断服务程序在系统中相当于拥有最高的优先级,会抢占所有线程优先执行)。这样在发生中断嵌套,或

    2024年02月10日
    浏览(48)
  • RT-Thread 中断管理学习(一)

    什么是中断?简单的解释就是系统正在处理某一个正常事件,忽然被另一个需要马上处理的紧急事件打断,系统转而处理这个紧急事件,待处理完毕,再恢复运行刚才被打断的事件。生活中,我们经常会遇到这样的场景: 当你正在专心看书的时候,忽然来了一个电话,于是记

    2024年02月10日
    浏览(46)
  • [攻城狮计划]RT-Thread—详解UART设备(基于RA2E1)

    🚀🚀开启攻城狮的成长之旅!这是我参与的由 CSDN博客专家 架构师李肯和 瑞萨MCU 联合发起的「 致敬未来的攻城狮计划 」的第4天,点击查看活动计划详情 🚀🚀首先非常感谢李老师能给我参加这个计划的机会,让我有机会接触到许多的开发板,同时也感谢瑞萨官方 为我们

    2024年02月13日
    浏览(80)
  • RT-Thread Studio学习(十四)ADC

    本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用ADC设备。硬件及开发环境如下: OS WIN10 STM32F407VET6 STM32CubeMX v6.10.0 STM32Cube MCU Package for STM32F4 Series v1.28.0 RT-Thread Studio v2.2.7 RT-Thread Source Code v5.0.2 STM32F4 chip support packages v0.2.3 打开RT-Thread Studio软件新建基于芯片的项

    2024年01月19日
    浏览(41)
  • RT-Thread学习(一)简介及基础环境配置

    之前学习了FreeRTOS,但是一直想深入学习,但是没有人指导,又不知道该如何学习,于是再学习一个操作系统看看情况。 RT-Thread是一个物联网操作系统,几乎支持所有主流的MCU和Wi-Fi芯片,实时多线程操作系统,主要用在32位的MCU上面。物联网(Internet Of Things,IoT),RT-Threa

    2024年01月17日
    浏览(36)
  • 嵌入式MCU学习利器-03-在线做RT-Thread实验

    很多学生想要学习RT-Thread,但是苦于没有好的学习工具或者物理开发板而选择放弃。现在福利来了,同学们可以基于我们的仿真平台做嵌入式demo,通过调试功能深入学习RT-Thread的原理。本仿真平台基于STM32F103ZE芯片上线了一套RT-Thread课程,逐步深入讲解FreeRTOS。 本文章以第一节

    2024年02月08日
    浏览(35)
  • RT-Thread 1. GD32移植RT-Thread Nano

    1. RT-Thread Nano 下载 RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实

    2024年02月05日
    浏览(44)
  • RT-Thread 9. VS2012下仿真RT-Thread 和LVGL

    1. 在ENV中添加组件 2. 下载组件 3. 生成代码 4. 打开代码 双击project.vcxproj 编译 5. 运行

    2024年02月06日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包