目次
前
次
命令検討
ラダー図で記述された回路情報を、PLCで実行するために
命令を利用して入力します。
ラダー図の情報を命令に変換するアプリケーションを作成
すればよいのですが、それは後にします。
基本となる命令は、論理演算(論理積、論理和、反転)と
リレーコイルの出力に限定します。
カウンタやタイマーも必要ですが、基本命令の動作確認が
とれてからとします。
PLCの入力には、A接点、B接点が接続されます。
接点情報は、1か0の論理値で表現します。
A接点は、通常0でボタンを押すと1になります。
B接点は、通常1でボタンを押すと0になります。
この2接点の状態を入力できるように命令を定義します。
- OUT レジスタの1ビットデータ出力
- LD A接点データを入力し、レジスタに保存
- LDN B接点データを入力し、レジスタに保存
- AND A接点データとの論理積を求めレジスタに保存
- ANDN B接点データとの論理積を求めレジスタに保存
- OR A接点データとの論理和を求めレジスタに保存
- ORN B接点データとの論理和を求めレジスタに保存
- ANDB ブロック間の論理積を求めレジスタに保存
- ORB ブロック間の論理和を求めレジスタに保存
- SETC カウンタに値を設定
- INC カウンタの値に+1して、再設定
- DEC カウンタの値に−1して、再設定
- SETT タイマーの値を設定
- COND 判定
- JUMP 指定ラインに分岐
- JMPZ 条件を使い、指定ラインに分岐
- END スキャン停止
命令だけでは、どの接点であるとか出力の情報が不明です。
そこで、マイコンの中にあるメモリの指定ビット番号で対応
をとります。
ANDB、ORB、ENDには、指定ビット番号の情報は不要です。
フォーマットは、次のようにします。
- OUT memory bit number
- LD memory bit number
- LDN memory bit number
- AND memory bit number
- ANDN memory bit number
- OR memory bit number
- ORN memory bit number
- ANDB
- ORB
- SETC counter_number value
- INC counter_number
- DEC counter_number
- SETT timer_counter_number value
- COND counter_number value
- JUMP line_number
- JMPZ line_number
- END
ビット番号とメモリサイズ
命令の中には、ビット番号とパラメータを
必要とするものがあります。
ビット番号を0〜255の256とします。
8ビットマイコンのレジスタ幅が、1バイトで
あっても扱える範囲とします。
256ビットは、バイトで換算すると32バイト
になるので、配列で次のように領域を確保します。
#define MSIZE 32
unsigned char memory[MSIZE] ;
マイコンによっては、32バイトを確保できない
場合もありえます。その時は、MSIZEの値を小さく
して調整します。
ビット番号は、0〜255の8ビットで指定するので
1命令は8ビットよりも大きくなります。
切りのよいところで、1命令を16ビットで表現します。
カウンタ番号とメモリ
命令の中には、カウンタ番号とパラメータを
必要とするものがあります。
カウンタ番号は、0〜15とします。
カウンタには、カウンタとタイマーカウンタがあります。
カウンタのビットサイズは、8ビットとします。
#define CSIZE 16
unsigned char counter[CSIZE] ;
タイマーカウンタは、10msのものと100msの2種類
利用できるようにします。
0から7は10msタイマー、8から15は100msタイマー
とします。
#define CTSIZE 8
unsigned char t000cnt[CTSIZE] ;
unsigned char t100cnt[CTSIZE] ;
命令フォーマット
ラダー図で記述された回路情報は、命令としてEEPROMに
保存します。
1命令=16ビットとしたので、16ビットの内部フォーマット
を仕様としてまとめます。
16ビットの下位8ビットをビット番号指定に利用します。
上位8ビットは、命令を上位ニブルに格納します。
下位ニブルは、タイマー、カウンタ命令を拡張するために
残しておきます。
各命令と16ビットの内容は、次のようにします。
(bは、1か0を表わすことにします。)
- END : 0000 0000 0000 0000
- OUT memory bit number : 0001 0000 bbbb bbbb
- LD memory bit number : 0010 0000 bbbb bbbb
- LDN memory bit number : 0011 0000 bbbb bbbb
- AND memory bit number : 0100 0000 bbbb bbbb
- ANDN memory bit number : 0101 0000 bbbb bbbb
- OR memory bit number : 0110 0000 bbbb bbbb
- ORN memory bit number : 0111 0000 bbbb bbbb
- ANDB : 1000 0000 0000 0000
- ORB : 1001 0000 0000 0000
- SETC counter_number value : 1010 bbbb ???? ????
- INC counter_number : 1011 bbbb 0000 0000
- DEC counter_number : 1100 bbbb 0000 0000
- SETT timer_counter_number value : 1101 0bbb ???? ???? ( 10ms timer)
- SETT timer_counter_number value : 1101 1bbb ???? ???? (100ms timer)
- COND counter_number value : 1110 bbbb ???? ????
- JUMP line_number value : 1111 00?? ???? ????
- JMPZ condtion line_number value : 1111 01?? ???? ????
EEPROMへの格納は、ビックエンディアンとします。
アドレスが小さい1バイトに、命令コードを含んだ8ビットを格納。
アドレスが大きい1バイトに、ビット番号かパラメータを格納。
ラダー行数とEEPROMサイズ
ラダーの1行を、1命令=16ビットで表現する仕様
としたので、EEPROMサイズで格納可能できる行数が
決まります。
最近は、128kバイトの容量をもつシリアルEEPROMも、
ワンコイン¥500以内で入手できるので、64x1024行
程度まで対応できます。
人間が管理できる上限行数は、1000行程度でしょう。
1024行として、EEPROMのサイズは2048バイトです。
最大1024行まで、ラダー図で表現できるとします。
関数定義
ラダーの1行を、1命令=16ビットで表現する仕様を
確定したので、関連する関数を定義します。
ファームウエアの雛形で、利用関数は別途定義とした
ので、EERPOMに関係する関数を定義します。
get_adr
シリアル受信バッファから、EEPROMアドレスを取得します。
EEPROMのアドレスは、0〜1023行まで指定できる仕様にした
ので、16ビットの値を返します。
typedef unsigned short UWORD ;
UWORD get_adr(void)
{
return 0 ;
}
受信バッファrbufが配列で確保されているとします。
受信バッファには、1文字コマンド、パラメータの順で
データが格納されているとします。
受信バッファに格納されている1文字は、英数字なので
数値に変換しなければなりません。
この変換関数が、get_hexで定義済みと仮定します。
typedef unsigned short UWORD ;
UWORD get_adr(void)
{
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) );
return result ;
}
get_dat
シリアル受信バッファから、EEPROMデータを取得します。
EEPROMのデータは、2バイトとしたので、16ビットの値を
返します。
typedef unsigned short UWORD ;
UWORD get_dat(void)
{
return 0 ;
}
受信バッファrbufには、アドレス、データと続けて
確保されているとします。
受信バッファに格納されている1文字は、英数字
なので数値に変換します。
typedef unsigned short UWORD ;
UWORD get_dat(void)
{
UWORD result ;
/* 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 ;
}
put_dat_eeprom
アドレスとデータをパラメータとして、EEPROMに
2バイトのデータを保存します。
アドレス、データとも16ビットなので、次のように
定義します。
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
void put_dat_eeprom(UWORD adr,UWORD dat)
{
}
指定アドレスには、16ビットの上位を
指定アドレス+1には、下位を格納します。
1バイトの格納用関数write_eepromは定義
済みと仮定します。
void put_dat_eeprom(UWORD adr,UWORD dat)
{
UBYTE dhl ;
/* get upper byte */
dhl = (UBYTE)(dat >> 8) ;
/* store upper byte */
write_eeprom( adr , dhl ) ;
/* get lower byte */
dhl = (UBYTE)(dat & 0xff) ;
/* store lowerr byte */
write_eeprom( adr+1 , dhl ) ;
}
get_hex
16進数字を16進数値に変換します。
typedef unsigned char UBYTE ;
UBYTE get_hex(UBYTE x)
{
return 0 ;
}
'0'〜'9'、'A'〜'F'、'a'〜'f'を0〜9、10〜15、10〜15
に変換します。
typedef unsigned char UBYTE ;
UBYTE get_hex(UBYTE x)
{
UBYTE result ;
/* default */
result = 0 ;
/* '0' -- '9' */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
/* 'A' -- 'F' */
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
/* 'a' -- 'f' */
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
目次
前
次