论坛风格切换切换到宽版
  • 4792阅读
  • 2回复

写了个基于时间轮片和优先级抢断的PIC16类初级操系统作内核 [复制链接]

上一主题 下一主题
离线XLDZZ
 
发帖
443
只看楼主 倒序阅读 0楼 发表于: 2011-10-31
其实就是不让单片机死循环,让1khz的中断去扫描各个任务

程序没有写完 也没测试 只是让大家看看思路对不对

是否可行

理论上这种结构比死循环的结构实时性和稳定性要好


#include<pic.h>
__config(0x3b32);

//**************************************************
//         key定义
//**************************************************
#define uchar unsigned char         //无符号字符数据声明
#define uint unsigned int         //无符号整形数据声明              
#define s1   rc4               //key1
#define s2   rc5               //key2
#define cw   rb1               //drv cw
#define ccw   rb2               //drv ccw
#define out1 rb3               //ext control1
#define out2 rb4               //ext control2
#define short rb0               //short signal input
#define ck   rb5               //clock dida output
const uchar table[]={0xd7,0x12,0xcb,0x5b,0x1e,0x5d,0xdd,0x13,0xdf,0x5f};
//**************************************************
//         任务调度标记
//**************************************************
volatile static uchar ad_flag;       //ad标记
volatile static uchar tmr1_flag;     //tm1标记
volatile static uchar disp_flag;     //disp标记
volatile static uchar short_flag;     //short标记
//**************************************************
//       内核调度标记
//**************************************************
volatile static uchar core_flag;     //内核调度标记
volatile static uchar task_flag;     //任务标记
volatile static uchar task_level;     //内核优先级标记

volatile static uchar h;           //定时器1高位值
volatile static uchar l;           //定时器1低位值
volatile static uint data_temp;
//***************************************************
//         变量声明
//***************************************************
uint ad_val;                   //瞬态值
long ad_ave;                   //平均值
uchar bai;                     //百位
uchar shi;                     //十位
uchar ge;                     //个位

//***************************************************
//         函数声明
//***************************************************
void dsp(uchar num1,uchar num2,uchar num3);
void io_init();                 //io初始化函数
void ext_init();               //外设初始化函数
void int_init();               //中断初始化函数
void delay(uint x);             //软件延时函数
uint task_ad();
void task_disp();
void task_nc();
void task_out();
void task_key();
void task_setp();
void task_cw();
void task_ccw();


main()
{
io_init();
ext_init();
int_init();
aa:
while(!s1);
delay(10);
if(s1)
  {
  goto ab;
  }
else
  {
  goto aa;
  }
ab:
  tmr1on=1;             //open time1 power
  adgo=1;               //open ad converter switch
  while(1)
  {
begin:  
      if(task_flag!=0)       //动态内核队列
      {
           if(task_level=((task_flag&0x80)>>7))
            {
            core_flag=0x01;
            goto core_process;
            }
           else if(task_level=((task_flag&0x40)>>6))
            {
            core_flag=0x02;
            goto core_process;
            }
           else if(task_level=((task_flag&0x20)>>5))
            {
            core_flag=0x03;
            goto core_process;
            }
           else if(task_level=((task_flag&0x10)>>4))
            {
            core_flag=0x04;
            goto core_process;
            }
           else if(task_level=((task_flag&0x08)>>3))
            {
            core_flag=0x05;
            goto core_process;
            }
           else if(task_level=((task_flag&0x04)>>2))
            {
            core_flag=0x06;
            goto core_process;
            }
           else
            {
            core_flag=0xff;
            goto begin;
            }
      }                           //end if
core_process:
      if(core_flag!=0)
      {
        switch(core_flag)               //t1
        {
            case 0x01:                 //内核任务扫描
              {
                  uchar disp_t;
                  uchar nc_t;
        uchar key_t;
        uchar short_t;
                  if(disp_t!=0)             //disp基准100hz
                  {
                    disp_t=disp_t--;
                    if(disp_t==0)
                    {
                        disp_t=0x0a;
                        task_flag=task_flag|0x08;   //队列3
                       }
                  }
                  else
                  {
                    disp_t=0x0a;
                  }
                 
                  if(nc_t!=0)               //nc时间基准
                  {
                    nc_t=nc_t--;
                    if(nc_t==0)
                    {
                        nc_t=0x0b;
                        task_flag=task_flag|0x10;   //任务队列4
                       }
                    }
                  else
                  {
                    nc_t=0x0b;
                  }
                 
                  if(key_t!=0)               //key时间基准
                  {
                    key_t=key_t--;
                    if(nc_t==0)
                    {
                        key_t=0x0f;
                        task_flag=task_flag|0x04;   //任务队列5
                       }
                    }
                  else
                  {
                    key_t=0x0f;
                  }      
             
                  if(short_t!=0)             //short时间基准
                  {
                    short_t=short_t--;
                    if(short_t==0)
                    {
                        short_t=0x09;
                        task_flag=task_flag|0x20;   //任务队列6
                       }
                  }
                  else
                  {
                    short_t=0x09;
                  }
                 task_flag=task_flag&0x7f;       //任务结束标记
            }
            break;
            case 0x02:                   //ad
              {
              uchar k;
        long ad_temp;
        long shi_temp;
        long ge_temp;
                  ad_val=task_ad();
                  if(k!=0)
                  {
                    ad_ave=ad_ave+ad_val;
          k--;
                    }
                  else
                  {
                    k=49;
                    ad_temp=ad_ave*1000; //数据转换
          ad_temp=ad_temp/50;
                    bai=ad_temp/1000;
          shi_temp=ad_temp%1000;
          shi=shi_temp/100;
                    ge_temp=ad_temp%100;
          ge=ge_temp/10;
                    ad_ave=0;
                    ad_val=0;
                  }
                 task_flag=task_flag&0xbf; //任务结束标记
              }
            break;
            case 0x03:             //short task
              {
              uchar i;
                 if(short)
                  {
                    i++;
                    if(i==2)
                    {
                        short_flag=1;
                        i=0;
                       }
                    else
                    {
                        short_flag=0;
                       }
                  }
                 else
                  {
                  i=0;
                  }
                 
              }
            break;
            case 0x04:             //nc
              {
              if(short_flag)
                  {
                  task_cw();
                  }
          else
                  {
                  task_ccw();
                  }
              }
            break;


            default:
      {
        nop();
      }  
        }
    }
  }                             //end while
  }

void io_init()
{
trisa=0x01;
trisb=0x01;
trisc=0x30;
trisd=0;
trise=0;
porta=0;
portb=0;
portc=0;
portd=0;
porte=0;

}

void ext_init()
{
h=((0xc350&0xff00)>>8);
l=(0xc350&0xff);
tmr1h=h;
tmr1l=l;
t1con=0x04;         //定时器1 分频比1:1 关闭振荡器 内部时钟 tmr1on=0
adcon0=0x81;         //an1输入 分频比1/64 power up 右对齐
adcon1=0xce;
cmcon=0x07;         //关比较器
}

void int_init()
{
gie=1;             //启用全局中断
peie=1;           //启用外设中断
adie=1;           //启用ad中断
tmr1ie=1;           //启用ti中断
tmr1if=0;           //t1标记清零
adif=0;           //ad标记清零
}

void sc()//数据所存
{
porte=0;
delay(2);
porte=0x06;
delay(2);
porte=0;
delay(2);
}

uint task_ad()
{
  uint adval_l,adval_h,adval_temp;
  float adval;
  adval_l=adresl;
  adval_h=adresh;
  adval_temp=((adval_h<<8)|adval_l);
  adval=adval_temp/1023*5.0;
  adval=adval*1000;
  return (adval);
}

void delay(uint x)//延时程序
{
  uint a,b;
  for(a=x;a>0;a--)      
  for(b=110;b>0;b--);      
  }

void dsp(uchar num1,uchar num2,uchar num3)
     {
      portb=table[num1];//显示第一个数码管
      portd=0x04;
      sc();
      delay(2);
      portb=table[num2];//显示第二个数码管
      portd=0x02;
      sc();
      delay(2);
      portb=table[num3];//显示第三个数码管
      portd=0x01;
      sc();
      delay(2);
     }

void task_cw()
{
cw=0;
ccw=1;
delay(10);
cw=1;
}
void task_ccw()
{
cw=1;
ccw=0;
delay(10);
ccw=1;
}
 


void interrupt di()//中断处理
{
if(adif)           //ad_flag创建
  {
  adif=0;
  task_flag=((1<<6)&0x40);
  }
else
  {
  adif=0;
  }
//========================================
if(tmr1if)
  {
  tmr1if=0;
     task_flag=((1<<7)&0x80);
     tmr1on=0;
     tmr1h=h;
     tmr1l=l;
     tmr1_flag=1;
     nop();
     nop();
     tmr1on=1;
     }
else
  {
  tmr1if=0;
  }      
//=========================================
if(ck)
  {
  ck=0;
     }
else
  {
  ck=1;
     }

}
离线BG4RFF
发帖
1581
只看该作者 1楼 发表于: 2011-10-31
其实有本书好像叫《基于时间轮转的51.。。
那个讲的挺好的,程序结构好弄一些
avr和51的都有人写好的,移植也很简单的
离线bellstudio
发帖
2820
只看该作者 2楼 发表于: 2011-11-03
老的pic16无法弹出硬件栈,资源少,多是协作式的。典型的有salvo,osa
pic18以上用os合适些,具有代表性的 u/c,picc18,freertos

你这个看起来也应该属于协作式,或者干脆说是有优先级的状态机。一个任务returen之前是执行不了其他任务的,必须任务自己交出控制权