目次

I/O設計

 定義したインタプリタは、接続部品に無関係に
 スキャン処理でメモリ内容を更新していきます。

 接続部品とメモリ内容を関係づけないと、シーケンス動作
 ができません。入力メモリと出力メモリという概念を導入
 します。

 入力メモリと出力メモリの実現は、非常に簡単です。

 スキャン処理を開始する前に、入力の状態を読取り
 入力メモリに転送します。

 1スキャンが終了したなら、出力メモリの内容を
 接続部品に転送します。

 スキャン動作は、次のように関数を組み合わせて
 記述できます。
    /* get INPUT state */
    get_input_information();
    /* scanning */
    perform_scanning();
    /* put OUTPUT state */
    update_output();

 関数get_input_informationが、入力の状態を入力メモリ
 に反映させます。

 関数update_outputが、出力メモリの内容を出力に反映
 させます。

 2つの関数とマイコン周辺の回路を設計します。


入力回路と関数

 入力の状態を入力メモリに反映させるには、入力ピン  からデータを取得して、格納するだけで充分です。  入力に接続できるスイッチ、センサーをいくつにするか  決めれば、関数を作成できます。  16ビット分を入力することにします。  ノイズ防止と過大入力から、マイコンを保護するために  次の回路を接続します。  フォトカプラ(TLP521-4)を利用し、ノイズ防止、過大  入力保護の双方を実現します。  フォトカプラの出力をラッチ(74HC574)に入力します。  ラッチは、マイコンからのトリガーで入力状態を確定します。  ラッチで、入力状態記憶後、マイコンは8ビットずつデータ  を取り込みます。  関数get_input_informationの動作シーケンスです。
  1. ラッチトリガー出力
  2. nOEAをイネーブルにし、8ビットデータ入力
  3. nOEAをディセーブル
  4. 入力8ビットデータを、配列に転送
  5. nOEBをイネーブルにし、8ビットデータ入力
  6. 入力8ビットデータを、配列に転送
  7. nOEBをディセーブル
 16ビットデータを、8ビットずつ2回に分けて  配列memoryに転送します。  インタプリタが扱うメモリには、ビット番号を振って  あるので、ビット番号0〜15に相当するエリアに転送  します。  マイコンのピンに、機能を割当てます。  仕様ができたので、コードを作成します。 #define ITRG 0 #define OEA 1 #define OEB 1 void get_input_information(void) { /* send latch trigger */ PORTB |= (1 << ITRG) ; PORTB &= ~(1 << ITRG) ; /* enable nOEA */ PORTB &= ~(1 << OEA) ; /* get data */ *(memory+0) = PINA ; /* disable OEA */ PORTB |= (1 << OEA) ; /* enable nOEB */ PORTB &= ~(1 << OEB) ; /* get data */ *(memory+1) = PINA ; /* disable OEA */ PORTB |= (1 << OEB) ; }

出力回路と関数

 出力メモリの内容を出力に反映させるには、出力ピン  へデータを出力するだけです。  出力に接続できるアクチュエータをいくつにするか  決めれば、関数を作成できます。  16ビット分を出力することにします。  ノイズ防止と出力側から、マイコンを保護するために  次の回路を接続します。  ラッチ(74HC574)を使い、出力メモリの16ビット分を  外部に引き出します。さらに、ラッチ(74HC574)出力  を、フォトカプラに接続します。  フォトカプラ(TLP521-4)を利用し、ノイズ防止、外部  からの回込み過大入力から保護します。  関数update_outputの動作シーケンスです。
  1. 配列から出力メモリの内容を取得し出力
  2. OTRGAにラッチパルス出力
  3. 配列から出力メモリの内容を取得し出力
  4. OTRGBにラッチパルス出力
 16ビットデータを、8ビットずつ2回に分けて  配列memoryから転送します。  インタプリタが扱うメモリには、ビット番号を振って  あるので、ビット番号16〜31に相当するエリアから  転送します。  マイコンのピンに、機能を割当てます。  仕様ができたので、コードを作成します。 #define OTRGA 4 #define OTRGB 5 void update_output(void) { /* set data */ PORTC = *(memory+2) ; /* send latch pulse */ PORTB |= (1 << OTRGA) ; PORTB &= ~(1 << OTRGA) ; /* set data */ PORTC = *(memory+3) ; /* send latch pulse */ PORTB |= (1 << OTRGB) ; PORTB &= ~(1 << OTRGB) ; }  出力イネーブル信号は、出力メモリの初期状態を決めて  から、ラッチの出力をフォトカプラに伝達する目的  で利用します。  出力にはアクチュエータが接続されているので、不用意な  動作は重大事故を起こす原因になります。  出力イネーブルを用意すると、緊急停止と初期状態を  確定するまで、出力アクチュエータを停止させること  ができます。  PLCを実現するマイコンの起動時に、出力メモリの状態を  確定後、出力イネーブル信号をイネーブルにします。  最近は、74HCの500番シリーズは入手しにくいので  CPLDの中に、I/O用レジスタを入れることが多くなり  ました。  XC95108を使う場合のVHDLコードは、以下です。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity mpreg is port( -- system nRESET : in std_logic; CLOCK : in std_logic; -- sequencer inputs SelInp : in std_logic ; Din : out std_logic_vector(7 downto 0); -- sequencer outputs TRGW : in std_logic ; SelOut : in std_logic ; Dout : in std_logic_vector(7 downto 0); -- I/O input IOinp : in std_logic_vector(15 downto 0) ; IOout : out std_logic_vector(15 downto 0) --; ); end mpreg; architecture behavioral of mpreg is -- trigger signal iTRGW : std_logic ; signal iTRGW_SFT : std_logic_vector(2 downto 0) ; -- inputs register signal iIOregIn : std_logic_vector(15 downto 0); -- outputs register signal iIOregOut : std_logic_vector(15 downto 0); begin -- trigger process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iTRGW_SFT <= "000" ; elsif rising_edge( CLOCK ) then iTRGW_SFT <= iTRGW_SFT(1 downto 0) & TRGW ; end if ; end process ; iTRGW <= '1' when ( iTRGW_SFT = "011" or iTRGW_SFT = "001" ) else '0' ; -- inputs process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iIOregIn <= (others => '0') ; elsif rising_edge( CLOCK ) then iIOregIn <= IOinp ; end if ; end process ; Din <= iIOregIn(15 downto 8) when ( SelInp = '1' ) else iIOregIn(7 downto 0); -- outputs process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iIOregOut <= (others => '0') ; elsif rising_edge( CLOCK ) then if ( iTRGW = '1' ) then if ( SelOut = '1' ) then iIOregOut(15 downto 8) <= Dout ; else iIOregOut( 7 downto 0) <= Dout ; end if ; end if ; end if ; end process ; IOout <= iIOregOut ; end behavioral;  ピンアサインは、以下としました。 # system NET "CLOCK" LOC = "P9" ; NET "nRESET" LOC = "P74" ; # I/O inputs NET "SelInp" LOC = "P11" ; NET "Din<7>" LOC = "P10" ; NET "Din<6>" LOC = "P7" ; NET "Din<5>" LOC = "P6" ; NET "Din<4>" LOC = "P5" ; NET "Din<3>" LOC = "P4" ; NET "Din<2>" LOC = "P3" ; NET "Din<1>" LOC = "P2" ; NET "Din<0>" LOC = "P1" ; # I/O outputs NET "TRGW" LOC = "P23" ; NET "SelOut" LOC = "P21" ; NET "Dou<7>" LOC = "P20" ; NET "Dou<6>" LOC = "P19" ; NET "Dou<5>" LOC = "P18" ; NET "Dou<4>" LOC = "P17" ; NET "Dou<3>" LOC = "P15" ; NET "Dou<2>" LOC = "P14" ; NET "Dou<1>" LOC = "P13" ; NET "Dou<0>" LOC = "P12" ; # inputs NET "IOinp<15>" LOC = "P65" ; NET "IOinp<14>" LOC = "P63" ; NET "IOinp<13>" LOC = "P62" ; NET "IOinp<12>" LOC = "P61" ; NET "IOinp<11>" LOC = "P58" ; NET "IOinp<10>" LOC = "P57" ; NET "IOinp<9>" LOC = "P56" ; NET "IOinp<8>" LOC = "P55" ; NET "IOinp<7>" LOC = "P54" ; NET "IOinp<6>" LOC = "P53" ; NET "IOinp<5>" LOC = "P52" ; NET "IOinp<4>" LOC = "P51" ; NET "IOinp<3>" LOC = "P50" ; NET "IOinp<2>" LOC = "P48" ; NET "IOinp<1>" LOC = "P47" ; NET "IOinp<0>" LOC = "P46" ; # outputs NET "IOout<15>" LOC = "P84" ; NET "IOout<14>" LOC = "P83" ; NET "IOout<13>" LOC = "P82" ; NET "IOout<12>" LOC = "P81" ; NET "IOout<11>" LOC = "P80" ; NET "IOout<10>" LOC = "P79" ; NET "IOout<9>" LOC = "P77" ; NET "IOout<8>" LOC = "P76" ; NET "IOout<7>" LOC = "P75" ; NET "IOout<6>" LOC = "P72" ; NET "IOout<5>" LOC = "P71" ; NET "IOout<4>" LOC = "P70" ; NET "IOout<3>" LOC = "P69" ; NET "IOout<2>" LOC = "P68" ; NET "IOout<1>" LOC = "P67" ; NET "IOout<0>" LOC = "P66" ;
目次

inserted by FC2 system