2010年2月18日 星期四

8051簡單多工4:中斷延時

這是基本延時功能,但要各組Task都可以使用。LED閃爍最常用了。
新加程式碼如下:
idata unsigned char Task_Delay_Count[TASK_NUM]={0,0,0,0};
void Dummy(void)
{
    return;
}

void Task_Delay_Next(void (*p_func)(void))
{
    TaskResumeFunc[FuncID]=p_func;
}

void Task_Delay_Ms(unsigned char n)
{
    if (! n ) n = 1;
    TaskFunc[FuncID] = Dummy; // to sleep
    Task_Delay_Count[FuncID] = n;
}

void Timer0_ISR (void) interrupt INTERRUPT_TIMER0
{
    unsigned char i;

    TL0  = 0x80;
    TH0  = 0x44; // set delay for 1 ms
    for ( i=0; i<TASK_NUM; i++)
    {
        if ( Task_Delay_Count[i] ) {
            Task_Delay_Count[i]--;
            if (! Task_Delay_Count[i]) TaskFunc[i]=TaskResumeFunc[i]; // wake up function
        }
    }
}

各函式功能說明:
Dummy()使用中斷延時,原本的函式就會用這個取代。
Task_Delay_Next()設定延時完畢後要執行的函式。
Task_Delay_Ms()設定延時時間。
Timer0_ISR()中斷程式。
大家可以比較一下和上篇的差異,其實主要的功能是一樣的,只是改由中斷做。

只有一個問題可能在使用時會遇到,那就是設定延時的變數Bee是用unsigned char,所以只能延時255ms。
因為Bee剛好就用這麼多,要加長就改一下變數型態就可以了。


3 則留言:

  1. Bee大大 您好
    請問如果idata unsigned char Task_Delay_Count[TASK_NUM]={0,0,0,0};
    改成16 bit idata unsigned short Task_Delay_Count[TASK_NUM]={0,0,0,0};
    那麼
    void Task_Delay_Ms(unsigned char n)
    {
    if (! n ) n = 1; TaskFunc[FuncID] = Dummy; // to sleep
    Task_Delay_Count[FuncID] = n;
    }
    須要改成
    void Task_Delay_Ms(unsigned char n)
    {
    if (! n ) n = 1;
    TaskFunc[FuncID] = Dummy; // to sleep
    EA=0;
    Task_Delay_Count[FuncID] = n;
    EA=1;
    } 嗎?
    謝謝!
    [版主回覆02/19/2010 12:22:56]沒錯,是要這樣改。我沒有注意到。
    不然low byte剛好是1,可能會產生問題。
    如果是compiler先填high byte還好,但這點不保證。還是保護起來會比較正常。

    回覆刪除
  2. 版主你好 最近正在學習你的簡單版RTOS 覺得收益良多 想請問說 timer作用是讓原本的執行續插入一個工作嗎?

    回覆刪除
    回覆
    1. 這個仍不算RTOS。這個timer只是移出執行,等時間到再移回來推入執行矩陣。

      刪除