网站颜色:

MPC82G516 仿FX1NPLC 源码 V3


@

MPC82G516 仿FX1NPLC 源码 V3

 

/*----------------------------------------------------------------------------------------------------*/
/*                                                                                                    */
/*                  PLC 梯型图 解释型监控 C Code示范程序(用于 51单片机)                             */
/*                                                                                                    */
/*     为防止 PLC 指令编码和 C 语言关键字混淆,特规定,在本监控程序中,所有 PLC 指令前面加下划线"_", */
/*  所有点(BIT型)前后各加下划线"_",所有点(WORD型)前加下划线"_",指令后面的数据用( )包含,数据  */
/*  中间用","分隔,以示和 C 语言关键字区分及适应于 C 语言书写方法。                                   */
/*      所有十进制常数去掉前导"K",所有十六进制常数去掉前导"H"再加前导数字"0x",以便适应于 C 语言常   */
/*  数书写方法。这些下划线和加减前导数字将由 PLC 梯型图反编译程序自动加入。                           */
/*                                                                                                    */
/*     说心里话,这种容量小、功能少的 PLC,用汇编是最佳选择,程序精练、执行效率高,比如散转指令,用   */
/*  C语言的函数指针效率大打折扣,但考虑到方便大家今后程序的移植、更改、提高,使之能适应于 AVR,STM8, */
/*  NEC,PIC,H8,STM32......等任何单片机,未使用 51单片机特有的 bit 操作指令,关键部位也未插入汇编, */
/*  等程序修改稳定后再修改相关指令,优化程序代码,提升执行速度,使之更适合 51单片机的使用。           */
/*                                                                                                    */
/*     本程序支持混合编程,即在 PLC 指令编码中可任意插入 C 语言语句,符合 C 语言规范的汇编语言语句。  */
/*  可使用现有的调试软件仿真器设置断点,单步,多步,跟踪,连续,全速等手段调试 PLC 程序,修改和监控   */
/*  PLC 点件状态和内容,使之更适合广大单片机爱好者使用。                                            */
/*                                                                                                    */
/*     目前支持下列点(继续完善中):                                                                 */
/*  _X0_---_X57_,_Y0_---_S57_,_M0_---_M255_,_S0_---_S255_,_T0---_T31,_C0---_C31,_D0---_D31;     */
/*                                                                                                    */
/*     目前支持常数(继续完善中):                                                                   */
/*  K 范围:-32768---32767;  H 范围:0---FFFFH;                                                       */
/*                                                                                                    */
/*      目前支持特殊点数(继续完善中):                                                              */
/*  _M8000_,_M8001_,_M8002_,_M8003_,_M8004_,_M8011_,_M8012_,_M8013_,_M8014_,                 */
/*  _M8020_,_M8021_,_M8022_;                                                                       */
/*                                                                                                    */
/*      目前支持下列基本指令和扩展指令(继续完善中):                                                */
/*  _LD,_LDI,_AND,_ANI,_OR,_ORI,_INV,_OUT(_OUT_T,_OUT_C),_SET,_RST,_ANB,_ORB,_LDP,_LDF,_ANDP,_ANDF,   */
/*  _ORP,_ORF,_PLS,_PLF,_MPS,_MRD,_MPP,_NOP,END,_ADD,_SUB,_MUL,_DIV,_INC,_DEC,_WAND,_WOR,_WXOR,       */
/*  _NEG,_ALT,_MOV,_CML,_XCH,_BCD,_BIN,_CMP,_ZCP,_FMOV,_ROR,_ROL,_ZRST,_REF,_ASCI,_SWAP,_CJ,_CALL,    */
/*  _SRET,_FEND,_LD>=,_LD<=,_LD>,_LD<,_LD<>,_LD=,_AND>=,_AND<=,_AND>,_AND<,_AND<>,_AND=,_OR>=,_OR<=,  */
/*  _OR>,_OR<,_OR<>,_OR=;                                                                             */
/*                                                                                                    */
/*      由于 C语言无法识别下列符号,特用下列英文缩写表示:                                            */
/*  大于等于(>=)  _GE,小于等于(<=)  _LE,大于(>)  _GT,小于(<)  _LT,不相等(<>)  _NE,相等(=)  _EQ;  */
/*  即指令集:_LD>=,_LD<=,_LD>,_LD<,_LD<>,_LD=,_AND>=,_AND<=,_AND>,_AND<,_AND<>,_AND=,                */
/*            _OR>=,_OR<=,_OR>,_OR<,_OR<>,_OR=;                                                       */
/*      用下列指令书写方式替代。                                                                      */
/*  _LD_GE,_LD_LE,_LD_GT,_LD_LT,_LD_NE,_LD_EQ,_AND_GE,_AND_LE,_AND_GT,_AND_LT,_AND_NE,_AND_EQ,        */
/*  _OR_GE,_OR_LE,_OR_GT,_OR_LT,_OR_NE,_OR_EQ;                                                        */
/*                                                                                                    */
/*                                                                                                    */
/*   C P U : MPC82G516A(51系列)单片机                                                                 */
/*   晶  振: 11.0592MHz                                                                               */
/*   作  者: 许意义                                                                                   */
/*   版  本: V1.1.6                                                                                   */
/*   日  期: 2009.10.10                                                                               */
/*   版  权: ourDEV.cn                                                                                */
/*                                                                                                    */
/*----------------------------------------------------------------------------------------------------*/
/*   历次修改记录:  详见 updata.txt                                                                  */
/*----------------------------------------------------------------------------------------------------*/

#include "SYSTEM.h"
// 所有头文件 至 SYSTEM.H MJ.2009.(咨询特价)
//#include "PLC51x_TYPE.H"
//#include "PLC51x_SYS.H"
//#include "PLC51x.H"
//#include "PLC51x_FNC.H"

//bit  RUN = 0;
volatile unsigned char PLCRunFlag=1;          // PLC 停止[0]运行[1] 标志位 MJ.2009.(咨询特价)

unsigned int code TYPE_BCD[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,    // LED显示器段码表
                                 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};  // 0123456789AbCdEF

/***************************************************************************************/

unsigned char  Timer_5ms;         // 5ms时基计数器,5ms Timer0中断计数
unsigned char  Timer_10ms;        // 10ms时基计数器,5ms Timer0中断计数
unsigned char  Timer_100ms;       // 100ms时基计数器,5ms Timer0中断计数
unsigned char  Pulse_val_Sec;     // 1s时基计数器
unsigned char  Pulse_val_Min;     // 1min时基计数器
bit   Pulse_10ms ;
bit   Pulse_100ms;
bit   Pulse_Sec  ;
bit   Pulse_Min  ;

/***************************************************************************************/

volatile unsigned char   data  ACC_BIT;                         //  位运算器及 7级中间过渡栈
volatile unsigned char   data  MPS_BIT;                         //  位件 8级堆栈

//-------------------------------------------------------------------------------------//
//  位件 D 内存分配                                                                  //
//-------------------------------------------------------------------------------------//
 
volatile TYPE_BIT_BYTE   data  rX[_X_BYTE] , rY[_Y_BYTE];       //  位件 X,Y 存储位
volatile TYPE_BIT_BYTE   data  rX1[_X_BYTE], rY1[_Y_BYTE];      //  位件 X,Y 存储位上一步备份
volatile TYPE_BIT_BYTE   data  rM8xxx[3];                       //  位件 M8xxx 存储位
volatile TYPE_BIT_BYTE   data  rM8xxx1[3];                      //  位件 M8xxx 存储位上一步备份
volatile TYPE_BIT_BYTE   data  rTF[_T_BYTE];                    //  T 得电失电标志位
volatile TYPE_BIT_BYTE   data  rCF[_C_BYTE];                    //  C 得电失电标志位
volatile TYPE_BIT_BYTE   data  rT[_T_BYTE] , rC[_C_BYTE];       //  位件 T,C 输出位   
volatile TYPE_BIT_BYTE   data  rT1[_T_BYTE], rC1[_C_BYTE];      //  位件 T,C 输出位上一步备份
volatile TYPE_BIT_BYTE  xdata  rM[_M_BYTE];                     //  位件 M 存储位
volatile TYPE_BIT_BYTE  xdata  rS[_S_BYTE];                     //  位件 S 存储位
volatile TYPE_BIT_BYTE  xdata  rM1[_M_BYTE];                    //  位件 M 存储位上一步备份
volatile TYPE_BIT_BYTE  xdata  rS1[_S_BYTE];                    //  位件 S 存储位上一步备份
volatile signed   int   xdata  _T[_T_num][2];                   //  位件 T 内存分配   
volatile signed   int   xdata  _C[_C_num];                      //  位件 C 内存分配   
volatile signed   int   xdata  _D[_D_num];                      //  位件 D 内存分配

//-------------------------------------------------------------------------------------//
//  基本指令,扩展指令 子函数                                                          //
//-------------------------------------------------------------------------------------//
volatile unsigned char  xdata addr0T,addr1T,addr2T,addr3T,addr4T;  // 数据位第一至第五位字地址/数据类型

volatile TYPE_BYTES_WORD xdata addr0x,addr1x,addr2x,addr3x,addr4x; // 数据位第一至第五位字地址/数据缓冲区

volatile TYPE_BYTES_WORD  xdata order0;            // 命令位地址缓冲区

volatile unsigned int ppp;
volatile unsigned char code *CODE_p;
       
#if  DEBUG

  unsigned char code CODE_START[PLCSTEP*4] = {0x0,0x24,0x8,0x0,0x0,0x88,0x0,0x28,0x0,0xd5,0x1,0x24,0x9,
  0x0,0x1,0x88,0x1,0x28,0x0,0xe5,0xca,0x1,0x2,0x84,0x2,0xc8,0x2,0x28,0x1,0xd5,0xcb,0x1,0x2,0x84,0x3,
  0xc8,0x3,0x28,0x1,0xe5,0x0f,0x0
       };  


/*
  unsigned char code CODE_START[PLCSTEP*4] = {0x00,0x24,0x00,0xd5, // 模拟PLC运行代码
               0x01,0x24,0x00,0xe5,0x02,0x24,0x01,0xd5,0x03,0x24,0x01,0xe5,0x04,0x24,0x02,0xd5,
               0x05,0x24,0x02,0xe5,0x06,0x24,0x03,0xd5,0x07,0x24,0x03,0xe5,0x08,0x24,0x04,0xc5,
               0x09,0x24,0xfd,0xff,0x05,0xc5,0x0a,0x24,0x06,0xc5,0x0b,0x24,0xfd,0xff,0x07,0xc5,
               0x0f,0x00,0xff,0xff,0xff,0xff };  
*/

/*
  unsigned char code CODE_START[PLCSTEP*2] = {
0x0,0x2f,0x1,0x6,0xa,0x80,0x0,0x80,0x1,0x26,0x0,0xc5,0x0,0x25,0x2,0x6,0xa,0x80,0x0,0x80,0x2,0x26,
0x1,0xc5,0x1,0x25,0x3,0x6,0xa,0x80,0x0,0x80,0x3,0x26,0x2,0xc5,0x2,0x25,0x4,0x6,0xa,0x80,0x0,0x80,
0x4,0x26,0x3,0xc5,0x3,0x25,0x5,0x6,0xa,0x80,0x0,0x80,0x5,0x26,0x4,0xc5,0x4,0x25,0x6,0x6,0xa,0x80,
0x0,0x80,0x6,0x26,0x5,0xc5,0x5,0x25,0x7,0x6,0xa,0x80,0x0,0x80,0x7,0x26,0x6,0xc5,0x6,0x25,0x8,0x6,
0xa,0x80,0x0,0x80,0x8,0x26,0x7,0xc5,0x7,0x25,0x0,0x6,0xa,0x80,0x0,0x80,0x0,0x26,0xc,0x0,0x1,0x86,
0xc,0x0,0x2,0x86,0xc,0x0,0x3,0x86,0xc,0x0,0x4,0x86,0xc,0x0,0x5,0x86,0xc,0x0,0x6,0x86,0xc,0x0,0x7,
(咨询特价),0xc,0x0,0x8,0x86,0xc,0x0,0x9,0x86,0xc,0x0,0x0,0x86,0x0f,0x0
 }; 
*/

#endif
//-----------------------------------------------------------------------------------------//
//    数组名称:   BYTE_BIT                                                                 //
//    数组类型:   unsigned char code BYTE_BIT[8]                                           //
//                                                                   //
//    功能描述:  BYTE 字节型 BIT 位表                                                     //
//                                                                   //
//    入口参数:  BIT 位编号                                                               //
//                                                                   //
//    出口参数:  返回 BYTE 字节中 BIT 屏蔽位                                              //
//                                                                   //
//                                                                   //
//    作   者:   许意义                                                       //
//    日   期:   2009年10月2日                                                   //
//    备    注:                                                     //
//-----------------------------------------------------------------------------------------//
//    修 改 人:  卢明君                                                   //
//    日   期:  2009年12月01日                                                   //
//    备    注:  从 PLC51x_FNC.c 文件 改至 PLC51x.c 文件 ; 消除编译警告.                   //
//-----------------------------------------------------------------------------------------//
unsigned char code BYTE_BIT_s[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char code BYTE_BIT_w[8]={0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80};
unsigned char code BYTE_BIT_e[8]={0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};

//-----------------------------------------------------------------------------------------//
//    子函数名:  void inc_CODE_p(void)                                                    //
//                                                                                         //
//    注    释:  指向 PLC 运行程序的当前指针 CODE_p 值加 1                                //
//                                                                                         //
//    入口参数:  无                                                                       //
//    出口参数:  无                                                                       //
//-----------------------------------------------------------------------------------------//
//void inc_CODE_p(void)
//{ CODE_p++;
//}

//-------------------------------------------------------------------------------------//
//  10ms延时子程序                                                                     //
//-------------------------------------------------------------------------------------//

void Time_10ms(void)  
{ volatile unsigned char i; 
  for(i=0; i<10; i++)
    { ; }
}

//-------------------------------------------------------------------------------------//
//  74HC166并入串出芯片输入键盘扫描程序                                                //
//-------------------------------------------------------------------------------------//

unsigned char Get_EX_BIT(void)  
{ unsigned char i;  
  unsigned char EX_data = 0;  
  
  HC166_SL = 0;       // HC166_Disable; 将并行口的数据锁存
  Time_10ms();
  HC166_CLK = 0;      // CLK : 0->1
  Time_10ms();
  HC166_CLK = 1;
  Time_10ms();
  HC166_SL = 1;       // HC166_Enable; 转为串行
  Time_10ms();
  for(i=0; i<8; i++)
    { EX_data <<= 1;  
      if (HC166_DATA == 1)    // DATA : QH
        { EX_data |= 0x01; } 
      HC166_CLK = 0;          // CLK : 0->1
      Time_10ms();
      HC166_CLK = 1;
    }  
  return(EX_data);  
}  

//-------------------------------------------------------------------------------------//
//  74HC595串入并出芯片输出(16bit数据)LED显示扫描程序                                //
//-------------------------------------------------------------------------------------//

void Out_EY_BIT(void)
{ static unsigned char con;
  unsigned char i;
  unsigned int  Ia;
  if (++con >=5)  { con = 0; }
  switch(con)
    { case 0: Ia =( Value       & 0x000f);
              Ia = TYPE_BCD[Ia];
           Ia |= 0x0800;
           if (Vc0 == 1)  { Ia |= 0xff; }
              else  { if (Vb0 == 1)  { Ia &= 0xff7f; }
                    }
           break;
      case 1: Ia =((Value >> 4) & 0x000f);
              Ia = TYPE_BCD[Ia];
           Ia |= 0x0400;
           if (Vc1 == 1)  { Ia |= 0xff; }
              else  { if (Vb1 == 1)  { Ia &= 0xff7f; }
                    }
           break;
      case 2: Ia =((Value >> 8) & 0x000f);
              Ia = TYPE_BCD[Ia];
           Ia |= 0x0200;
           if (Vc2 == 1)  { Ia |= 0xff; }
              else  { if (Vb2 == 1)  { Ia &= 0xff7f; }
                    }
           break;
      case 3: Ia =((Value >>12) & 0x000f);
              Ia = TYPE_BCD[Ia];
           Ia |= 0x0100;
           if (Vc3 == 1)  { Ia |= 0xff; }
              else  { if (Vb3 == 1)  { Ia &= 0xff7f; }
                    }
           break;
      default:
              Ia = (~((Va4 << 4) | (Va3 << 3) | (Va2 << 2) | (Va1 << 1) | Va0) & 0x00ff) | 0x1000;
           break;
 }
 for (i = 16; i > 0; i--)
    { HC595_SCLK = 0;            //拉低74HC595时钟  
      Time_10ms();
      if ((Ia & 0x8000) == 0)    //先送高bit位数据  
          { HC595_SDATA = 0; }
        else                     //送74HC595的数据
          { HC595_SDATA = 1; }
      Time_10ms();
      Ia <<= 1;  
      HC595_SCLK = 1;            //拉高74HC595时钟
      Time_10ms();
    }
    HC595_SDATA = 1;             //释放数据总线
    Time_10ms();
    HC595_RCLK = 0;              //锁存数据
    Time_10ms();
    HC595_RCLK = 1;
    Time_10ms();
}

//-------------------------------------------------------------------------------------//
//  100ms 定时子函数                                                                   //
//-------------------------------------------------------------------------------------//

void _T100mS(void)
{ unsigned char i;
  if (Timer_100ms != 0)
    { Timer_100ms--;
      Pulse_val_Sec++;
      if (Pulse_val_Sec == 5)
     { Pulse_Sec = ~Pulse_Sec;
     }  
      if (Pulse_val_Sec == 10)
     { Pulse_Sec = ~Pulse_Sec;
    Pulse_val_Min++;
          Pulse_val_Sec = 0;
  }
   for (i=0; i<_T_num; i++ )
        { if ((rTF[i/8].BYTE & (1 << (i%8))) != 0)
            { if (_T[i][0] < _T[i][1])  { _T[i][0]++; }
            }
        }
 }
}

//-------------------------------------------------------------------------------------//
//  1Set 定时子函数                                                                    //
//-------------------------------------------------------------------------------------//

void _T1Set(void)
{ if ((Pulse_val_Min == 30) && (Pulse_val_Sec == 0))
 { Pulse_Min = ~Pulse_Min;
 }  
  if ((Pulse_val_Min == 60) && (Pulse_val_Sec == 0)) 
 { Pulse_Min = ~Pulse_Min;
   Pulse_val_Min = 0;
 }
}

//-------------------------------------------------------------------------------------//
//  5ms 定时中断 子函数,使用定时器 0                                                  //
//-------------------------------------------------------------------------------------//

void timer0(void) interrupt 1 using 1
{ TH0 = (Value_T0_cons >> 8);
  Pulse_10ms = ~Pulse_10ms;
  if ((++Timer_5ms & 0x01) != 0)  { Timer_10ms++; }
  if (Timer_5ms == 10)  { Pulse_100ms = ~Pulse_100ms; }
  if (Timer_5ms == 20)
    { Pulse_100ms = ~Pulse_100ms;
      Timer_100ms++; 
   Timer_5ms = 0;
    }
  if(UartRxTimerStartFlag)   // 接收超时...50ms
 { if(UartWaitForCounter>=10)
  { UartWaitForCounter=0;
    UartRxTimerStartFlag=0;
    UartDataReadyFlag=1;
    REN=0;      // 禁止UART接收器
  }
   else UartWaitForCounter++;
 }
}


//-------------------------------------------------------------------------------------//
//  初始化,输入输出,内存处理 子函数                                                  //
//-------------------------------------------------------------------------------------//
void input_IO(void)           // X输入,Y输出刷新
{ unsigned char i;
  i = P2;
  i = ((i << 1) & 0xaa) | ((i >> 1) & 0x55);
  i = ((i << 2) & 0xcc) | ((i >> 2) & 0x33);
  rX[0].BYTE = ~((P1 & 0x0f) | (i & 0xf0));
  rX[1].BYTE = ~(i & 0x0f) & 0x0f;
  rX[2].BYTE = ~Get_EX_BIT();
  P0 = rY[0].BYTE;
  Out_EY_BIT();
  _M8011_ = Pulse_10ms;
  _M8012_ = Pulse_100ms;
  _M8013_ = Pulse_Sec;
  _M8014_ = Pulse_Min;
}

void reset_IO(void)             // I,O口初始化
{ P0M0  = 0x00;
  P0M1  = 0xff;
  P0    = 0x00;
  P1    = 0xff;
  P2    = 0xff;
  P3    = 0xff;
  Value = 0;          // 变频显示器LED显示缓冲区
  Va0   = 0;          // 变频显示器F/R指示显示缓冲区
  Va1   = 0;          // 变频显示器 Hz指示显示缓冲区
  Va2   = 0;          // 变频显示器 V 指示显示缓冲区
  Va3   = 0;          // 变频显示器 A 指示显示缓冲区
  Va4   = 0;          // 变频显示器PLCRunFlag指示显示缓冲区
  Vb0   = 0;          // 变频显示器LED个位小数点显示缓冲区
  Vb1   = 0;          // 变频显示器LED十位小数点显示缓冲区
  Vb2   = 0;          // 变频显示器LED百位小数点显示缓冲区
  Vb3   = 0;          // 变频显示器LED千位小数点显示缓冲区
  Vc0   = 0;          // 变频显示器LED个位数熄灭标志
  Vc1   = 0;          // 变频显示器LED十位数熄灭标志
  Vc2   = 0;          // 变频显示器LED百位数熄灭标志
  Vc3   = 0;          // 变频显示器LED千位数熄灭标志
}

void reset_M8xxx(void)             // PLCRunFlag 后输出一个扫描周期初始化
{ rM8xxx[0].BYTE = 0x09;
}

void reset_RAM(void)
{ unsigned char i;
  for (i=0; i<_T_num;  i++)  { _T[i][0] = 0; }
  for (i=0; i<_T_num;  i++)  { _T[i][1] = 0x7fff; }
  for (i=0; i<_C_num;  i++)  { _C[i]    = 0; }
  for (i=0; i<_T_BYTE; i++)  { rT[i].BYTE = 0; rT1[i].BYTE = 0; rTF[i].BYTE = 0; }
  for (i=0; i<_C_BYTE; i++)  { rC[i].BYTE = 0; rT1[i].BYTE = 0; rCF[i].BYTE = 0; }
  for (i=0; i<_Y_BYTE; i++)  { rY[i].BYTE = 0; rY1[i].BYTE = 0; }
  for (i=0; i<_M_BYTE; i++)  { rM[i].BYTE = 0; rM1[i].BYTE = 0; }
  for (i=0; i<_S_BYTE; i++)  { rS[i].BYTE = 0; rS1[i].BYTE = 0; }
  for (i=0; i<_M8xxx_BYTE; i++) { rM8xxx[i].BYTE = 0; rM8xxx1[i].BYTE = 0; }
  rM8xxx[0].BYTE  = 0x05;
  rM8xxx1[0].BYTE = 0x05;
  Timer_5ms     = 0;           // 5ms时基计数器,5ms Timer0中断计数
  Timer_10ms    = 0;           // 10ms时基计数器,5ms Timer0中断计数
  Timer_100ms   = 0;           // 100ms时基计数器,5ms Timer0中断计数
  Pulse_val_Sec = 0;           // 1s时基计数器
  Pulse_val_Min = 0;           // 1min时基计数器
  CODE_ERROR    = 0;
  input_IO();
  for (i=0; i<_X_BYTE; i++) { rX1[i].BYTE = rX[i].BYTE; }
}

void reset_interrupt(void)
{ IP   = 0x00;
  IE   = 0x00;
  TCON = 0x00;           // 定时器控制寄存器, 注意:TCON只需操作一次
  TMOD = 0x01;
  T0  = Value_T0_cons;       // 装入5ms Timer0中断常数
  PT0 = 1;
  ET0 = 1;
  TR0 = 1;
}

void mov_to_old(void)
{ unsigned char i;
  for (i=0; i<_X_BYTE; i++) { rX1[i].BYTE = rX[i].BYTE; }
  for (i=0; i<_Y_BYTE; i++) { rY1[i].BYTE = rY[i].BYTE; }
  for (i=0; i<_M_BYTE; i++) { rM1[i].BYTE = rM[i].BYTE; }
  for (i=0; i<_S_BYTE; i++) { rS1[i].BYTE = rS[i].BYTE; }
  for (i=0; i<_T_BYTE; i++) { rT1[i].BYTE = rT[i].BYTE; }
  for (i=0; i<_C_BYTE; i++) { rC1[i].BYTE = rC[i].BYTE; }
  for (i=0; i<_M8xxx_BYTE; i++) { rM8xxx1[i].BYTE = rM8xxx[i].BYTE; }
  for (i=0; i<_T_num; i++ )
    { if (_T[i][0] >= _T[i][1])
    { rT[((&_T[i][0]-&_T[0][0])/2)/8].BYTE |= 1<<(((&_T[i][0]-&_T[0][0])/2)%8);
  }
   else { rT[((&_T[i][0]-&_T[0][0])/2)/8].BYTE &= ~(1 << (((&_T[i][0]-&_T[0][0])/2)%8));
     } 
    }
  PS1_BIT = PS_BIT;
}
#if 0
//-------------------------------------------------------------------------------------//
//  延迟 函数  delay_ms(unsigned int time)                                             //
//-------------------------------------------------------------------------------------//

void delay_ms(unsigned int time)
{
 volatile unsigned int i;
 volatile unsigned char j;
 for (i=0; i<time; i++)
   { for(j=0;j<0xfe;j++);
  for(j=0;j<0xfe;j++);
   }
}
#endif
//-------------------------------------------------------------------------------------//
//   串口初始化 函数  UartInit();                                                      //
//-------------------------------------------------------------------------------------//

void UartInit(void)
{
 SCON  = 0x50;
 TR1=0;    // 停止定时器
// TCON=0x00;   // 定时器控制寄存器 注意:TCON只需操作一次
 TMOD |= 0x20;  // 定时器1
 TL1 = -(SYSCLK/12/32/BAUD);
    TH1 = TL1;
 TR1=1;    // 启动定时器1
 UartReceiveCounter=0;
 UartRxTimerStartFlag=0;
}

//-------------------------------------------------------------------------------------//
//   PLC 入口 函数  main_PLC();                                                        //
//-------------------------------------------------------------------------------------//

void main_PLC (void)
{
  CODE_p = (unsigned char code *)CODE_START;
  Pi = 0x01;
  do{
      orderL = *CODE_p;
   CODE_p++;
      orderH = *CODE_p;
   CODE_p++;
      ppp = order & 0xfff;
      (*key_list[orderH >> 4])();
    } while((CODE_p < CODE_END) && (CODE_p != CODE_START));
}

unsigned char code ArrPLCSoftwareVer[] ="V1.01.06";// PLC Software Version

unsigned char FX1NPLCSoftwareVerCheck(void)
{
 unsigned int i;
 unsigned int tempaddr;
 unsigned char tempArray[8];
 unsigned char code ArrSoftwareUpdate[] ="Software Update!rn0";

 // 根据 PLC 软件版本号,自动恢复出厂设置. MJ.2009.(咨询特价)
 tempaddr=PLCSoftwareVerAddr;
 for(i=0;i<8;i++)
 {
  tempArray[i]=IAPFlashReadMode(tempaddr++); // Software Version
  if(tempArray[i]!=ArrPLCSoftwareVer[i])
  {
   UartSendByte(ArrPLCSoftwareVer,8);
   UartSendString(ArrSoftwareUpdate);
   return 0;
  }
 }
 return 1;
}

void PLCStateCheck(void)
{
 unsigned char tPLCState;

 tPLCState=IAPFlashReadMode(PLCStateRealAddr);
 if(tPLCState==PLCStateRun)PLCRunFlag=1;
 else if(tPLCState==PLCStateStop)PLCRunFlag=0;
 else
 {
  while(1);      // 错误处理
 }
}

//-------------------------------------------------------------------------------------//
//  主程序入口 主函数                                                                  //
//-------------------------------------------------------------------------------------//
void main(void)
{
 unsigned char reset_i=1;
 unsigned int i;
 unsigned char PLCVerPassFlag;
 unsigned char code ArrPass[] ="PASS!rn0";
 unsigned char code DefaultSet[] ="System in factory default.rn0";
 unsigned char TimesBuf=0;        // 检测 上升 or下降 沿.

 reset_IO();
 reset_RAM();
 reset_interrupt();
 UartInit();
 EA = 1;
 PLCVerPassFlag=FX1NPLCSoftwareVerCheck();    // 上电,核实 PLC 软件版本号
 if(PLCVerPassFlag==0)         // 恢复出厂设置.
 {
  ErasurePLC(ErasureALL);        // 全部擦除 初始PLC程序为空
  for(i=0;i<8;i++)         // 更新软件版本号
  {
   IAPFlashProgremMode(PLCSoftwareVerAddr+i,ArrPLCSoftwareVer[i]);
  }
  IAPFlashProgremMode(PLCStateRealAddr,PLCStateRun); // 写入 PLC [运行/停止状态位]为[运行]
  for(i=0;i<92;i++)         // 写入 PLC 初始化代码 查询地址0x8000~0x805B.
  {
   IAPFlashProgremMode(CodeStartAddr+i,CodeStart[i]);
  }
  for(i=0;i<0x100;i++)        // 写入 PLC 初始化代码 查询地址0x0E00~0x0EFF
  {
   IAPFlashProgremMode(SDataRegStartAddr+SDataRegOffset+i,SDataReg[i]);
  }
  UartSendString(DefaultSet);
 }
 else UartSendString(ArrPass);

 Value=0;
 CODE_scan();
 while (1)
 {
  // =============================================================================
  // [====]以下内容由 MJ.2009.12.23 凌晨加入.
  // 目的:【(运行)按钮按下】时为【停止】, 用 PLC -- 遥控运行/停止 命令至 PLC 内的控制字遥控运行/停止比按钮优先。
  //    ---- 摘自[★ 简易PLC 梯型图 解释型监控 示范程序 测试版(51)----直接使用三菱FXGPWIN软件!]一贴,第【199楼】 oste
  // 说明:
  // 1.在[运行按钮]按下(由抬起至按下)★变化当次★,无论[运行/停止状态位]是运行还是停止,一律停止;
  // 2.在[运行按钮]抬起(由按下至抬起)★变化当次★,无论[运行/停止状态位]是运行还是停止,一律运行;
  // 无论执行 1 或者 2 ,而后可通过[FXGPWIN]软件修改[运行/停止状态位].是运行就运行.是停止就停止;
  // 注意:
  // 1.请在[编写梯形图软件]时,自行避开两个引脚同时为低的情况.
  // 2.请在[编写梯形图软件]时,注意这两个引脚为低时的后果.
  TimesBuf<<=0x01;
  if((P1 & 0x03) == 0)
  {
   if(TimesBuf==0xfc) // 下降沿
   {
    if(PLCRunFlag==1)IAPFlashProgremMode(PLCStateRealAddr,PLCStateStop);
   }
   else TimesBuf&=~0x01;
  }
  else
  {
   if(TimesBuf==0x02) // 上升沿
   {
    if(PLCRunFlag==0)IAPFlashProgremMode(PLCStateRealAddr,PLCStateRun);
   }
   else TimesBuf |=0x01;
  }
  PLCStateCheck();
  // [====]以上内容由 MJ.2009.12.23 凌晨加入.
  // =============================================================================
  FX1NComPortProcessing();    // PLC 下载通信处理
  if(PLCRunFlag)
  {
   input_IO();
   if (CODE_ERROR == 0)main_PLC();
   else
   {
    if (Pulse_Sec != 0)P1 &= 0xfc; // PLC 程序出错报警,X0,X1灯闪烁。
    else P1 |= 0x03;
   }
   _T100mS();
   _T1Set();
   mov_to_old();
   if (reset_i != 0)
   {
    reset_i--;
    reset_M8xxx();
   }
  }
 }
}

//-------- main  END ----------//

 

 

热门设计服务