目次
前
次
Z80でPLC
PLCは、ワンチップマイコンがあれば実現できます。
手元には、Z80ボードが多数あるので、これらを
PLCにしてみます。これらのボードは、Z84C015
を利用しているので、PIO、CTC、SIOが含まれて
おり、SRAMも8kBか32kBあるので、ROMの中に
PLC用インタプリタを入れて、実現します。
入力、出力は、PIOがあるので、ポートA、Bを
利用します。8ビット入力、8ビット出力として
使います。
動作は、タイマー割込みで入力ポートから入力メモリ
に内容を転送します。スキャン処理が終了したなら
出力メモリから出力ポートにデータを出力します。
全体をC言語で記述した後、スキャン処理を高速
に実行するため、アセンブリ言語コードで書換え
ます。
最初にAVR用C言語で記述した内容を、Z80に
置き換えます。AVR用C言語のソースコードは
以下。
#include <avr/io.h>
#include <avr/io8535.h>
#include <avr/interrupt.h>
#define TSK_ID_MAX 6
#define TSK_ID0 0
#define TSK_ID1 1
#define TSK_ID2 2
#define TSK_ID3 3
#define TSK_ID4 4
#define TSK_ID5 5
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
typedef struct {
void (*tsk)(void);
UWORD wcount ;
} TCBP ;
typedef union {
struct {
unsigned char B0:1;
unsigned char B1:1;
unsigned char B2:1;
unsigned char B3:1;
unsigned char B4:1;
unsigned char B5:1;
unsigned char B6:1;
unsigned char B7:1;
} BIT ;
unsigned char DR ;
} FLAGSP ;
volatile FLAGSP x_flags ;
#define SFLAG x_flags.BIT.B0
#define IFLAG x_flags.BIT.B1
#define PFLAG x_flags.BIT.B2
#define NFLAG x_flags.BIT.B3
#define OFLAG x_flags.BIT.B4
#define MFLAG x_flags.BIT.B4
#define BUFSIZE 10
volatile UBYTE rbuf[BUFSIZE] ;
volatile UBYTE rindex;
UBYTE asc_cha[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} ;
#define OFF 0
#define ON 1
#define IDLE 0
#define RUN IDLE+1
#define LED_OFF (PORTD |= 0x10)
#define LED_ON (PORTD ^= 0xef)
#define LOWER_LATCH 1
#define UPPER_LATCH 2
#define MASKFF 0xff
#define MASK0F 0x0f
volatile UBYTE msft ;
volatile UBYTE memory[32] ;
volatile UBYTE mshift ;
volatile UWORD cadr ;
volatile UWORD cdat ;
volatile UBYTE stksft ;
volatile UBYTE opcode ;
volatile UBYTE operand;
volatile UBYTE q ;
volatile UBYTE r ;
volatile UBYTE cmd ;
volatile UWORD rom_address ;
volatile UBYTE reg ;
volatile UBYTE regx ;
volatile UWORD pcnt ;
#define TTS_SUSPEND 0
#define TTS_WAIT TTS_SUSPEND+1
#define TTS_READY TTS_SUSPEND+2
#define NO 0
#define YES 1
UBYTE ready ;
UBYTE suspend;
UBYTE vldtsk ;
UBYTE run_tsk;
TCBP tcb[TSK_ID_MAX];
/*------------------------*/
/* task function protoype */
/*------------------------*/
void tsk0_proc(void);
void tsk1_proc(void);
void tsk2_proc(void);
void tsk3_proc(void);
void tsk4_proc(void);
void tsk5_proc(void);
/*-----------------------*/
/* system call prototype */
/*-----------------------*/
void init_os(void);
void cre_tsk(UBYTE tid,void (*tsk)(void));
void sta_tsk(UBYTE tid,UBYTE sta);
void rsm_tsk(UBYTE tid);
void sus_tsk(UBYTE tid);
void slp_tsk(void);
void wai_tsk(UWORD x);
UBYTE is_tsk_ready(UBYTE tid);
/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void user_initialize(void);
#define ITRG 0
#define OEA 1
#define OEB 2
#define OEO 3
#define OTRGA 4
#define OTRGB 5
#define OP_END 0
#define OP_OUT 1
#define OP_LD 2
#define OP_LDN 3
#define OP_AND 4
#define OP_ANDN 5
#define OP_OR 6
#define OP_ORN 7
#define OP_ANDB 8
#define OP_ORB 9
void rs_putchar(UBYTE x);
void rs_puts(UBYTE *x);
void write_eeprom(UWORD adr,UBYTE dat);
UBYTE read_eeprom(UWORD adr);
void push(UBYTE x);
UBYTE pull(void);
UWORD get_circuit_infomation(UWORD x);
void doStep(UWORD radr);
void doScan(UWORD radr);
UBYTE get_hex(UBYTE x);
UWORD get_ad(UBYTE onoff);
void put_dat_eeprom(UWORD adr,UWORD dat);
/*------*/
/* main */
/*------*/
int main(void)
{
TCBP pcur_tsk ;
/* disable interrupt */
cli();
/* initialize monitor */
init_os();
cre_tsk(TSK_ID0,tsk0_proc);
cre_tsk(TSK_ID1,tsk1_proc);
cre_tsk(TSK_ID2,tsk2_proc);
cre_tsk(TSK_ID3,tsk3_proc);
cre_tsk(TSK_ID4,tsk4_proc);
cre_tsk(TSK_ID5,tsk5_proc);
sta_tsk(TSK_ID0,TTS_READY);
sta_tsk(TSK_ID1,TTS_SUSPEND);
sta_tsk(TSK_ID2,TTS_SUSPEND);
sta_tsk(TSK_ID3,TTS_READY);
sta_tsk(TSK_ID4,TTS_READY);
sta_tsk(TSK_ID5,TTS_READY);
user_initialize();
/* enable interrupt */
sei();
/* loop */
run_tsk = TSK_ID0 ;
while ( 1 ) {
pcur_tsk = tcb[run_tsk] ;
if ( is_tsk_ready( run_tsk ) == YES ) { (*(pcur_tsk.tsk))(); }
run_tsk++;
if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }
}
/* dummy */
return 0 ;
}
/*----------------*/
/* task functions */
/*----------------*/
void tsk0_proc(void)
{
/* mode switch handling */
LED_OFF ;
if ( MFLAG == ON ) { LED_ON ; }
/* check flag */
if ( SFLAG == OFF ) return ;
/* clear flag */
SFLAG = OFF ;
/* get command */
cmd = *(rbuf+0) ;
/* judge */
if ( cmd == 'S' ) {
/* get address */
cadr = get_ad(OFF) ;
/* get data */
cdat = get_ad(ON) ;
/* wake up */
rsm_tsk( TSK_ID1 ) ;
}
if ( cmd == 'L' ) { rsm_tsk( TSK_ID2 ) ; }
if ( cmd == 'I' ) {
IFLAG = OFF ;
if ( *(rbuf+1) == '1' ) { IFLAG = ON ; }
}
if ( cmd == 'P' ) {
PFLAG = OFF ;
if ( *(rbuf+1) == '1' ) { PFLAG = ON ; pcnt = 0 ; }
}
if ( cmd == 'N' ) { pcnt += 2 ; }
if ( cmd == 'O' ) {
OFLAG = OFF ;
if ( *(rbuf+1) == '1' ) { OFLAG = ON ; }
}
}
void tsk1_proc(void)
{
/* save */
put_dat_eeprom( cadr , cdat );
/* sleep */
slp_tsk();
}
void tsk2_proc(void)
{
UBYTE tmp ;
UBYTE xdat[3];
/* set delimiter */
*(xdat+2) = 0 ;
for ( rom_address = 0 ; rom_address < 512 ; rom_address++ ) {
tmp = read_eeprom( rom_address ) ;
*(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ];
*(xdat+1) = asc_cha[ tmp & MASK0F ];
rs_puts( xdat );
}
/* sleep */
slp_tsk();
}
void tsk3_proc(void)
{
UBYTE xdat[3];
UBYTE tmp ;
/* send latch trigger */
PORTB |= (1 << ITRG);
PORTB &= ~(1 << ITRG);
/* enable nOEA */
PORTB &= ~(1 << OEA);
/* get lower data */
*(memory+0) = PINA ;
/* disable nOEA */
PORTB |= (1 << OEA);
/* enable nOEB */
PORTB &= ~(1 << OEB);
/* get upper data */
*(memory+1) = PINA ;
/* disable nOEB */
PORTB |= (1 << OEB);
/* show input memory */
if ( IFLAG == ON ) {
*(xdat+2) = 0 ;
tmp = *(memory+0) ;
*(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ];
*(xdat+1) = asc_cha[ tmp & MASK0F ];
rs_puts( xdat );
tmp = *(memory+1) ;
*(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ];
*(xdat+1) = asc_cha[ tmp & MASK0F ];
rs_puts( xdat );
}
}
void tsk4_proc(void)
{
UWORD i;
if ( PFLAG == ON ) {
doStep(pcnt);
} else {
for ( i = 0 ; i < 512 ; i += 2 ) { doStep(i); }
}
}
void tsk5_proc(void)
{
UBYTE xdat[3];
UBYTE tmp ;
/* output lower data */
PORTC = *(memory+2) ;
/* send latch pulse */
PORTB |= (1 << OTRGA) ;
PORTB &= ~(1 << OTRGA) ;
/* output upper data */
PORTC = *(memory+3) ;
/* latch upper data */
PORTB |= (1 << OTRGB) ;
PORTB &= ~(1 << OTRGB) ;
/* show output memory */
if ( OFLAG == ON ) {
*(xdat+2) = 0 ;
tmp = *(memory+2) ;
*(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ];
*(xdat+1) = asc_cha[ tmp & MASK0F ];
rs_puts( xdat );
tmp = *(memory+3) ;
*(xdat+0) = asc_cha[ (tmp >> 4) & MASK0F ];
*(xdat+1) = asc_cha[ tmp & MASK0F ];
rs_puts( xdat );
}
}
/*------------------*/
/* system call body */
/*------------------*/
void init_os(void)
{
ready = vldtsk = 0 ;
}
void cre_tsk(UBYTE tid,void (*tsk)(void))
{
if ( tid >= TSK_ID_MAX ) return ;
vldtsk |= (1 << tid) ;
tcb[tid].tsk = tsk;
tcb[tid].wcount = 0;
}
void sta_tsk(UBYTE tid,UBYTE sta)
{
if ( tid >= TSK_ID_MAX ) return ;
if ( sta == TTS_READY ) {
ready |= (1 << tid);
suspend &= ~(1 << tid);
}
if ( sta == TTS_WAIT ) {
ready &= ~(1 << tid);
suspend &= ~(1 << tid);
}
if ( sta == TTS_SUSPEND ) {
ready &= ~(1 << tid);
suspend |= (1 << tid);
}
}
void rsm_tsk(UBYTE tid)
{
if ( tid >= TSK_ID_MAX ) return ;
ready |= (1 << tid);
suspend &= ~(1 << tid);
}
void sus_tsk(UBYTE tid)
{
if ( tid >= TSK_ID_MAX ) return ;
ready &= ~(1 << tid);
suspend |= (1 << tid);
}
void slp_tsk(void)
{
sus_tsk(run_tsk);
}
void wai_tsk(UWORD x)
{
ready &= ~(1 << run_tsk);
suspend &= ~(1 << run_tsk);
tcb[run_tsk].wcount = x ;
}
UBYTE is_tsk_ready(UBYTE tid)
{
return( (ready >> tid) & 1 ) ;
}
/*-----------------------------*/
/* timer handler */
/* call from timer interrupt */
/*-----------------------------*/
void timer_handler(void)
{
UBYTE tmp;
UBYTE i ;
tmp = (ready ^ vldtsk) ^ suspend ;
for ( i = 0 ; i <= TSK_ID_MAX ; i++ ) {
if ( tmp & 1 ) {
tcb[i].wcount-- ;
if ( tcb[i].wcount == 0 ) { rsm_tsk(i); }
}
tmp >>= 1 ;
}
}
/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
#define FOSC 8000000
#define BAUD 38400
#define MYUBRR (FOSC/16/BAUD)-1
void user_initialize(void)
{
volatile UBYTE i ;
/* PORT A */
DDRA = 0b00000000 ; /* iiiiiiii */
PORTA = 0b00000000 ; /* 00000000 */
/* PORT B */
DDRB = 0b11111111 ; /* oooooooo */
PORTB = 0b00000000 ; /* 00000000 */
/* PORT C */
DDRC = 0b11111111 ; /* oooooooo */
PORTC = 0b00000000 ; /* 00000000 */
/* PORT D */
DDRD = 0b11110010 ; /* ooooiioi */
PORTD = 0b00010000 ; /* 00010000 */
/* initialize registers */
x_flags.DR = 0 ;
for ( i = 0 ; i < 32 ; i++ ) { *(memory+i) = 0 ; }
msft = 0 ;
/* initialize serial */
{
/* clear index */
rindex = 0 ;
/* clear buffer */
*(rbuf+0) = 0 ;
/* set Baud Rate Registers */
UBRR = MYUBRR ;
/* Enable receive interrupt , receive module and transmit module */
UCR = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
}
/* initialize timer1 */
{
/* clear timer/counter */
TCNT1 = 0 ;
/* set counter */
OCR1A = 9999 ;
/* Control Register 1 B */
TCCR1B = (1 << CS10) ;
}
/* Enable interrupt */
TIMSK |= (1 << OCIE1A) | (1 << TOIE0);
}
/* UART receive interrupt */
ISR(SIG_UART_RECV)
{
UBYTE ch ;
/* get 1 charactoer */
ch = UDR ;
/* store */
*(rbuf+rindex) = ch ;
rindex++ ;
/* judge */
if ( ch == '\r' ) {
SFLAG = ON ;
rindex = 0 ;
}
}
/* timer1 interrupt */
ISR(SIG_OUTPUT_COMPARE1A)
{
/* clear timer/counter */
TCNT1 = 0 ;
/* get switch data */
msft <<= 1 ;
msft &= 0xfe ;
if ( PIND & 0x20 ) { msft |= 1 ; }
if ( msft == MASKFF ) {
MFLAG = ON ;
} else {
MFLAG = OFF ;
}
/* handling */
timer_handler();
}
void rs_putchar(UBYTE x)
{
while ( !(USR & (1 <<<< UDRE)) ) {}
UDR = x ;
}
void rs_puts(UBYTE *x)
{
while ( *x != '\0' ) {
rs_putchar( *x ) ;
x++ ;
}
rs_putchar('\r');
rs_putchar('\n');
}
void write_eeprom(UWORD adr,UBYTE dat)
{
/* wait */
while ( EECR & (1 << EEWE) ) ;
/* set address */
EEARH = (UBYTE)((adr >> 8) & MASKFF);
EEARL = (UBYTE)(adr & MASKFF);
/* set data */
EEDR = dat ;
/* enable Master Write Enable */
EECR |= (1 << EEMWE) ;
/* enable Write Enable */
EECR |= (1 << EEWE);
}
UBYTE read_eeprom(UWORD adr)
{
/* wait */
while ( EECR & (1 << EEWE) ) ;
/* set address */
EEARH = (UBYTE)((adr >> 8) & MASKFF);
EEARL = (UBYTE)(adr & MASKFF);
/* enable Read Enable */
EECR |= (1 << EERE) ;
return EEDR ;
}
void push(UBYTE x)
{
stksft <<= 1 ;
stksft &= 0xfe ;
stksft |= x ;
}
UBYTE pull(void)
{
volatile UBYTE tmp ;
tmp = stksft ;
stksft >>= 1 ;
return(tmp & 1);
}
UWORD get_circuit_infomation(UWORD x)
{
volatile UBYTE dh;
volatile UBYTE dl;
volatile UWORD result ;
/* get upper byte */
dh = read_eeprom( x ) ;
/* get lower byte */
dl = read_eeprom( x+1 ) ;
/* concatenate */
result = dh ;
result <<= 8 ;
result |= dl ;
return result ;
}
void doStep(UWORD radr)
{
/* get circuit infomation from EEPROM */
operand = get_circuit_infomation( radr );
/* get operational code */
opcode = (UBYTE)(operand >> 12);
operand &= 0x0fff ;
q = ((operand & 0xff) >> 3);
r = ((operand & 0xff) & 0x07);
/* END instruction */
if ( opcode == OP_END ) return ;
/* LD LDN instruction */
if ( opcode == OP_LD || opcode == OP_LDN ) {
push( reg );
reg = *(memory+q);
reg >>= r;
reg &= 1 ;
/* inverse */
if ( opcode == OP_LDN ) { reg ^= 1 ; }
}
/* OP_AND OP_ANDN OP_OR OP_ORN instruction */
if ( opcode == OP_AND || opcode == OP_ANDN ||
opcode == OP_OR || opcode == OP_ORN ) {
regx = *(memory+q);
regx >>= r;
regx &= 1;
/* inverse */
if ( opcode == OP_ANDN || opcode == OP_ORN ) { regx ^= 1 ; }
/* AND ANDN instruction */
if ( opcode == OP_AND || opcode == OP_ANDN ) { reg &= regx ; }
/* OR ORN instruction */
if ( opcode == OP_OR || opcode == OP_ORN ) { reg |= regx ; }
}
/* OP_ANDB OP_ORB instruction */
if ( opcode == OP_ANDB || opcode == OP_ORB ) {
regx = pull();
/* block AND */
if ( opcode == OP_ANDB ) { reg &= regx ; }
/* block OR */
if ( opcode == OP_ORB ) { reg |= regx ; }
}
/* OP_OUT instruction */
if ( opcode == OP_OUT ) {
/* shift bit data */
reg <<= r ;
/* clear target bit */
*(memory+q) ^= ~(1 << r);
/* store target bit */
*(memory+q) |= reg ;
}
}
UBYTE get_hex(UBYTE x)
{
volatile UBYTE result ;
/* default */
result = 0 ;
/* select */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
/* */
return result ;
}
UWORD get_ad(UBYTE onoff)
{
volatile UWORD result ;
/* get first byte */
result = get_hex( *(rbuf+1) );
/* get second byte */
result = (result << 4) | get_hex( *(rbuf+2) );
/* get third byte */
result = (result << 4) | get_hex( *(rbuf+3) );
/* get fourth byte */
result = (result << 4) | get_hex( *(rbuf+4) );
/* compute data */
if ( onoff == ON ) {
/* get first byte */
result = get_hex( *(rbuf+5) );
/* get second byte */
result = (result << 4) | get_hex( *(rbuf+6) );
/* get third byte */
result = (result << 4) | get_hex( *(rbuf+7) );
/* get fourth byte */
result = (result << 4) | get_hex( *(rbuf+8) );
}
/* */
return result ;
}
void put_dat_eeprom(UWORD adr,UWORD dat)
{
volatile UBYTE dhl ;
/* get upper data */
dhl = (UBYTE)((dat >> 8) & MASKFF) ;
/* store */
write_eeprom( adr , dhl );
/* get lower data */
dhl = (UBYTE)(dat & MASKFF) ;
/* store */
write_eeprom( adr+1 , dhl );
}
ソースコードを眺めると、シリアルインタフェース、EEPROMを
利用しています。シリアルインタフェースはZ80SIOを利用する
だけでよいのですが、EEPROMは外付けとなります。
RTOS(Real Time Operating System)を利用しているので、タイマー
割込みでを10msを生成しなければなりません。
パラレルI/Oは、Z80PIOがあり、8ビットx2を使えますが
EEPROMを外付けするには、どちらかのチャネルをEEPROMに
割当てしないとうまくいかないでしょう。
手元には8255が2個あるので、I/Oメモリに8255を2個配置し
入力24ビット、出力24ビットとして使います。
Z84C015では、内蔵I/Oは10h〜1Fhにアサインされているので
2個の8255を、00h〜07hに配置します。
I/Oアドレスを、以下とします。
00h 8255#A_PA (input)
01h 8255#A_PB (input)
02h 8255#A_PC (input)
03h 8255#A_CTRL
04h 8255#B_PA (output)
05h 8255#B_PB (output)
06h 8255#B_PC (output)
07h 8255#B_CTRL
I/Oアドレスを、上のようにするため、74LS125、74LS139を
使います。配線は、次のように接続します。
この他に、リード、ライト信号が必要なので74LS32を利用し
負論理のAND回路を作ります。
デジタル回路がわかった時点で、入力、出力を担当する
最下位層のプログラムコードを記述します。
8255の#Aは、全ポートを入力にするので
制御レジスタに設定する値は、0x9b。
8255の#Bは、全ポートを出力にするので
制御レジスタに設定する値は、0x80。
Cのコードにすると、次のようになります。
#define I8255A 0x00
#define I8255B 0x01
#define I8255C 0x02
#define I8255W 0x03
#define O8255A 0x04
#define O8255B 0x05
#define O8255C 0x06
#define O8255W 0x07
#define I8255DDRV 0x9b
#define O8255DDRV 0x80
void set_dds(void)
{
outportb(I8255W,I8255DDRV);
outportb(O8255W,O8255DDRV);
}
入力24ビット、出力24ビットは、構造体変数の中に
配列を定義していれておけば充分でしょう。
typedef unsigned char UBYTE ;
typedef struct {
UBYTE xin[3];
UBYTE xout[3];
} IOPARAMP ;
構造体変数の内容を決めれば、入力と出力は
専用関数の中に定義するだけ。
IOPARAMP ioparam ;
void get_io(IOPARAMP iox)
{
iox.xin[0] = inportb(I8255A) ;
iox.xin[1] = inportb(I8255B) ;
iox.xin[2] = inportb(I8255C) ;
}
void put_io(IOPARAMP iox)
{
outportb(O8255A,iox.xout[0]);
outportb(O8255B,iox.xout[1]);
outportb(O8255C,iox.xout[2]);
}
コーリングシーケンスは、単純です。
入力
単純に関数get_ioを呼び出すだけです。
get_io(ioparam);
これだけで構造体変数の中に、その時点の
入力値(3バイト)を記憶できます。
出力
構造体変数の中に、値を入れて関数put_ioを
呼出すだけになります。
ioparam.xin[0] = 0x12 ;
ioparam.xin[1] = 0x34 ;
ioparam.xin[2] = 0x56 ;
put_io(ioparam);
PLCの場合、ビット単位での処理になるので
バイトアクセス処理を用意して、コードを
作成しやすくします。
1バイト中の指定ビットをセット、クリアする
関数を定義します。
UBYTE bit_set(UBYTE xdat,UBYTE xbit)
{
UBYTE result ;
/* copy */
result = xdat ;
/* judge */
if ( xbit < 8 ) { result |= (1 << xbit); }
return result ;
}
UBYTE bit_clr(UBYTE xdat,UBYTE xbit)
{
UBYTE result ;
/* copy */
result = xdat ;
/* judge */
if ( xbit < 8 ) { result &= ~(1 << xbit); }
return result ;
}
さらに指定ビットの論理反転をできるように
しておけば、使いやすくなります。
UBYTE bit_invers(UBYTE xdat,UBYTE xbit)
{
UBYTE result ;
/* copy */
result = xdat ;
/* judge */
if ( xbit < 8 ) { result ^= (1 << xbit); }
return result ;
}
これらの関数は、PLCのニモニックで次の命令を
実行する場合に使います。
LDN ANDN ORN
1ビットの値をスタックに保存、復帰することができると
スキャン処理を記述しやすくなるので、16ビットのシフト
レジスタを用意し、1ビットの値を出し入れする関数を
定義しておきます。
typedef unsigned short UWORD ;
UWORD stksft ;
void push_bit(UBYTE xdat)
{
/* shift */
stksft <<= 1 ;
/* update LSB */
stksft |= xdat ;
}
UBYTE pop_bit(void)
{
/* shift */
stksft >>= 1 ;
/* get LSB */
return(stksft & 1) ;
}
最下位層の処理を定義したので、入力、スキャン、出力の
各機能を担当タスクに割り振っていきます。
入力
入力は、タスク3に記述されているので
関数get_ioを利用して、定義します。
void tsk3_proc(void)
{
get_io(ioparam);
}
出力
出力は、タスク5に記述されているので
関数put_ioを利用して、定義します。
スキャン結果で生成された出力情報がメモリの中に
あるとして、次のように記述します。
UBYTE omemory[3] ;
void tsk5_proc(void)
{
/* copy */
ioparam.xout[0] = omemory[0] ;
ioparam.xout[1] = omemory[1] ;
ioparam.xout[2] = omemory[2] ;
/* send */
put_io(ioparam);
}
スキャン
スキャンは、タイマー割込みで10msに
呼び出される仕様とします。
タイマー割込みをトリガーにして、入力と記憶に
含まれている内容をすべて読み込み、指定されて
いる処理後、記憶と出力の内容を更新します。
(under construction)
目次
前
次