历史上的今天
返回首页

历史上的今天

今天是:2025年03月06日(星期四)

正在发生

2018年03月06日 | 混合式调度器C51源代码和相关注释

2018-03-06 来源:eefocus

/*==============================================================
1ms时标 混合式调度器(一个抢占式任务,多个合作式任务)
作者:shadow.hu
===============================================================*/
#include
#define uchar  unsigned char
#define ushort unsigned short
#define SCH_MAX_TASKS 9
#define ERROR_SCH_TOO_MANY_TASKS  9
#define ERROR_SCH_CANOT_DELETE_TASK 0
#define RETURN_ERROR 0
#define RETURN_NORMAL 1

#define INTERRPT_Timer_2_Overflow 5

#define SCH_REPORT_ERRORS
#ifdef  SCH_REPORT_ERRORS
#define Error_Port P1
#endif

typedef data struct
{
    void (code *pTask)(void);
 ushort Delay;
 ushort Period;
 ushort RunMe;
 uchar  Co_op;//如果任务是合作式的,设置为1,如果任务是抢占式的,设置为0
}sTask;
sTask SCH_tasks_G[SCH_MAX_TASKS];

void SCH_Init_T2(void);
uchar SCH_Add_Task(void (code * pFunction)(),const ushort Delay,  ushort PERIOD);
//                      函数名指针                延时的时标数    执行任务的时间间隔
//                                                为0则立即执行  如果为0,表示单次任务  
 void SCH_Dispatch_Tasks(void);
void SCH_Start(void);
bit SCH_Delete_Task(const ushort TASK_INDEX);
void SCH_Go_To_Sleep(void);
void SCH_Report_Status(void);//报告系统状况
void LED_Flash_Init(void);
void LED_Flash_Update_A(void);
void LED_Flash_Update_B(void);
void LED_Flash_Update_C(void);
void LED_Flash_Update_D(void);
void LED_Flash_Update_E(void);
void LED_Flash_Update_F(void);
void LED_Flash_Update_G(void);
void LED_Flash_Update_H(void);

uchar Error_code_G = 0;//
statIC ushort Error_tick_count_G;//记住自从上一次纪录错误以来的时间
static uchar Last_error_code_G;//上次的错误代码(在1分钟之后复位)

uchar  LED_State_G_A = 0;
uchar  LED_State_G_B = 0;
uchar  LED_State_G_C = 0;
uchar  LED_State_G_D = 0;
uchar  LED_State_G_E = 0;
uchar  LED_State_G_F = 0;
uchar  LED_State_G_G = 0;
uchar  LED_State_G_H = 0;

sbit LED_PIN_A = P1^0;
sbit LED_pin_B = P1^1;
sbit LED_pin_C = P1^2;
sbit LED_pin_D = P1^3;
sbit LED_pin_E = P1^4;
sbit LED_pin_F = P1^5;
sbit LED_pin_G = P1^6;
sbit LED_pin_H = P1^7;

//Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
//Error_code_G = ERROR_SCH_WAITING_FOR_SLAVE_TO_ACK;
//Error_code_G = ERROR_SCH_WAITING_FOR_START_COMAND_FROM_MASTER;
//Error_code_G = ERROR_SCH_ONE_OR_MORE_SLAVES_DID_NOT_START;
//Error_code_G = ERROR_SCH_LOST_SLAVE;
//Error_code_G = ERROR_SCH_CAN_BUS_ERROR;
//Error_code_G = ERROR_I2C_WRITE_BYTE_AT24C64;

void main(void)
{
 SCH_Init_T2();
 LED_Flash_Init();
 SCH_Add_Task(LED_Flash_Update_A,0,1000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_B,0,2000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_C,0,3000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_D,0,4000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_E,0,5000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_F,0,6000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_G,0,7000);//添加一个任务
 SCH_Add_Task(LED_Flash_Update_H,0,8000);//添加一个任务

     SCH_Start();//开全局中断
 while(1)
 {
  SCH_Dispatch_Tasks();
 }
}
/*------------------------------------------------------------
 这是调度器的中断服务程序,初始化函数中的定时器设置决定了它
的调度频率,这个版本的调度器由定时器2触发中断,定时器自动重装。
-------------------------------------------------------------*/
void SCH_Update(void) interrupt INTERRPT_Timer_2_Overflow
{
 //刷新任务队列
 uchar Index;
 TF2 = 0;//必须手工清除
 //注意:计算单位为时标(不是毫秒)
 for(Index = 0;Index < SCH_MAX_TASKS;Index++)
 {  //检测这里是否有任务
  if(SCH_tasks_G[Index].pTask)
  {  
  if(SCH_tasks_G[Index].Delay == 0)
  {
    //任务需要运行,间隔的时间已经到了
    if(SCH_tasks_G[Index].Co_op)
    {
    //如果是合作式任务,RunMe标志加1
    SCH_tasks_G[Index].RunMe += 1;//要执行任务的标志加1
    }
    else//如果它是抢占式任务,立即运行它
    {
    (*SCH_tasks_G[Index].pTask)();//运行任务
    SCH_tasks_G[Index].RunMe -= 1;
    //周期性的任务将自动再次运行,单次任务就删除
    if(SCH_tasks_G[Index].Period == 0)
    {
      SCH_tasks_G[Index].pTask = 0;
    }
    }    
    if(SCH_tasks_G[Index].Period)//时标间隔不等于0
    {
    //调度周期性的任务再次运行,每隔这个固定的时标长度执行一次任务
    SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
    }
  }
  else //任务有延迟执行要求,还没到达延迟的时间
  {
    //还没有准备好运行,延迟减1
    SCH_tasks_G[Index].Delay -= 1;
  }
  }
 }
}

    void SCH_Init_T2(void)
{
    uchar i;
 for(i=0;i {
  SCH_Delete_Task(i);
 }
 Error_code_G = 0;
 T2CON = 0x04;
 TMOD = 0x00;
 TH2  = 0xfc;
 RCAP2H = 0xfc;
 TL2  = 0x18;
 RCAP2L = 0x18;
 ET2  = 1;
 TR2  = 1;
}
/*----------------------------------------------------------------------------
任务函数每隔一定时间间隔或在用户定义的延迟之后运行
pFunction -- 将被调用的函数名称。注意:被调函数必须是“void void”型
DELAY    -- 在任务第一次被执行之前的间隔
PERIOD    -- 如果它为0,则只调用该函数一次,由DELAY确定其调用的时间
            如果非0,那么它就是被重复调用的时间间隔
Co_op    -- 如果是合作式任务则设置为1,如果是抢占式任务则设置为0.

    注意:如果以后要删除任务,将需要返回值
例子:
Task_ID = SCH_Add_Task(Do_X,1000,0,0);
使函数Do_X()在1000个调度器时标之后运行一次(抢占式任务) 
Task_ID = SCH_Add_Task(Do_X,0,1000,1);
使函数Do_X()每隔1000个调度器时标运行一次(合作式任务)
Task_ID = SCH_Add_Task(Do_X,300,1000,0);
使函数Do_X()每隔1000个调度器时标运行一次,任务首先在T=300个时标时被执行
  然后是1300个时标.........(抢占式任务)

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

uchar SCH_Add_Task(void (code * pFunction)(),const ushort DELAY, ushort PERIOD,bit Co_op)
{
 uchar Index = 0;
 //首先在队列中找到一个空隙(如果有的话,否则就不添加新任务)
 while((SCH_tasks_G[Index].pTask != 0)&&(Index < SCH_MAX_TASKS))
 {
  Index++;//当一个新任务被添加,且没有超过任务上限
 }
 //是否达到任务队列的结尾?
 if(Index == SCH_MAX_TASKS)//任务数量达到上限
 {
  Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
  return SCH_MAX_TASKS;//直接返回,不添加这个新任务
 }
 //如果能运行到这里,说明任务队列中有空隙,添加任务。
 SCH_tasks_G[Index].pTask = pFunction;
 SCH_tasks_G[Index].Delay = DELAY;
 SCH_tasks_G[Index].Period = PERIOD;
 SCH_tasks_G[Index].Co_op = Co_op;
 SCH_tasks_G[Index].RunMe  = 0;
 return Index;//返回任务的位置(以便以后删除)
}


     

    void SCH_Dispatch_Tasks(void)
{
 uchar Index;
 //调度(运行)下一个任务(如果有任务就绪)
 for(Index = 0;Index < SCH_MAX_TASKS;Index++)
 {
  //只调度合作式任务
  if((SCH_tasks_G[Index].RunMe > 0)&&(SCH_tasks_G[Index].Co_op))
  {
   (*SCH_tasks_G[Index].pTask)();//执行任务
   SCH_tasks_G[Index].RunMe -= 1;//清除任务需要执行的标志
  }
  //如果这是个“单次”任务,将它从队列中删除
  if(SCH_tasks_G[Index].Period == 0)
  {
   SCH_tasks_G[Index].pTask = 0;// 比通过调用来删除任务更快SCH_Delete_Task(Index);
  }
 }
 SCH_Report_Status();//报告系统状况
 SCH_Go_To_Sleep();
}

    void SCH_Start(void)
{
 EA = 1;
}

    bit SCH_Delete_Task(const ushort TASK_INDEX)
{
 bit Return_code;
 if(SCH_tasks_G[TASK_INDEX].pTask == 0)
 {
  //这里没有任务。。。设置全局错误变量
  Error_code_G = ERROR_SCH_CANOT_DELETE_TASK;
  Return_code = RETURN_ERROR;//返回错误代码
 }
 else
 {
  Return_code = RETURN_NORMAL;
 }
 //删除任务
 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 Return_code;
}

    void SCH_Go_To_Sleep()
{
 PCON |= 0x01;//进入休眠模式
}

    void SCH_Report_Status(void)
{
/* #ifdef SCH_REPORT_ERRORS
 if(Error_code_G != Last_error_code_G)
 {
  Error_Port = 255 - Error_code_G;
  Last_error_code_G = Error_code_G;
  if(Error_code_G != 0)
  {
   Error_tICk_count_G = 60000;
  }
  else
  {
   Error_tick_count_G = 0;
  }
 }
 else
 {
  if(Error_tick_count_G != 0)
  {
   if(--Error_count_G == 0)
   {
    Error_code_G = 0;
   }
  }
 }
 #endif    */
}

    void LED_Flash_Update_A(void)
{
 if(LED_State_G_A == 1)
 {
  LED_State_G_A = 0;
  LED_PIN_A = 0;
 }
 else
 {
  LED_State_G_A = 1;
  LED_pin_A = 1;
 }
}

    void LED_Flash_Update_B(void)
{
 if(LED_State_G_B == 1)
 {
  LED_State_G_B = 0;
  LED_pin_B = 0;
 }
 else

{
  LED_State_G_B = 1;
  LED_PIN_B = 1;
 }
}


     

    void LED_Flash_Update_C(void)
{
 if(LED_State_G_C == 1)
 {
  LED_State_G_C = 0;
  LED_pin_C = 0;
 }
 else
 {
  LED_State_G_C = 1;
  LED_pin_C = 1;
 }
}
void LED_Flash_Update_D(void)
{
 if(LED_State_G_D == 1)
 {
  LED_State_G_D = 0;
  LED_pin_D = 0;
 }
 else
 {
  LED_State_G_D = 1;
  LED_pin_D = 1;
 }
}
void LED_Flash_Update_E(void)
{
 if(LED_State_G_E == 1)
 {
  LED_State_G_E = 0;
  LED_pin_E = 0;
 }
 else
 {
  LED_State_G_E = 1;
  LED_pin_E = 1;
 }
}
void LED_Flash_Update_F(void)
{
 if(LED_State_G_F == 1)
 {
  LED_State_G_F = 0;
  LED_pin_F = 0;
 }
 else
 {
  LED_State_G_F = 1;
  LED_pin_F = 1;
 }
}
void LED_Flash_Update_G(void)
{
 if(LED_State_G_G == 1)
 {
  LED_State_G_G = 0;
  LED_pin_G = 0;
 }
 else
 {
  LED_State_G_G = 1;
  LED_pin_G = 1;
 }
}
void LED_Flash_Update_H(void)
{
 if(LED_State_G_H == 1)
 {
  LED_State_G_H = 0;
  LED_pin_H = 0;
 }
 else
 {
  LED_State_G_H = 1;
  LED_pin_H = 1;
 }
}

    void LED_Flash_Init(void)
{
 LED_State_G_A= 0;//初始化LED状态
 LED_State_G_B= 0;//初始化LED状态
 LED_State_G_C= 0;//初始化LED状态
}


推荐阅读

史海拾趣

East Texas Integrated Circuits公司的发展小趣事

随着市场的不断扩大,ETIC意识到必须不断提升自身的研发实力才能保持竞争优势。因此,公司加大了对研发的投入,引进了一批高端人才和先进的研发设备。同时,ETIC还积极与国内外高校和研究机构开展合作,共同开展前沿技术的研究和开发。这些努力使ETIC在集成电路领域的技术实力得到了显著提升。

Dean Technology公司的发展小趣事

Dean Technology公司起源于上世纪80年代,当时电子行业正经历着飞速的发展。创始人凭借其深厚的电子技术背景和敏锐的市场洞察力,决定进入高压二极管领域。他带领研发团队不断攻克技术难题,成功推出了一系列性能稳定、品质可靠的高压二极管产品,奠定了公司在行业中的技术领先地位。

Densei-Lambda (TDK)公司的发展小趣事

近年来,随着电子行业的快速发展和市场竞争的加剧,Dean Technology公司也面临着前所未有的挑战。为了应对这些挑战,公司积极调整战略方向,加强内部管理和团队建设。同时,他们还密切关注行业趋势和市场需求的变化,及时调整产品结构和市场策略。这些努力使得Dean Technology在应对行业变革和挑战时更加从容和自信。

请注意,以上故事是基于对Dean Technology公司一般情况的了解而编写的,可能不完全符合公司的实际发展历程。如需更详细的信息,请查阅相关资料或联系公司官方渠道。

Altus Technology Inc公司的发展小趣事

Altus深知人才是企业发展的根本。因此,公司一直注重人才培养和引进工作。通过建立完善的培训体系和激励机制,Altus吸引了大量优秀人才加入公司,并为他们提供了广阔的发展空间和职业晋升机会。这些人才在公司的各个岗位上发挥着重要作用,推动了公司的技术创新和市场拓展。同时,Altus还注重员工的福利待遇和文化建设,营造了积极向上、团结和谐的工作氛围。

Belden Wire and Cable公司的发展小趣事

随着全球化的深入发展,Belden公司开始积极拓展国际市场。通过在全球范围内设立分支机构和工厂,百通不仅提升了自身的产能和效率,也更好地满足了全球客户的需求。同时,公司还不断推出新产品和新技术,拓展在工控线缆、音视频线缆和计算机网络等领域的市场份额。如今,Belden已经成为全球最大的综合布线及专业线缆制造商之一,其产品和服务遍布全球各地。

这五个故事只是Belden Wire and Cable公司发展历程中的一部分,但它们都客观地反映了公司在电子行业里不断发展、创新和壮大的事实。通过这些故事,我们可以看到一个企业通过不断创新和拓展市场,逐渐成长为行业领导者的过程。

Advanced_Linear_Devices_Inc.公司的发展小趣事

随着市场需求的不断增长,ALD不断拓展其产品线。除了最初的CMOS线性集成电路外,公司还研发出了轨到轨运算放大器、双斜率A/D前端转换器、电压比较器等一系列产品。这些产品不仅满足了不同行业的需求,还进一步提升了ALD在电子行业的市场地位。同时,公司还针对特定应用,如医疗仪器和汽车领域,推出了定制化的解决方案,赢得了客户的广泛赞誉。

问答坊 | AI 解惑

超声波模块+红外遥控资料

本帖最后由 paulhyde 于 2014-9-15 04:00 编辑 1超声波测距已通过实物测试 2专门针对SMK1838遥控接收头的红外遥控装置  …

查看全部问答>

刚才把开发板单片机的串口烧了,郁闷!

单片机(STC89C52)VCC是5V, GPS(MTK M89)VCC是4.3V RXD连TXD,TXD连RXD 用万用表量的时候GPS的串口是4.8V,GPS的是3.6V 不知道怎么的就烧了?为什么没接串口之前MCU的RXD、TXD都有4.8的电压? 小弟刚入门还请指点迷经,要怎么联才可以让MCU读到GPS ...…

查看全部问答>

Freescale的单片机RTI的一个问题

   实时中断定时0.625ms,难道是中断的时间太快了?怎么For里面的循环都没有执行了呢?    现在想明白的就是一个问题,在进入中断响应的处理过程中,定时器是不是还在定时?我感觉应该在退出响应之后才可以,要不然,如果响应 ...…

查看全部问答>

wince系统下 compact framework程序崩溃的求救

我的wince系统,已经按照过compact framwork 2.0 ,期间运行 dotnet 程序都很正常(程序比较经常读写文件)。大约持续运行1个月后,dotnet程序无法启动,报异常。而且我用任意一个dotnet程序都是出现这个异常。怀疑系统中产生了什么异常。具体不明 ...…

查看全部问答>

请问:什么叫上位机,下位机啊,它们是干什么用的啊?

什么叫上位机,下位机啊,它们是干什么用的啊?…

查看全部问答>

IR new ic Rugged AEC-Q100 Qualified 600V ICs

IR Introduces Family of Rugged AEC-Q100 Qualified 600V ICs for Energy-Efficient Automotive Gate Drive Applications International Rectifier has launched a family of rugged 600V ICs for energy-efficient automotive ga ...…

查看全部问答>

请教城主一个MCO的问题,你以前回复的帖子!

版主发表于 2010-8-24 17:44 | 只看该作者 回复 引用 评分 报告 返回版面 TOP   得分:0…

查看全部问答>

菜鸟求组用CCS设置PWM的问题

用16F690做一个PWM信号的项目,但是总是不出来PWM信号,程序如下 #include #use delay(clock = 12000000) #fuses HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,MCLR #use fixed_io(c_outputs = PIN_C4,PIN_C6, PIN_C7) void main(void) { setup_ ...…

查看全部问答>

AD620双级放大电路

本系统要采集的信号十分微弱,5~100uV,设计电路要放大40000倍。由于AD620放大倍数越大,误差就越大,故本电路用了两片AD620形成二级放大。其中U1放大100倍,U2放大10倍。图中IN1,IN2为经过差分放大后的信号,输入到U1。U1放大后形成一路信号输入到U ...…

查看全部问答>