rtthread studio與正點原子apollo[3]--硬體定時器HTIMER
- 前言
- 一、軟體定時器和硬體定時器?
- 二、HTIMER使用詳解
-
- 1.RT-Thread studio配置
- 2.功能代碼實作
- 總結
前言
本文介紹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)首先,啟動硬體定時器功能,按下圖配置:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLlhDZmZDNwITYmNjNkhTO5UjMkRzYhZjZ4cDZmhjZ2czLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(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中硬體定時器的配置使用方法,及使用時的注意事項。