Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
timer
nuc980
NK-980IOT测评之TIMER
发布于 2022-03-28 00:36:39 浏览:770
订阅该版
[tocm] ## 开发环境简介 ![IMG_20220326_205404.jpg](https://oss-club.rt-thread.org/uploads/20220328/e82c1348233c6dc1a133571e53382f8f.jpg.webp) - NK-980IOT V1.0 (NUC980DK61Y) - RT-Thread Studio + J-Link + VCOM - U-Boot from SPI-NAND and rtthread running in DDR ## TIMER硬件介绍 ### 概述 > The timer controller includes six 32-bit timers, Timer0 ~ Timer5, allowing user to easily implement a timer control applications. The timer can perform functions, such as frequency measurement, delay timing, clock generation, and event counting by external input pins, and interval measurement by external capture pins. TMR共包含6个32位定时器,定时器0~定时器5,可实现多种功能如:频率测量、延迟计时、时钟生成和通过外部输入引脚的事件计数,以及通过外部捕获引脚进行间隔测量。 ### 特性 > - Six sets of 32-bit timers with 24-bit up counter and one 8-bit prescale counter > - Independent Clock Source for each Timer > - Provides one-shot, periodic, toggle-output and continuous counting operation modes > - 24-bit up counter value is readable through CNT (TIMERx_CNT[23:0]) > - Supports event counting function to count input event from pin TMx_ECNT (x = 0~5) > - Supports toggle output to pin TMx_TGL (x = 0~5) > - 24-bit capture value is readable through CAPDAT (TIMERx_CAP[23:0]) > - Supports event capture from external pin TMx_EXT (x = 0~5) for interval measurement > - Supports event capture from RTC 1Hz signal for RTC clock calibration > - Supports event capture from external pin TMx_EXT (x = 0~5) to reset 24-bit up counter > - Supports chip wake-up from Idle/Power-down mode if a timer interrupt signal is > generated > - Supports time-out interrupt or capture interrupt to trigger ADC and PDMA. > - Supports Inter-Timer trigger that Timer 0 can trigger Timer 1, Timer 2 can trigger Timer 3, > and Timer4 can trigger Timer5. ### 功能框图 详见[NUC980 Series Technical Reference Manual](https://www.nuvoton.com/export/resource-files/TRM_NUC980_Series_EN_Rev1.01.pdf) **6.9.3 Block Diagram** ## TIMER使用说明 1. 创建工程 使用RT-Thread Studio基于开发板傻瓜式创建项目,调试方式选择J-Link + JTAG: ![Snipaste_2022-03-26_21-20-10.jpg](https://oss-club.rt-thread.org/uploads/20220328/4f54ccc6199829972aadce369936b4a2.jpg.webp) 2. 修改RT-Thread Settings 去除掉模板工程中多余的配置和组件,只保留必要功能和TIMER(timer0)外设: ![Snipaste_2022-03-26_21-28-57.jpg](https://oss-club.rt-thread.org/uploads/20220328/af6a1375f442346f83f4d86551214554.jpg.webp) 编译运行并查看已经注册到系统里的设备是否有`etimer0`: ![Snipaste_2022-03-26_21-40-40.jpg](https://oss-club.rt-thread.org/uploads/20220328/363a594362ae403442ee8bf5f1ab35e1.jpg.webp) 3. 代码简述 参考RT-Thread文档中心[硬件定时器设备使用示例](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/hwtimer/hwtimer?id=%e7%a1%ac%e4%bb%b6%e5%ae%9a%e6%97%b6%e5%99%a8%e8%ae%be%e5%a4%87%e4%bd%bf%e7%94%a8%e7%a4%ba%e4%be%8b) - 流程说明:查找设备→打开设备→设置超时回调函数→将定时值写入设备→读设备值查看验证 ```c #define HWTIMER_DEV_NAME "etimer0" 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); /* 设置模式为周期性定时器 */ 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; } /* 设置定时器超时值为1s并启动定时器 */ 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; } /* 读取定时器当前值 */ 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); /* 延时500ms */ rt_thread_mdelay(500); /* 读取定时器当前值 */ rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s)); rt_kprintf("\r\nRead: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec); ``` 超时回调函数: ```c static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) { int led_s = rt_pin_read(LED_R); rt_kprintf("%s timeout callback at %d ticks!\n", dev->parent.name, rt_tick_get()); rt_pin_write(LED_R, !led_s); rt_kprintf("The RED led is %s now!\n", led_s == 1 ? "on" : "off"); return 0; } ``` 该函数会在定时器超时中断里调用,作用:每1S将红色LED输出状态翻转一次,即使用硬件定时器“点灯”(梦开始的地方)。 > PS:timeout_cb函数内容只是为了演示说明,好孩子千万别在实际项目里这么写 - 底层浅析(以timer0为例) 终于到了祭出分层优雅的IO设备模型图的时候了: ![io-call.png](https://oss-club.rt-thread.org/uploads/20220328/4325ead0a144794832cc2b65745a6d92.png) 上面的程序调用`rt_device_open`时,会向下调用新唐提供的底层设备驱动`drv_etimer.c`,在这里初始化定时器的预分频系数,才能为接下来的定时器操作提供时基: ![Snipaste_2022-03-26_22-15-28.jpg](https://oss-club.rt-thread.org/uploads/20220328/b100049bd0572d80658d0a57da112d60.jpg.webp) 翻开手册瞥一眼: ![Snipaste_2022-03-26_22-18-53.jpg](https://oss-club.rt-thread.org/uploads/20220328/9a62c8e017fbdab76150894a179d671a.jpg.webp) 可以发现上面的程序将timer0的时基设为12M ÷ (11 + 1) = 1MHz,并写入了最底层的预分频寄存器,时间线收束,perfect! >RT-Thread Studio 宏展开真好用 (#^.^#) 其它的诸如`rt_device_write`→`nu_etimer_start`等流程,类比上述分析即可。 - 功能演示 ![Snipaste_2022-03-26_22-37-56.jpg](https://oss-club.rt-thread.org/uploads/20220328/f702fbe471e3f8a92b61d451754f93a9.jpg) 将定时值写入etimer0设备后读其值,延时500ms后再读值,发现Usec从3变成500553,单位为us,说明定时器已经按照预期设定跑起来了。 ![动画.gif](https://oss-club.rt-thread.org/uploads/20220328/931f98b21ede1c0b176f1ff8477b9b6e.gif) 从上面动图演示也不难看出,定时器每隔1S就会将红色LED的输出状态翻转一次(忽略wifi图传延时)。 ## 代码链接 [Gitee](https://gitee.com/charlesxsong/nuc980.git) ## 心得体会 总体来说,RT-Thread向下提供了层级完备的移植接口,新唐能够很容易地将自家的驱动对接注册进来。用户在使用的时候可以不必过于关注底层的东西,直接照着官方文档调用上层API即可很快地让板子跑起来。 然而,timer的功能不仅仅只有“定时”而已,更多的诸如计数、测频以及输入捕获等功能我也大抵翻了手册研究了一下,但由于没有文档使用说明(尤其是`rt_inputcapture.c`),且鄙人时间和能力有限,只是盲人摸象般简单看了下相关驱动,没能将功能跑起来;希望在RT官方和开源的力量下能够慢慢完善使用教程,让这些常用功能早日浮出水面。 ```c static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) { nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture); RT_ASSERT(inputcapture != RT_NULL); /* Enable Timer Interrupt */ rt_hw_interrupt_umask(psNuTCap->irqn); /* Clear counter before openning. */ ETIMER_ClearCounter(psNuTCap->idx); ETIMER_Open(psNuTCap->idx, ETIMER_CONTINUOUS_MODE, 1); ETIMER_SET_PRESCALE_VALUE(psNuTCap->idx, cal_time_prescale(psNuTCap)); ETIMER_SET_CMP_VALUE(psNuTCap->idx, 0xFFFFFF); ETIMER_EnableCapture(psNuTCap->idx, ETIMER_CAPTURE_COUNTER_RESET_MODE, ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE); ETIMER_EnableCaptureInt(psNuTCap->idx); ETIMER_Start(psNuTCap->idx); return RT_EOK; } ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
CharlesX
Make science fiction science
文章
4
回答
33
被采纳
8
关注TA
发私信
相关文章
1
不同的pwm能否使用同一个timer的不同channel?
2
硬件定时器的问题咨询
3
hard fault on thread: timer
4
NANO移植finsh会导致启动时卡死在rt_object_init
5
rt_timer_start 链表死循环
6
定时器 rt_timer_init 里超时时间无效
7
timer文件的源码分析
8
定时器API bug反馈
9
关于RT-Thread中的软定时器使用疑问请教
10
rt_timer_detach脱离定时器后,定时器还在执行
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部