軟件定時器是FreeRTOS中的一個重要模塊,使用軟件定時器可以方便的實現(xiàn)一些與超時或周期性相關(guān)的功能。
	
	
硬件定時器
	
	
芯片本身提供的定時功能。一般是由外部晶振提供給芯片輸入時鐘,芯片向軟件模塊提供一組配置寄存器,接受控制輸入,到達(dá)設(shè)定時間值后芯片中斷控制器產(chǎn)生時鐘中斷。硬件定時器的精度一般很高,可以達(dá)到納秒級別,并且是中斷觸發(fā)方式。
	
軟件定時器
	
	
	
軟件定時器是由操作系統(tǒng)提供的一類系統(tǒng)接口,它構(gòu)建在硬件定時器基礎(chǔ)之上,使系統(tǒng)能夠提供不受硬件定時器資源限制的定時器服務(wù),它實現(xiàn)的功能與硬件定時器也是類似的。
	
	
FreeRTOS 軟件定時器功能
裁剪:能通過宏關(guān)閉軟件定時器功能。
軟件定時器創(chuàng)建。
軟件定時器啟動。
軟件定時器停止。
軟件定時器復(fù)位。
	軟件定時器刪除。
	
	
	
軟件定時器模式
	
	
單次模式:當(dāng)用戶創(chuàng)建了定時器并啟動了定時器后,定時時間到了,只執(zhí)行一次回調(diào)函數(shù)之后就將該定時器刪除,不再重新執(zhí)行。
周期模式:這個定時器會按照設(shè)置的定時時間循環(huán)執(zhí)行回調(diào)函數(shù),直到用戶將定時器刪除

	
	
FreeRTOS 通過一個 prvTimerTask 任務(wù)(也叫守護(hù)任務(wù) Daemon)管理軟定時器,它是在啟動調(diào)度器時自動創(chuàng)建的,為了滿足用戶定時需求。prvTimerTask 任務(wù)會在其執(zhí)行期間檢查用戶啟動的時間周期溢出的定時器,并調(diào)用其回調(diào)函數(shù)。只有設(shè)置 FreeRTOSConfig.h中的宏定義 configUSE_TIMERS 設(shè)置為 1 ,將相關(guān)代碼編譯進(jìn)來,才能正常使用軟件定時器相關(guān)功能。
配置定時器
//啟用軟件定時器
#define configUSE_TIMERS                    1                              
//軟件定時器優(yōu)先級
#define configTIMER_TASK_PRIORITY            (configMAX_PRIORITIES-1)        
//軟件定時器隊列長度
#define configTIMER_QUEUE_LENGTH            10                               
//軟件定時器任務(wù)堆棧大小
#define configTIMER_TASK_STACK_DEPTH        (configMINIMAL_STACK_SIZE*2) 
	
創(chuàng)建定時器
TimerHandle_t xTimerCreate( const char *pcTimerName, 
                            const TickType_t xTimerPeriod, 
                            const UBaseType_t uxAutoReload, 
                            void * const pvTimerID, 
                           TimerCallbackFunction_t pxCallbackFunction );
	參數(shù):
	
pcTimerName:定時器名稱
xTimerPeriod :定時周期
uxAutoReload : 如果將uxAutoReload設(shè)置為pdTRUE,則計時器將以xTimerPeriod參數(shù)設(shè)置的頻率重復(fù)終止。如果將uxAutoReload設(shè)置為pdFALSE,則計時器將是一次觸發(fā),并在其到期后進(jìn)入休眠狀態(tài)。
pvTimerID:分配給正在創(chuàng)建的計時器的標(biāo)識符。
pxCallbackFunction:計時器到期時要調(diào)用的函數(shù)。
	返回值:
	
如果成功創(chuàng)建了計時器,則返回新創(chuàng)建的計時器的句柄。如果由于剩余的FreeRTOS堆不足而無法分配計時器結(jié)構(gòu)而無法創(chuàng)建計時器,則返回NULL
啟動定時器
BaseType_t xTimerStart( TimerHandle_t xTimer, 
                        TickType_t xTicksToWait );
	參數(shù):
	
	xTimer:計時器的句柄
	
xTicksToWait:指定在計時器命令隊列已經(jīng)滿的情況下,任務(wù)應(yīng)保持阻塞狀態(tài)以等待空間可用的最大時間。
	返回值:
	
如果即使經(jīng)過xBlockTime刻度后仍無法將啟動命令發(fā)送到計時器命令隊列,則將返回pdFAIL。如果命令已成功發(fā)送到計時器命令隊列,則將返回pdPASS。
停止定時器
BaseType_t xTimerStop( TimerHandle_t xTimer, 
                       TickType_t xTicksToWait );
參數(shù):同上
	返回值:同上
	
	
	
復(fù)位定時器
BaseType_t xTimerReset( TimerHandle_t xTimer, 
                        TickType_t xTicksToWait );
參數(shù):同上
返回值:同上
	
	
刪除定時器
BaseType_t xTimerDelete( TimerHandle_t xTimer, 
                         TickType_t xTicksToWait );
參數(shù):同上類似
返回值:同上類似
	
	
改變定時器周期
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, 
                               TickType_txNewPeriod,
                               TickType_t xTicksToWait );
參數(shù):
	xTimer:定時器的句柄
	
xNewPeriod:新的周期參數(shù)
xTicksToWait:指定在計時器命令隊列已經(jīng)滿的情況下,任務(wù)應(yīng)保持阻塞狀態(tài)以等待空間可用的最大時間。
	返回值:
	
如果即使經(jīng)過xBlockTime滴答聲后仍無法將更改周期命令發(fā)送到計時器命令隊列,則將返回pdFAIL。如果命令已成功發(fā)送到計時器命令隊列,則將返回pdPASS。
	
	
還有中斷啟動定時器、停止、復(fù)位、改變周期的API函數(shù),請查閱官方文檔!
	
	
附上小例程
#include "stm32f10x.h"
#include 
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "timers.h"
//毫秒級的延時
void Delay_Ms(u16 time)
{    
   u16 i=0;  
   while(time--)
   {
      i=12000;  //自己定義
      while(i--) ;    
   }
}
void LED_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;        //定義結(jié)構(gòu)體變量
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);  //開啟時鐘
  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;            //選擇你要設(shè)置的IO口
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;      //設(shè)置推挽輸出模式
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;     //設(shè)置傳輸速率
  GPIO_Init(GPIOC,&GPIO_InitStructure);                //初始化GPIO
  
  GPIO_SetBits(GPIOC,GPIO_Pin_0);             //將LED端口拉高,熄滅LED
}
void KEY_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure; //定義結(jié)構(gòu)體變量  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;     //選擇你要設(shè)置的IO口
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//下拉輸入  
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;     //設(shè)置傳輸速率
  GPIO_Init(GPIOA,&GPIO_InitStructure);      /* 初始化GPIO */
  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;  //上拉輸入
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOE,&GPIO_InitStructure);
}
void USART_init(uint32_t bound)
{
  GPIO_InitTypeDef GPIO_InitStruct;   //定義GPIO結(jié)構(gòu)體變量
  USART_InitTypeDef USART_InitStruct;   //定義串口結(jié)構(gòu)體變量
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);   //使能GPIOC的時鐘
  
  GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;   //配置TX引腳
  GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;   //配置PA9為復(fù)用推挽輸出
  GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;   //配置PA9速率
  GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函數(shù)
  
  GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;   //配置RX引腳
  GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;   //配置PA10為浮空輸入
  GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;   //配置PA10速率
  GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函數(shù)
  
  
  USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;   //發(fā)送接收模式
  USART_InitStruct.USART_Parity=USART_Parity_No;   //無奇偶校驗
  USART_InitStruct.USART_BaudRate=bound;   //波特率
  USART_InitStruct.USART_StopBits=USART_StopBits_1;   //停止位1位
  USART_InitStruct.USART_WordLength=USART_WordLength_8b;   //字長8位
  USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;   //無硬件數(shù)據(jù)流控制
  USART_Init(USART1,&USART_InitStruct);   //串口初始化函數(shù)
  
  USART_Cmd(USART1,ENABLE);   //使能USART1
}
int fputc(int ch,FILE *f)   //printf重定向函數(shù)
{
  USART_SendData(USART1,(uint8_t)ch);   //發(fā)送一字節(jié)數(shù)據(jù)
  while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);   //等待發(fā)送完成
  return ch;
}
#define START_TASK_PRIO 5      //任務(wù)優(yōu)先級
#define START_STK_SIZE 128      //任務(wù)堆棧大小
TaskHandle_t StartTask_Handler;   //任務(wù)句柄
void Start_Task(void *pvParameters);//任務(wù)函數(shù)
#define Low_TASK_PRIO 2       //任務(wù)優(yōu)先級
#define Low_STK_SIZE 50       //任務(wù)堆棧大小
TaskHandle_t LowTask_Handler;     //任務(wù)句柄
void Low_Task(void *p_arg);     //任務(wù)函數(shù)
#define Med_TASK_PRIO 3       //任務(wù)優(yōu)先級
#define Med_STK_SIZE 50       //任務(wù)堆棧大小
TaskHandle_t MedTask_Handler;     //任務(wù)句柄
void Med_Task(void *p_arg);     //任務(wù)函數(shù)
TimerHandle_t Time0Handler = NULL;  //軟件定時器句柄
void Time0Callback( TimerHandle_t pxTimer );//回調(diào)函數(shù)
int main( void ) 
{
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設(shè)置系統(tǒng)中斷優(yōu)先級分組 4
  
  LED_Init(); //初始化 LED
  KEY_Init();
  USART_init(9600);
  
  //創(chuàng)建開始任務(wù)
  xTaskCreate(
    (TaskFunction_t )Start_Task,     //任務(wù)函數(shù)
    (const char* )"Start_Task",     //任務(wù)名稱
    (uint16_t )START_STK_SIZE,       //任務(wù)堆棧大小
    (void* )NULL,             //傳遞給任務(wù)函數(shù)的參數(shù)
    (UBaseType_t )START_TASK_PRIO,     //任務(wù)優(yōu)先級
    (TaskHandle_t* )&StartTask_Handler  //任務(wù)句柄 
  );
  vTaskStartScheduler();  //開啟調(diào)度
}
//開始任務(wù)函數(shù)
void Start_Task(void *pvParameters)
{
  taskENTER_CRITICAL();   //進(jìn)入臨界區(qū)
  //創(chuàng)建軟件定時器
  Time0Handler = xTimerCreate( ( char *                ) "Time0",     //定時器的名稱
                 ( TickType_t              ) 1000,       //定時周期
                 ( UBaseType_t             ) pdTRUE,       //是否重裝載 (pdTRUE or pdFAIL)
                 ( void *                  ) 0,         //ID號
                 ( TimerCallbackFunction_t ) Time0Callback ); //回調(diào)函數(shù)
  //開啟定時器
  xTimerStart( Time0Handler, portMAX_DELAY );
  //創(chuàng)建 Low 任務(wù)
  xTaskCreate(
    (TaskFunction_t )Low_Task, 
    (const char* )"Low_Task", 
    (uint16_t )Low_STK_SIZE, 
    (void* )NULL,
    (UBaseType_t )Low_TASK_PRIO,
    (TaskHandle_t* )&LowTask_Handler
  );
  //創(chuàng)建 Med 任務(wù)
  xTaskCreate(
    (TaskFunction_t )Med_Task, 
    (const char* )"Med_Task", 
    (uint16_t )Med_STK_SIZE, 
    (void* )NULL,
    (UBaseType_t )Med_TASK_PRIO,
    (TaskHandle_t* )&MedTask_Handler
  );
  vTaskDelete(StartTask_Handler); //刪除開始任務(wù)
  taskEXIT_CRITICAL();   //退出臨界區(qū)
}
void Low_Task(void *pvParameters)
{
  while(1)
  {
    
    vTaskDelay(1000);
  }
}
void Med_Task(void *pvParameters)
{
  //BaseType_t xReturn = NULL;
  while(1)
  {
    printf("正在運行n");
    vTaskDelay(1000);
  }
}
void Time0Callback( TimerHandle_t pxTimer )
{
  static int count = 0;
  printf("%dn",++count);
}
	
	
實驗現(xiàn)象

	
	
	--END--
	
- 
                                軟件定時器
                                +關(guān)注關(guān)注 0文章 18瀏覽量 7023
- 
                                FreeRTOS
                                +關(guān)注關(guān)注 14文章 496瀏覽量 66061
發(fā)布評論請先 登錄
Linux和RTOS的時鐘和定時器怎么使用
555定時器應(yīng)用設(shè)計軟件免費下載
 
    
設(shè)計軟件定時器
 
    
詳細(xì)剖析Linux和RTOS(RT-Thread)的時鐘和定時器的使用
 
    
軟件定時器簡介及程序配置
 
    
 
           
        
 
         Free RTOS的軟件定時器
Free RTOS的軟件定時器 
                 
  
     
     
     
     
            
             
             
                 
             工商網(wǎng)監(jiān)
工商網(wǎng)監(jiān)
        
評論