lichuangze 发表于 2010-10-6 21:21:23

PIC16F877A 基于时间调度实现两个任务(LED灯闪烁)

首先感谢greatsnows,看了greatsnows将时间调度器内核移植到AVR,而我一直使用的是PIC系列单片机,因此也把greatsnows作者的代码给移植到PIC16F877A上,但是不知到哪儿出问题,时间调度器死活不进行任务调度,只有一个LED灯可以闪烁,望高手给指点下,呵呵,先说声谢谢了
开发环境MPLAB8.53 + (HT)PICC 9.71a
/*-----------------------------SCH.c--------------------------*-
#include "MySch.h"

/////////////////////////////////////////////////////////////////////////////
//SCH调度器内核函数


//   任务调度器数组
sTask SCH_tasks_G;


/*
***********************************************
*void SCH_Init_T0(void)
***********************************************
*/

void SCH_Init_T1(void)
{
   uint8_ti;

   for (i = 0; i < SCH_MAX_TASKS; i++)
      {
                SCH_Delete_Task(i);
      }

   T1CON = 0x08;//Set the internal OSC as the timer1 source
   TMR1H = 0xD8;//Load the timer1's high and low register
   TMR1L = 0xF0;
   TMR1IF = 0; //Clear the Timer1 flag
   TMR1IE = 1; //Enable the Timer1
   TMR1ON = 1; //Start the Timer1

}



/*
************************************************
*void SCH_Start(void)
***********************************************
*/
void SCH_Start(void)
{
          PEIE = 1; //开启外设中断
        GIE = 1; //开启全局中断
}

/*
************************************************************
*
* void SCH_Update(void) interrupt INTERRUPT_Timer_0_Overflow
*
*************************************************************
*/
static void interrupt ISR(void)       
{        if(TMR1IF == 1)
        {
          uint8_t Index;

          TMR1IF = 0; // Have to manually clear this.
          TMR1ON = 0;

               // PIC16F877A, 4 MHz
                   TMR1H= 0xD8;
                   TMR1L= 0xF0;

                   //Start Timer 0
                   TMR1ON= 1;

        // NOTE: calculations are in *TICKS* (not milliseconds)
                for (Index = 0; Index < SCH_MAX_TASKS; Index++)
                {
                // Check if there is a task at this location
                if (SCH_tasks_G.pTask)
                        {
                //**********************************************************
             if (SCH_tasks_G.Delay == 0)
            {
                  // 给可以被调度的任务设置标志位
                // 说明:任务运行标志位不具有存储功能,也就是说,如果在规定的
                //       间隔内没有被运行,则机会丧失
                SCH_tasks_G.RunMe += 1;// Inc. the 'Run Me' flag

                   if (SCH_tasks_G.Period)//将任务需要的延时装入
                   {
                     SCH_tasks_G.Delay = SCH_tasks_G.Period;
                }
             }
            //************************************************************
            else
             {
                  SCH_tasks_G.Delay -= 1;//延时-1
             }
            //************************************************************            
      }
   }   
}
}

/*
********************************************************************************************************
*   
*                           任务调度器内核
*
********************************************************************************************************
*/


/*
************************************************************
*
* void SCH_RUN_Tasks(void)
*
************************************************************
*/
void SCH_RUN_Tasks(void)
{
   uint8_t Index;

   // 调度器调度任务
   for (Index = 0; Index < SCH_MAX_TASKS; Index++)
   {
      if (SCH_tasks_G.RunMe > 0)
      {
         (*SCH_tasks_G.pTask)();// 运行任务

         SCH_tasks_G.RunMe -= 1;// 清除任务标志位

         // 如果任务只要求运行一次,则删除任务
         if (SCH_tasks_G.Period == 0)
         {
            SCH_Delete_Task(Index);
         }
      }
   }
}

/*
************************************************************
*
*   uchar SCH_Add_Task
*
*************************************************************
*/
uint8_t SCH_Add_Task(void (*pFunction)(void),
                  uint16_t DELAY,
                  uint16_t PERIOD)   
{
   uint8_t Index = 0;
   
   while ((SCH_tasks_G.pTask != 0) && (Index < SCH_MAX_TASKS))
   {
      Index++;                                       
   }
   
   // Have we reached the end of the list?   
   if (Index == SCH_MAX_TASKS)
   {
      // Task list is full
      
      return SCH_MAX_TASKS;
    }
      
   // If we're here, there is a space in the task array
   SCH_tasks_G.pTask= pFunction;
   
   SCH_tasks_G.Delay= DELAY;
   SCH_tasks_G.Period = PERIOD;

   SCH_tasks_G.RunMe= 0;

   return Index; // return position of task (to allow later deletion)
}

/*
************************************************************
*
*   uint8_t SCH_Delete_Task(const uchar TASK_INDEX)
*
*************************************************************
*/
uint8_t SCH_Delete_Task( uint8_t TASK_INDEX)
{
   SCH_tasks_G.pTask   = 0x0000;
   SCH_tasks_G.Delay   = 0;
   SCH_tasks_G.Period= 0;

   SCH_tasks_G.RunMe   = 0;

   return 0;       // return status
}

-*----------------------------------------------------*/

/*------------------------MySch.h-----------------------------------/
//MySch.h : header file for the MySch project
//
#ifndef _MySch_
#define _MySch_
#endif

//#define __MCU_CLOCK_FREQUENCY__ _8.0000_MHz

#include <htc.h>

typedef unsigned char uint8_t;
typedef unsigned intuint16_t;

#ifndef   TRUE

#define   FALSE         0
#define   TRUE         (!FALSE)

#endif

#define RETURN_NORMAL             0
#define RETURN_ERROR            1
///////////////////////////////////////////////////
//函数声明和任务结构体定义

// 定义调度器数据结构
// 每一个任务消耗 7 bytes RAM
typedefstruct data
   {
   //定义函数类型指针,const关键字意思是这是一个指向flash的指针
   void (*pTask)(void);

    volatile uint16_t Delay;      // 任务第一次被执行前的延迟时间,如果为0则立即执行
   
   
    volatile uint16_t Period;   // 任务的执行间隔时间,如果为0,则只执行一次

   

    volatile uint8_t RunMe;                // 任务执行标志为,1 等待执行,0 不需要执行
   
} sTask;                                 //sTask是结构体变量




// 调度器内核
// 本文件所有函数
//*****************************************************
void SCH_Init_T1(void);
void SCH_Start(void);
// 调度器对外部接口
void SCH_RUN_Tasks(void);
uint8_t SCH_Add_Task(void (*pFunction)(void),
                   uint16_t DELAY,
                   uint16_t PERIOD);
uint8_t SCH_Delete_Task(uint8_t TASK_INDEX);




// 调度器支持的任务个数,用户在调用调度器的时候必须设置
#define SCH_MAX_TASKS               2
-*--------------------------------------------------------------*/


/*--------------------------------PIC_PIC16F877A-----------------

#ifndef _PIC_PIC16F877A_
#define _PIC_PIC16F877A_
#endif

#include<htc.h>

// Misc #defines
//#define LED_ON sbi(PORTB,0)
//#define LED_OFF cbi(PORTB,0)
//#define LED_ON1 sbi(PORTB,1)
//#define LED_OFF1 cbi(PORTB,1)

#define LED_ON   PORTD |= (1 << RD7)
#define LED_OFF    PORTD &= ~(1 << RD7)
#define LED_ON1    PORTD |= (1 << RD6)
#define LED_OFF1   PORTD &= ~(1 << RD6)
-*----------------------------------------------*/

/*------------------------------LED_FLASH.c-------------------------
#include "PIC_PIC16F877A.h"
#include "MySch.h"

// ------ Private variable definitions -----------------------------

static uint8_t LED_state_G;
static uint8_t LED_state_G1;
/*------------------------------------------------------------------*-

LED_Flash_Init()

-*------------------------------------------------------------------*/
void LED_Flash_Init(void)
   {
   LED_state_G = 0;
   LED_state_G1 = 0;
   }


void LED_Flash_Update(void)
   {
   // Change the LED from OFF to ON (or vice versa)
   if (LED_state_G == 1)
      {
      LED_state_G = 0;
      LED_OFF;
      }
   else
      {
      LED_state_G = 1;
      LED_ON;
      }
   }
   
void LED_Flash_Update1(void)
   {
   // Change the LED from OFF to ON (or vice versa)
   if (LED_state_G1 == 1)
      {
      LED_state_G1 = 0;
      LED_ON1;
      }
   else
      {
      LED_state_G1 = 1;
      LED_OFF1;
      }
   }
-*-----------------------------------------------------------------*/
/*----------------------------MySch.c---------------------------

#include "MySch.h"

/////////////////////////////////////////////////////////////////////////////
//MySch   主程序
externvoid LED_Flash_Update(void);               
externvoid LED_Flash_Update1(void);               
extern void LED_Flash_Init(void);       

static void io_init(void)
{
        // PortC
        PORTC = 0x00;
        TRISC = 0x00;
        // PortD
        PORTD = 0x00;//初始时灯灭
        TRISD = 0x00;//端口设置成输出
}

int main(void)
{
       
        io_init();

        SCH_Init_T1();
        LED_Flash_Init();                                                        //用于闪灯,实际中可代替
        SCH_Add_Task(LED_Flash_Update, 0, 500);        //用于闪灯,实际中可代替LED_Flash_Update
        SCH_Add_Task(LED_Flash_Update1, 10, 500);
        SCH_Start();
       
        while(1)
        {
                SCH_RUN_Tasks();
               
               
        }
}
-*-------------------------------------------------------------*/

以上是我移植修改后的源程序!

lichuangze 发表于 2010-10-6 21:22:23

这是整个打包的源文件ourdev_587967O20RYN.rar(文件大小:82K) (原文件名:PIC调度测试.rar)

depv 发表于 2012-11-23 21:17:26

Thanks for sharing!
页: [1]
查看完整版本: PIC16F877A 基于时间调度实现两个任务(LED灯闪烁)