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();
}
}
-*-------------------------------------------------------------*/
以上是我移植修改后的源程序! 这是整个打包的源文件ourdev_587967O20RYN.rar(文件大小:82K) (原文件名:PIC调度测试.rar) Thanks for sharing!
页:
[1]