本篇介紹中科藍(lán)訊 ab32vg1 的 timer 的用法,ab32vg1 有5個(gè)timer,其中timer0、timer1、timer2 只支持 32 位的定時(shí)器功能,timer3、timer4、timer5 能夠被配置成定時(shí)器模式、計(jì)數(shù)器模式、輸入捕獲模式和 pwm 模式。本文首先介紹 rt-thread 提供的 api函數(shù),接著列出了使用 sdk 的詳細(xì)步驟,最后分析一次代碼。
1.rt-thread提供的 timer的API
?rt-thread是通過(guò) I/O 設(shè)備模型來(lái)管理 soc 上的外設(shè),從上到下分為三層:I/O 設(shè)備管理層、設(shè)備驅(qū)動(dòng)框架層和設(shè)備驅(qū)動(dòng)層。stm32 的 HAL 庫(kù)就屬于設(shè)備驅(qū)動(dòng)層,比如熟知的 i2c、spi 的外設(shè)驅(qū)動(dòng)在用 cubemx 生成代碼的時(shí)候就已經(jīng)準(zhǔn)備好。中科藍(lán)訊的 ab32vg1 的設(shè)備驅(qū)動(dòng)已經(jīng)在 sdk 中由藍(lán)訊的工程師實(shí)現(xiàn)。而在設(shè)備驅(qū)動(dòng)層之上的設(shè)備驅(qū)動(dòng)框架層和設(shè)備 I/O 管理層要說(shuō)明一下:設(shè)備驅(qū)動(dòng)框架層提供了一些接口留給設(shè)備驅(qū)動(dòng)開發(fā)者去實(shí)現(xiàn),只在做驅(qū)動(dòng)移植的時(shí)候需要,作為普通用戶,只需要關(guān)心I/O 管理層即可,rt-thread 的 I/O 管理層提供了類似于 linux 中文件 IO 的API,常用的有 rt_device_find、rt_device_open、rt_device_read、rt_device_close 等。下面列舉了 hwtimer 的 api,結(jié)合示例去理解如何將這些API用起來(lái)實(shí)現(xiàn)定時(shí)器的功能。
rt_device_trt_device_find(const char* name):查找設(shè)備,name為設(shè)備名字。
rt_err_trt_device_open(rt_device_t dev, rt_uint16_t oflags):打開定時(shí)器設(shè)備,dev為定時(shí)器設(shè)備句柄,oflags:打開模式,一般取RT_DEVICE_OFLAG_RDWR。
rt_err_trt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_tdev,rt_size_t size)) :設(shè)置超時(shí)回調(diào),dev:定時(shí)器設(shè)備句柄 rx_ind:超時(shí)回調(diào)函數(shù)
rt_err_trt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg): 控制定時(shí)器, dev:定時(shí)器設(shè)備句柄 cmd:控制命令,可取值如下:
HWTIMER_CTRL_FREQ_SET設(shè)置計(jì)數(shù)頻率
HWTIMER_CTRL_STOP停止定時(shí)器
HWTIMER_CTRL_INFO_GET獲取定時(shí)器特征信息
HWTIMER_CTRL_MODE_SET設(shè)置定時(shí)器模式
arg:控制命令參數(shù) 設(shè)置定時(shí)器模式時(shí),可取值如下:
?HWTIMER_MODE_ONESHOT 單 次 定 時(shí)
?HWTIMER_MODE_PERIOD 周 期 性 定 時(shí)
rt_size_trt_device_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_tsize):設(shè)置定時(shí)器超時(shí)值,dev:定時(shí)器設(shè)備句柄 pos:偏移值,未使用,可取 0 值 buffer:指向超時(shí)時(shí)間結(jié)構(gòu)體 size:超時(shí)時(shí)間結(jié)構(gòu)體大小
rt_size_trt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size ):獲取定時(shí)器當(dāng)前值,dev:定時(shí)器句柄 pos:偏移值,未使用,可取 0值 buffer:超時(shí)時(shí)間結(jié)構(gòu)體 size:超時(shí)時(shí)間結(jié)構(gòu)體大小。
rt_err_trt_device_close(rt_device_t dev):關(guān)閉定時(shí)器。
2.硬件定時(shí)器的應(yīng)用步驟
定時(shí)器的配置流程:首先用rt_device_find 根據(jù)設(shè)備名稱查找到定時(shí)器句柄、使用定時(shí)器句柄打開定時(shí)器、接著設(shè)置定時(shí)器的回調(diào)函數(shù)、配置完定時(shí)器后設(shè)置定時(shí)器的定時(shí)值后定時(shí)器啟動(dòng),之后每當(dāng)定時(shí)器的計(jì)數(shù)器溢出就會(huì)執(zhí)行一次定時(shí)器的回調(diào)函數(shù)。
3.具體應(yīng)用案例
3.1利用rt-thread studio 新建BSP工程,選擇基于開發(fā)板的項(xiàng)目,開發(fā)型號(hào)選擇AB32VG1-AB-PROUGEN,點(diǎn)擊完成即可。
3.2 配置 rt-thread setting
雙擊 RT-Thread Setting,進(jìn)入RT-Thread Setting配置界面,如下所示
然后點(diǎn)擊點(diǎn)擊更多配置
在硬件選項(xiàng)下勾選定時(shí)器,使能定時(shí)器1
?
按快捷鍵Ctrl+S,更新軟件包。然后編譯工程,將程序下載開發(fā)板。在Downloader軟件窗口中msh指令lsit_device,可以看到打印結(jié)果定時(shí)器設(shè)備timer1,這里的timer1就是定時(shí)器的名字name,這個(gè)名字在對(duì)定時(shí)器操作時(shí)用到。
3.3 增加測(cè)試源文件
?選中applications,點(diǎn)擊右鍵添加源文件timer.c。
然后復(fù)制如下示例代碼粘貼到timer.c中,
/*
?* Copyright (c) 2006-2021, RT-ThreadDevelopment Team
?*
?* SPDX-License-Identifier: Apache-2.0
?*
?* Change Logs:
?* Date?????????? Author?????? Notes
?* 2021-12-11???? admin?????? the first version
?*/
#include
#include
#defineHWTIMER_DEV_NAME?? "timer1"??? /* 定時(shí)器名稱 */
/* 定時(shí)器超時(shí)回調(diào)函數(shù) */
staticrt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
??? rt_kprintf("this is hwtimer timeoutcallback fucntion!\n");
??? rt_kprintf("tick is :%d !\n", rt_tick_get());
??? return 0;
}
staticint hwtimer_sample(int argc, char *argv[])
{
??? rt_err_t ret = RT_EOK;
??? rt_hwtimerval_t timeout_s;????? /* 定時(shí)器超時(shí)值 */
??? rt_device_t hw_dev = RT_NULL;?? /* 定時(shí)器設(shè)備句柄 */
??? rt_hwtimer_mode_t mode;??????? /* 定時(shí)器模式 */
??? /* 查找定時(shí)器設(shè)備 */
??? 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;
??? }
??? /* 以讀寫方式打開設(shè)備 */
??? 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;
??? }
??? /* 設(shè)置超時(shí)回調(diào)函數(shù) */
??? rt_device_set_rx_indicate(hw_dev,timeout_cb);
??? /* 設(shè)置模式為周期性定時(shí)器 */
??? 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;
??? }
??? /* 設(shè)置定時(shí)器超時(shí)值為5s并啟動(dòng)定時(shí)器 */
??? 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;
??? }
??? /* 延時(shí)3500ms */
??? rt_thread_mdelay(3500);
??? /* 讀取定時(shí)器當(dāng)前值 */
??? 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;
}
/* 導(dǎo)出到 msh命令列表中 */
MSH_CMD_EXPORT(hwtimer_sample,hwtimer sample);
3.4 編譯工程
3.5 下載工程
3.6 運(yùn)行效果
該例程導(dǎo)出了hwtimer_sample 命令到控制終端,命令調(diào)用格式:hwtimer_sample,只需要msh窗口中輸入hwtimer_sample即可啟動(dòng)定時(shí)器。硬件定時(shí)器超時(shí)回調(diào)函數(shù)周期性的打印當(dāng)前 tick 值,2 次 tick 值之差換算為時(shí)間等同于定時(shí)時(shí)間值。運(yùn)行打印內(nèi)容如下:兩次tick值為5000ms,即定時(shí)時(shí)間為5s。
4. 章節(jié)總結(jié)
使用 rt-threadstudio 進(jìn)行 sdk 的開發(fā)是一件非常有效率的事情,新建 bsp 工程后只需要在 rt-thread setting 配置需要的硬件功能就可以使用 rt-thread 提供的設(shè)備 I/O 管理接口對(duì)底層的 soc 的外設(shè)進(jìn)行控制。
審核編輯:劉清
評(píng)論