軟定時(shí)器實(shí)驗(yàn)
一.實(shí)驗(yàn)?zāi)康?br>本程序展示了Small RTOS51 中使用一個(gè)任務(wù)實(shí)現(xiàn)多個(gè)軟定時(shí)器管理,軟定時(shí)器的精度
達(dá)到1 個(gè)系統(tǒng)節(jié)拍。
二.設(shè)備及器件
IBM PC 機(jī) 一臺
DP-51PROC 單片機(jī)綜合仿真實(shí)驗(yàn)儀 一臺
三.實(shí)驗(yàn)步驟
1. 將A2 區(qū)的A0~A2 分別連接到B3 區(qū)的A0~A2。
2. 將A2 區(qū)的P10 連接到B3 區(qū)的RST。
3. 將A3 區(qū)的Y0 連接到B3 區(qū)的/CS。
4. 將A2 區(qū)的A15~A10 分別連接到A3 區(qū)的相關(guān)控制引腳,如下:
A15 --- /G2B
A14 --- /G2A
A13 --- G1
A12 --- C
A11 --- B
A10 --- A
5. 在B3 區(qū)的J92 插入圖形液晶模塊(單色,128×64 點(diǎn))。
6. 將B3 區(qū)的J85 短接,A3 區(qū)的JP4 短接。
四.實(shí)驗(yàn)參考程序主要部分
/**********************************************************
** Small RTOS(51)
** The Real-Time Kernel(For Keil c51)
** (c) Copyright 2002-2002, chenmingji
** All Rights Reserved
** V1.20
**************************************************************/
#include "config.h"
uint8 TimeAdd[4]; //時(shí)間計(jì)數(shù),用于紀(jì)錄從復(fù)位以來的時(shí)間
void TimeSum(void);
/**********************************************************
** 函數(shù)名稱: main
** 功能描述: 主函數(shù),用戶程序從這里執(zhí)行
**********************************************************/
void main(void)
{
OSInit();
TMOD = (TMOD & 0XF0) | 0X01;
TH0 = (65536 - (11059200 / 12) / 100) / 256;
TL0 = (65536 - (11059200 / 12) / 100) % 256;
TR0 = 1;
ET0 = 1;
TF0 = 0;
OSSemCreate(ZL12864_SEM, 1);
LCM_DispIni();
OSDispClr();
OSTaskCreate(TimeSum, NULL, 0);
OSTaskCreate(SoftTimer, NULL, 1);
while(1)
{
PCON = PCON | 0x01; /* CPU 進(jìn)入休眠狀態(tài) */
}
}
/**********************計(jì)時(shí)*************************/
void SoftTimerFunction2(void);
/*******************************************************
** 函數(shù)名稱: SoftTimerFunction1
** 功能描述: 軟定時(shí)器0 運(yùn)行的任務(wù),與軟定時(shí)器1 配合使LCD 顯示的“:”閃爍
********************************************************/
void SoftTimerFunction1(void)
{
OSDispChar(3, 7, ':');
SoftTimerRun(1,(OS_TICKS_PER_SEC + 1) / 2,SoftTimerFunction2);
}
/*********************************************************
** 函數(shù)名稱: SoftTimerFunction2
** 功能描述: 軟定時(shí)器1 運(yùn)行的任務(wù),與軟定時(shí)器0 配合使LCD 顯示的“:”閃爍
***********************************************************/
void SoftTimerFunction2(void)
{
OSDispChar(3, 7, ' ');
SoftTimerRun(0,OS_TICKS_PER_SEC / 2,SoftTimerFunction1);
}
/************************************************************
** 函數(shù)名稱: SoftTimerFunction3
** 功能描述: 軟定時(shí)器2 運(yùn)行的任務(wù),與任務(wù)TimeSum 配合使LCD 顯示閃爍
*************************************************************/
void SoftTimerFunction3(void)
{
OSDispChar(3, 5, ' ');
OSDispChar(3, 6, ' ');
OSDispChar(3, 8, ' ');
OSDispChar(3, 9, ' ');
SoftTimerRun(2,OS_TICKS_PER_SEC * 4,SoftTimerFunction3);
}
/**************************************************************
** 函數(shù)名稱: TimeSum
** 功能描述: 記錄復(fù)位以來的時(shí)間的任務(wù)
***********************************************************/
void TimeSum(void)
{
/* 初始化軟定時(shí)器模塊 */
InitSoftTimer();
/* 運(yùn)行兩個(gè)軟定時(shí)器 */
SoftTimerRun(1,OS_TICKS_PER_SEC / 2,SoftTimerFunction2);
SoftTimerRun(2,OS_TICKS_PER_SEC * 4
+ OS_TICKS_PER_SEC / 2,SoftTimerFunction3);
OSDispChar(3, 7, ':');
while (1)
{
OSDispChar(3, 5, TimeAdd[0] + '0');
OSDispChar(3, 6, TimeAdd[1] + '0');
OSDispChar(3, 8, TimeAdd[2] + '0');
OSDispChar(3, 9, TimeAdd[3] + '0');
OSWait(K_TMO,OS_TICKS_PER_SEC);
/* 計(jì)時(shí)并顯示 */
TimeAdd[3]++;
if (TimeAdd[3] >= 10)
{
TimeAdd[3] = 0;
TimeAdd[2]++;
if (TimeAdd[2] >= 6)
{
TimeAdd[2] = 0;
TimeAdd[1]++;
if (TimeAdd[1] >= 10)
{
TimeAdd[1] = 0;
TimeAdd[0]++;
if(TimeAdd[0] >= 10)
{
TimeAdd[0] = 0;
}
}
}
}
}
}
SoftTimer. c 文件源代碼
#define IN_SOFT_TIMER
#include "config.h"
/* 軟定時(shí)器的數(shù)據(jù)結(jié)構(gòu) */
typedef SOFT_TIMER_MEM_SEL struct _TySoftTimerData
{
uint8 Falg; /* 軟定時(shí)器狀態(tài) */
uint16 DelayTime; /* 軟定時(shí)器運(yùn)行時(shí)間 */
void (const * Fuction)(void); /* 軟定時(shí)器溢出調(diào)用的函數(shù) */
};
#if MAX_SOFT_TIMER > 0
uint16 SoftTimerCnt; /* 輔助定時(shí)器 */
uint16 SoftTimerThisDelay; /* 輔助定時(shí)器初始值 */
struct _TySoftTimerData SOFT_TIMER_MEM_SEL SoftTimerData[MAX_SOFT_TIMER];
/**********************************************************
** 函數(shù)名稱: SoftTimerSum
** 功能描述: 每次系統(tǒng)節(jié)拍處理時(shí)調(diào)用的函數(shù),一個(gè)輔助定時(shí)器
******************************************************************/
void SoftTimerSum(void)
{
if( --SoftTimerCnt == 0)
{
OSIntSendSignal(SOFT_TIMER_TASK_ID);
}
}
/**************************************************************
** 函數(shù)名稱: InitSoftTimer
** 功能描述: 初始化軟定時(shí)器模塊
************************************************************/
void InitSoftTimer(void)
{
uint8 i;
OS_ENTER_CRITICAL();
for (i = 0; i < MAX_SOFT_TIMER; i++)
{
SoftTimerData[i].Falg = 0;
SoftTimerData[i].DelayTime = 0;
SoftTimerData[i].Fuction = NULL;
}
OS_EXIT_CRITICAL();
}
/*****************************************************************
** 函數(shù)名稱: SoftTimerRun
** 功能描述: 運(yùn)行一個(gè)軟定時(shí)器
** 輸 入: Index:軟定時(shí)器的索引
** Delay:延時(shí)時(shí)間
** Fuction:定時(shí)器溢出執(zhí)行的函數(shù)
** 輸 出: NOT_OK:參數(shù)錯(cuò)誤
** SOFT_TIMER_OK:操作正確
*********************************************************/
uint8 SoftTimerRun(uint8 Index, uint16 Delay, void (const * Fuction)(void))
{
#if EN_SOFT_TIMER_CHK > 0
if (Index >= MAX_SOFT_TIMER)
{
return NOT_OK;
}
#endif
if (Delay != 0 && Fuction != NULL)
{
OS_ENTER_CRITICAL();
SoftTimerData[Index].Fuction = Fuction;
SoftTimerThisDelay -= SoftTimerCnt;
SoftTimerCnt = 0;
SoftTimerData[Index].DelayTime = Delay + SoftTimerThisDelay;
SoftTimerData[Index].Falg &= ~SOFT_TIMER_TIMER_OUT;
SoftTimerData[Index].Falg |= SOFT_TIMER_TIMER_RUN;
OS_EXIT_CRITICAL();
OSSendSignal(SOFT_TIMER_TASK_ID);
return SOFT_TIMER_OK;
}
else
{
return NOT_OK;
}
}
/*********************************************************
** 函數(shù)名稱: SoftTimerStop
** 功能描述: 停止一個(gè)正在運(yùn)行的軟定時(shí)器
** 輸 入: Index:軟定時(shí)器的索引
** 輸 出: NOT_OK:軟定時(shí)器不存在
** SOFT_TIMER_OK:操作成功
** 全局變量: SoftTimerData
** 調(diào)用模塊: OS_ENTER_CRITICAL(),OS_EXIT_CRITICAL()
************************************************************/
uint8 SoftTimerStop(uint8 Index)
{
#if EN_SOFT_TIMER_CHK > 0
if (Index >= MAX_SOFT_TIMER)
{
return NOT_OK;
}
#endif
OS_ENTER_CRITICAL();
SoftTimerData[Index].DelayTime = 0;
SoftTimerData[Index].Fuction = NULL;
SoftTimerData[Index].Falg &=
~(SOFT_TIMER_TIMER_OUT | SOFT_TIMER_TIMER_RUN);
OS_EXIT_CRITICAL();
return SOFT_TIMER_OK;
}
/***************軟定時(shí)器任務(wù)***************************************/
/****************************************************************
** 函數(shù)名稱: SoftTimer
** 功能描述: 軟定時(shí)器管理任務(wù)
***************************************************************/
void SoftTimer(void)
{
uint16 ThisDelay;
uint8 i;
SoftTimerCnt = 0;
while (1)
{
OS_ENTER_CRITICAL();
// 找到定時(shí)最短的定時(shí)器
ThisDelay = -1;
for (i = 0; i< MAX_SOFT_TIMER; i++)
{
if (SoftTimerData[i].DelayTime != 0 &&
SoftTimerData[i].DelayTime < ThisDelay)
{
ThisDelay = SoftTimerData[i].DelayTime;
}
}
// 計(jì)算等待時(shí)間
if (ThisDelay > -SoftTimerCnt)
{
SoftTimerCnt += ThisDelay;
}
else
{
SoftTimerCnt = 1;
}
SoftTimerThisDelay = ThisDelay;
OSWait(K_SIG,0);
ThisDelay = SoftTimerThisDelay;
// 查詢定時(shí)到的軟定時(shí)器
for (i = 0; i < MAX_SOFT_TIMER; i++)
{
SoftTimerData[i].Falg &= ~SOFT_TIMER_TIMER_OUT;
if (SoftTimerData[i].DelayTime != 0)
{
if (SoftTimerData[i].DelayTime <= ThisDelay)
{
SoftTimerData[i].DelayTime = 0;
if (SoftTimerData[i].Fuction != NULL)
{
SoftTimerData[i].Falg |= SOFT_TIMER_TIMER_OUT;
}
}
else
{
SoftTimerData[i].DelayTime -= ThisDelay;
}
}
}
SoftTimerThisDelay = 0;
OS_EXIT_CRITICAL();
// 執(zhí)行軟定時(shí)器指定的任務(wù)
for (i = 0; i < MAX_SOFT_TIMER; i++)
{
if (((SoftTimerData[i].Falg & SOFT_TIMER_TIMER_OUT) != 0) &&
(SoftTimerData[i].Fuction != NULL))
{
SoftTimerData[i].Falg &= ~SOFT_TIMER_TIMER_OUT;
SoftTimerData[i].Fuction();
}
}
}
}
#endif
五.實(shí)驗(yàn)例程簡析
本軟件定時(shí)器所使用的存儲空間由程序自己分配,并通過一個(gè)唯一的索引(即序號)
來表示每一個(gè)軟定時(shí)器。由于軟定時(shí)器執(zhí)行的任務(wù)時(shí)間等因素不確定,所以一般把這個(gè)任務(wù)
優(yōu)先級定得比較低(表示任務(wù)的優(yōu)先權(quán)越高)。
要使用軟定時(shí)器模塊,首先需要初始化軟定時(shí)器模塊。這是由調(diào)用函數(shù)InitSoftTimer( )
實(shí)現(xiàn)的。初始化后,就可以調(diào)用函數(shù)SoftTimerRun( )來運(yùn)行一個(gè)軟定時(shí)器,或是調(diào)用函數(shù)
SoftTimerStop( )來停止一個(gè)定時(shí)器。
在模塊初始化之后,任務(wù)就可以調(diào)用函數(shù)SoftTimerRun( )運(yùn)行一個(gè)軟定時(shí)器。
SoftTimerRun9( )有三個(gè)參數(shù)。第一個(gè)參數(shù)Index 用來指示使用的軟定時(shí)器;第二個(gè)參數(shù)Delay
用來設(shè)置定時(shí)器運(yùn)行的時(shí)間,以系統(tǒng)時(shí)鐘節(jié)拍為單位,范圍大約是0~65000;第三個(gè)參數(shù)
Function 是一個(gè)函數(shù)指針,指向一個(gè)無參數(shù)、無返回值的函數(shù),當(dāng)軟定時(shí)器溢出時(shí)會調(diào)用這
個(gè)函數(shù)。圖5.1 為SoftTimerRun( )函數(shù)的偽流程圖。
為了提高程序的執(zhí)行效率,程序沒有使用讓每一個(gè)時(shí)鐘節(jié)拍將每一個(gè)軟定時(shí)器的計(jì)數(shù)
值都減1 的方法。這種方法雖然簡單易懂,但會大量消耗CPU 時(shí)間。而且,由于軟定時(shí)器
引入了不確定的函數(shù),為了避免這些不確定的函數(shù)對系統(tǒng)造成大的影響,軟定時(shí)器管理任務(wù)
的優(yōu)先級比較低。這樣,當(dāng)每個(gè)系統(tǒng)節(jié)拍都需要處理每一個(gè)軟件定時(shí)器時(shí),如果高優(yōu)先級的
任務(wù)運(yùn)行時(shí)間超過一個(gè)時(shí)鐘節(jié)拍,則軟定時(shí)器就會出現(xiàn)誤差,且誤差會積累。本程序使用一
個(gè)輔助減計(jì)數(shù)器來減少這些負(fù)面影響。軟定時(shí)器管理任務(wù)首先要查找這些軟定時(shí)器中等待時(shí)
間最短的,然后將它的等待值賦予輔助減計(jì)數(shù)器。輔助減計(jì)數(shù)器每個(gè)系統(tǒng)節(jié)拍都減一,且與
系統(tǒng)時(shí)鐘節(jié)拍處理函數(shù)一起執(zhí)行。當(dāng)輔助減計(jì)數(shù)器溢出時(shí)通知軟定時(shí)器管理任務(wù),軟定時(shí)器
管理任務(wù)再進(jìn)行其他處理。輔助減計(jì)數(shù)器的代碼見函數(shù)SoftTimerSum ( )。
圖5.2 為軟定時(shí)器處理任務(wù)的流程圖。
評論
查看更多