⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tinyplc.c

📁 单片PLC,AT2581实现梯形图功能,可作为参考
💻 C
📖 第 1 页 / 共 3 页
字号:
   }

void ctt()
   {
   tempvar = linetrue;  /* need to save this before we change it */
   if (linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if (!dataregs[r1].t.b1)  /* FALSE -> TRUE transition */
            {
            if (++dataregs[r1].t.w >= *(WORD *)&program[program_ip+2])
               dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   dataregs[r1].t.b1 = tempvar;
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void ctf()
   {
   tempvar = linetrue;  /* need to save this before we change it */
   if (!linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if (dataregs[r1].t.b1)  /* TRUE -> FALSE transition */
            {
            if (++dataregs[r1].t.w >= *(WORD *)&program[program_ip+2])
               dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   dataregs[r1].t.b1 = tempvar;
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void tmt()
   {
   if (linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         if (!(dataregs[r1].t.b0 & TIMER_ENABLED_BIT))  /* initting timer */
            dataregs[r1+1].v = tick_counter;
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if ((tick_counter - dataregs[r1+1].v) >= (DWORD)(*(WORD *)&program[program_ip+2]))
                        /* timer expired */
            {
            dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   else
      {
      dataregs[r1].t.b0 = 0;  /* all flags off */
      }
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void tmf()
   {
   if (!linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         if (!(dataregs[r1].t.b0 & TIMER_ENABLED_BIT))  /* initting timer */
            dataregs[r1+1].v = tick_counter;
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if ((tick_counter - dataregs[r1+1].v) >= (DWORD)(*(WORD *)&program[program_ip+2]))
                        /* timer expired */
            {
            dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   else
      {
      dataregs[r1].t.b0 = 0;  /* all flags off */
      }
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void rtmt()
   {
   if (linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         if (!(dataregs[r1].t.b0 & TIMER_ENABLED_BIT))  /* initting timer */
            dataregs[r1+1].v = tick_counter - dataregs[r1].t.w;
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if ((tick_counter - dataregs[r1+1].v) >= (DWORD)(*(WORD *)&program[program_ip+2]))
                        /* timer expired */
            {
            dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   else
      {
      if (dataregs[r1].t.b0 & TIMER_ENABLED_BIT)
         {
         dataregs[r1].t.w = tick_counter - dataregs[r1+1].v;
         dataregs[r1].t.b0 &= ~TIMER_ENABLED_BIT;  /* flag off */
         }
      }
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void rtmf()
   {
   if (!linetrue)
      {
      if (!(dataregs[r1].t.b0 & TIMER_DONE_BIT))  /* if not already done */
         {
         if (!(dataregs[r1].t.b0 & TIMER_ENABLED_BIT))  /* initting timer */
            dataregs[r1+1].v = tick_counter - dataregs[r1].t.w;
         dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_ACTIVE_BIT;
         if ((tick_counter - dataregs[r1+1].v) >= (DWORD)(*(WORD *)&program[program_ip+2]))
                        /* timer expired */
            {
            dataregs[r1].t.b0 = TIMER_ENABLED_BIT | TIMER_DONE_BIT;
            }
         }
      }
   else
      {
      if (dataregs[r1].t.b0 & TIMER_ENABLED_BIT)
         {
         dataregs[r1].t.w = tick_counter - dataregs[r1+1].v;
         dataregs[r1].t.b0 &= ~TIMER_ENABLED_BIT;  /* flag off */
         }
      }
   linetrue = dataregs[r1].t.b0 & TIMER_DONE_BIT ? TRUE : FALSE;
   program_ip += 4;
   }

void reset()
   {
   if (linetrue)
      dataregs[r1].v = 0;  /* reset flags & accum */
   program_ip += 2;
   }

void invert()
   {
   linetrue = !linetrue;
   program_ip++;
   }

void (*optable[LAST_OPCODE+1])() =
   {
   nop,           /* 0x00: NOP */
   nop,           /* 0x01: BREAK, implement later */
   setlinetrue,   /* 0x02: set linetrue to TRUE */
   pushlinetrue,  /* 0x03: push linetrue to init stack */
   orbranch,      /* 0x04: push linetrue to result stack, copy (not pop) linetrue from init stack */
   orpoplinetrue, /* 0x05: or linetrue with top of result stack, pop initstack and result stack */
   inp,           /* 0x06: linetrue = input */
   ninp,          /* 0x07: linetrue = !input */
   out,           /* 0x08: output = linetrue */
   nout,          /* 0x09: output = !linetrue */
   lout,          /* 0x0a: if linetrue set output */
   uout,          /* 0x0b: if linetrue clear output */
   add,           /* 0x0c: if linetrue dest = R1 + R2 */
   addb,          /* 0x0d: if linetrue dest = R1 + BVAL */
   sub,           /* 0x0e: if linetrue dest = R1 - R2 */
   subb,          /* 0x0f: if linetrue dest = R1 - BVAL */
   mul,           /* 0x10: if linetrue dest = R1 * R2 */
   mulb,          /* 0x11: if linetrue dest = R1 * BVAL */
   div,           /* 0x12: if linetrue dest = R1 / R2 */
   divb,          /* 0x13: if linetrue dest = R1 / BVAL */
   mod,           /* 0x14: if linetrue dest = R1 % R2 */
   modb,          /* 0x15: if linetrue dest = R1 % BVAL */
   and,           /* 0x16: if linetrue dest = R1 & R2 */
   andb,          /* 0x17: if linetrue dest = R1 & BVAL */
   or,            /* 0x18: if linetrue dest = R1 | R2 */
   orb,           /* 0x19: if linetrue dest = R1 | BVAL */
   xor,           /* 0x1a: if linetrue dest = R1 ^ R2 */
   xorb,          /* 0x1b: if linetrue dest = R1 ^ BVAL */
   not,           /* 0x1c: if linetrue R1 = ~R1 */
   neg,           /* 0x1d: if linetrue R1 = -R1 */
   equ,           /* 0x1e: linetrue = R1 == R2 */
   equb,          /* 0x1f: linetrue = R1 == BVAL */
   neq,           /* 0x20: linetrue = R1 != R2 */
   neqb,          /* 0x21: linetrue = R1 != BVAL */
   grt,           /* 0x22: linetrue = R1 > R2 */
   grtb,          /* 0x23: linetrue = R1 > BVAL */
   geq,           /* 0x24: linetrue = R1 >= R2 */
   geqb,          /* 0x25: linetrue = R1 >= BVAL */
   les,           /* 0x26: linetrue = R1 < R2 */
   lesb,          /* 0x27: linetrue = R1 < BVAL */
   leq,           /* 0x28: linetrue = R1 <= R2 */
   leqb,          /* 0x29: linetrue = R1 <= BVAL */
   mov,           /* 0x2a: if linetrue dest = R1 */
   movd,          /* 0x2b: if linetrue dest = DVAL */
   jmp,           /* 0x2c: if linetrue goto label */
   osr,           /* 0x2d: if previous scan was FALSE and linetrue, set linetrue for one scan */
   ctt,           /* 0x2e: counter of FALSE -> TRUE transitions */
   nop,           /* 0x2f: not implmenented, reserved */
   ctf,           /* 0x30: counter of TRUE -> FALSE transitions */
   nop,           /* 0x31: not implemented, reserved */
   tmt,           /* 0x32: timer of TRUE duration */
   nop,           /* 0x33: not implemented, reserved */
   tmf,           /* 0x34: timer of FALSE duration */
   nop,           /* 0x35: not implemented, reserved */
   rtmt,          /* 0x36: retentive timer of TRUE duration */
   nop,           /* 0x37: not implemented, reserved */
   rtmf,          /* 0x38: retentive timer of FALSE duration */
   nop,           /* 0x39: not implemented, reserved */
   reset,         /* 0x3a: if linetrue reset timer/counter */
   invert         /* 0x3b: linetrue = !linetrue */
   };

void process_ladder()
   {
   while (runflag)  /* or until BREAK */
      {
      PET_WATCHDOG();
      r1 = program[program_ip+1];
      r2 = program[program_ip+2];
      (*optable[program[program_ip]])();
      if (debugflag)
         {
         if (run_nodecount)
            {
            if (--run_nodecount == 0)
               {
               runflag = FALSE;
               }
            }
         }
      if (program_ip == program_len)  /* end of ladder */
         {
         program_ip = 0;
         break;
         }
      }
   }

update_runstop_status()
   {
   lasthardrun = hardrun;
   if ((hardrun == RUNSTOP_RUN) && (softrun))
      {
      runflag = TRUE;
      }
   else
      {
      runflag = FALSE;
      }
   }

read_eeprom_program()
   {
   WORD p_l, i, chksum;

   p_l = eeprom_program_len;
   if ((p_l) && (p_l <= MAX_PROGRAM))  /* could be valid... */
      {
      for (chksum = 0, i = 0; i < p_l; i++)
         {
         program[i] = eeprom_program[i];
         chksum += program[i];
         }
      if (chksum == eeprom_program_checksum)
         {
         program_len = p_l;
         program_valid = TRUE;
         softrun = TRUE;  /* at powerup, assume software run permission */
         }
      }
   }

void save_program()
   {
   WORD i, chksum;

   if (program_valid)
      {
      eeprom_program_len = program_len;
      for (chksum = 0, i = 0; i < program_len; i++)
         {
         eeprom_program[i] = program[i];
         chksum += program[i];
         }
      eeprom_program_checksum = chksum;
      }
   }

void check_message_type()
   {
   incoming_len = (WORD)message[3] + ((WORD)message[4] << 8);
   if (message[2] > LAST_MSG)
      message_status = MSG_STATUS_IGNORE;
   if (message[2] == MSG_PROGRAM)
      {
      p_len = 0;
      if ((incoming_len < 3) || (incoming_len > MAX_PROGRAM + 2))
         message_status = MSG_STATUS_IGNORE;
      else
         {
         runflag = FALSE;
         softrun = FALSE;
         program_valid = FALSE;
         program_ip = 0;
         debugflag = FALSE;
         message_status = MSG_STATUS_PROGRAM;
         update_runstop_status();
         init_logic();
         }
      }
   else
      if (incoming_len > 16)
         message_status = MSG_STATUS_IGNORE;
   incoming_len += message_ptr;
   }

sendack()
   {
   xmit_char(MSG_BYTE0);
   xmit_char(MSG_BYTE1);
   xmit_char(MSG_ACK);
   xmit_char(0);
   xmit_char(0);
   }

sendstatus()
   {
   xmit_char(linetrue);
   xmit_char(runflag);
   xmit_char(debugflag);
   xmit_char(program_ip & 0xff);
   xmit_char(program_ip >> 8);
   xmit_char(program_valid);
   xmit_char(program_len & 0xff);
   xmit_char(program_len >> 8);
   }

sendregs()
   {
   WORD i;

   sendstatus();
   for (i = 0; i < PLC_MEMORY_LOCS; i++)
      {
      xmit_wait(dataregs[i].bytes[0]);
      xmit_wait(dataregs[i].bytes[1]);
      xmit_wait(dataregs[i].bytes[2]);
      xmit_wait(dataregs[i].bytes[3]);
      }
   }

void process_message()
   {
   WORD i;
   WORD chksum;

   switch (message[2])
      {
      case MSG_RUN:
         if (program_valid)
            {
            softrun = TRUE;
            sendack();
            update_runstop_status();
            }
         break;
      case MSG_STOP:
         softrun = FALSE;
         sendack();
         update_runstop_status();
         break;
      case MSG_GETREGS:
         sendregs();
         break;
      case MSG_NUMSTEPS:
         if ((program_valid) && (message_ptr == 7))
            {
            run_nodecount = (WORD)message[5] + ((WORD)message[6] << 8);
            if (run_nodecount)
               {
               debugflag = TRUE;
               sendack();
               }
            }
         break;
      case MSG_PROGRAM:
         p_len -= 2;
         for (chksum = 0, i = 0; i < p_len; i++)
            chksum += program[i];
         if (((chksum & 0xff) == program[i])
               && ((chksum >> 8) == program[i+1]))
            {
            program_len = p_len;
            program_valid = TRUE;
            sendack();
            save_program();
            }
         break;
      case MSG_PROGSTATUS:
         sendstatus();
         break;
      case MSG_ACK:
         break;
      }
   }

void main(void)
   {
   system_init();

   xmit_str("TinyPLC V0.01A 9/13/06\r\n");
   program_valid = FALSE;
   read_eeprom_program();
   init_logic();
   lasthardrun =
   hardrun = RUNSTOP_SWITCH;
   update_runstop_status();

   while (1)
      {
      if (rx_buf_in)
         {
         if (program_timer == 0)  /* start of incoming */
            program_timer = 10;
         if (program_abort)
            {
            program_abort = FALSE;
            program_timer = 0;
            rx_buf_in = 0;
            rx_buf_out = 0;
            message_ptr = 0;
            incoming_len = 0xffff;  /* invalid! */
            message_status = MSG_STATUS_WAITING;
            }
         else
            {
            DI();
            while (rx_buf_out != rx_buf_in)
               {
               if (message_status == MSG_STATUS_PROGRAM)
                  {
                  if (p_len != MAX_PROGRAM + 2)
                     program[p_len++] = rx_buf[rx_buf_out];
                  }
               else
                  {
                  if ((message_status != MSG_STATUS_IGNORE) && (message_ptr < MAX_MSG_SIZE))
                     message[message_ptr] = rx_buf[rx_buf_out];
                  }
               message_ptr++;
               rx_buf_out = (rx_buf_out == RXBUF_SIZE - 1) ? 0 : rx_buf_out + 1;
               if ((message_ptr == 1) && (message[0] != MSG_BYTE0))
                  message_ptr = 0;
               if ((message_ptr == 2) && (message[1] != MSG_BYTE1))
                  message_ptr = 0;
               if (message_ptr == 5)  /* 55 AA <cmd> <len-low> <len-high> */
                  check_message_type();
               }
            rx_buf_in = 0;
            rx_buf_out = 0;
            EI();
            if (message_ptr >= incoming_len)  /* EOM or error */
               {
               if (message_ptr == incoming_len)
                  process_message();
               program_timer = 0;
               program_abort = FALSE;
               message_ptr = 0;
               message_status = MSG_STATUS_WAITING;
               incoming_len = 0xffff;  /* invalid! */
               }
            }
         }
      PET_WATCHDOG();
      if (program_abort)
         {
         program_abort = FALSE;
         message_ptr = 0;
         incoming_len = 0xffff;  /* invalid! */
         }
      if (++status_led_counter > status_led_pwm)
         STATUS_LED = STATUS_LED_ON;
      else
         STATUS_LED = STATUS_LED_OFF;
      if ((hardrun = RUNSTOP_SWITCH) != lasthardrun)
         update_runstop_status();
      if (program_valid)
         {
         if (program_ip == 0)  /* if about to start the ladder */
            gather_inputs();
         process_ladder();
         if (program_ip == 0)  /* if we just finished the ladder */
            service_outputs();
         }
      }  /* while (1) */
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -