搜索
bottom↓
回复: 2

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

[复制链接]

出0入0汤圆

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

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


//   任务调度器数组
sTask SCH_tasks_G[SCH_MAX_TASKS];


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

void SCH_Init_T1(void)
{
   uint8_t  i;

   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[Index].pTask)
                        {
                //**********************************************************
             if (SCH_tasks_G[Index].Delay == 0)
            {
                  // 给可以被调度的任务设置标志位
                // 说明:任务运行标志位不具有存储功能,也就是说,如果在规定的
                //       间隔内没有被运行,则机会丧失
                SCH_tasks_G[Index].RunMe += 1;  // Inc. the 'Run Me' flag

                   if (SCH_tasks_G[Index].Period)//将任务需要的延时装入
                   {
                       SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
                }
             }
            //************************************************************
            else
             {
                    SCH_tasks_G[Index].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[Index].RunMe > 0)
      {
         (*SCH_tasks_G[Index].pTask)();  // 运行任务

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

         // 如果任务只要求运行一次,则删除任务
         if (SCH_tasks_G[Index].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[Index].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[Index].pTask  = pFunction;
     
   SCH_tasks_G[Index].Delay  = DELAY;
   SCH_tasks_G[Index].Period = PERIOD;

   SCH_tasks_G[Index].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[TASK_INDEX].pTask   = 0x0000;
   SCH_tasks_G[TASK_INDEX].Delay   = 0;
   SCH_tasks_G[TASK_INDEX].Period  = 0;

   SCH_tasks_G[TASK_INDEX].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 int  uint16_t;

#ifndef     TRUE

#define     FALSE         0
#define     TRUE         (!FALSE)

#endif

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

// 定义调度器数据结构
// 每一个任务消耗 7 bytes RAM
typedef  struct 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     主程序
extern  void LED_Flash_Update(void);               
extern  void 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();
               
               
        }
}
-*-------------------------------------------------------------*/

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2010-10-6 21:22:23 | 显示全部楼层
这是整个打包的源文件ourdev_587967O20RYN.rar(文件大小:82K) (原文件名:PIC调度测试.rar)

出0入0汤圆

发表于 2012-11-23 21:17:26 | 显示全部楼层
Thanks for sharing!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 04:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表