📄 tinyplc.c
字号:
}
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 + -