目次

ラップタイマー作成

 軽量マシン、産業用モータ利用マシンが完成したので
 どのくらいの時間でコースを1周できるのか、測定を
 してみることにしました。

 コース横にストップウォッチを用意するよりも
 マイコン、CPLD/FPGAを使った計時装置を用意
 する方が、いろいろと応用が利くと考えラップ
 タイマーを作成しました。



 この大型LEDは、秋月電子で販売されていたキットを
 流用しました。

 本キットの回路図は、以下でした。



 ダイナミック点灯でラップタイム表示するため
 電源電圧を12Vとしたインタフェース回路を
 次のようにしました。



 7セグメントLEDは、アノードコモンなので
 1けた毎に、電源を与えられるように、小信号
 トランジスタを導通させます。

 インタフェース回路は、基板に小さくまとめました。



 表示回路が完成したので、ラップタイマーのファームウエア
 あるいはデジタル回路を考えます。

 今回は、デジタル回路で実現します。
 デジタル回路を多数入れられる、CPLDを
 利用します。

 CPLDの中に入れるデジタル回路は、VHDLで
 記述します。

 表示はダイナミック点灯なので、ビットパターン
 を出力後、けた選択信号を出力します。

 シーケンスは、以下のようにしました。
  1. 1000の位の値をデコードし出力
  2. 1000の位を選択
  3. 100の位の値をデコードし出力
  4. 100の位を選択
  5. 10の位の値をデコードし出力
  6. 10の位を選択
  7. 1の位の値をデコードし出力
  8. 1の位を選択
 シーケンサ実現するには、カウンタが必要なので  バイナリカウンタを使います。  カウンタの値を利用して、セレクタとエキサイタを  制御します。 -- display controller process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iDSTATE <= 0 ; elsif rising_edge(iMCLK) then -- counter handling if ( iDSTATE = 8 ) then iDSTATE <= 0 ; else iDSTATE <= iDSTATE + 1 ; end if ; end if ; end process ; iDIN0 <= conv_std_logic_vector(iA1000,4) ; iDIN1 <= conv_std_logic_vector(iA100 ,4) ; iDIN2 <= conv_std_logic_vector(iA10 ,4) ; iDIN3 <= conv_std_logic_vector(iA1 ,4) ; -- selector iDOUT <= iDOUT0 when ( iDSTATE = 0 ) else iDOUT1 when ( iDSTATE = 2 ) else iDOUT2 when ( iDSTATE = 4 ) else iDOUT3 when ( iDSTATE = 6 ) else (others => '0') ; -- exciter iDSPENABLE <= "1000" when ( iDSTATE = 0 or iDSTATE = 1 ) else "0100" when ( iDSTATE = 2 or iDSTATE = 3 ) else "0010" when ( iDSTATE = 4 or iDSTATE = 5 ) else "0001" when ( iDSTATE = 6 or iDSTATE = 7 ) else "0000" ;  ラップタイマーの最小分解能は、0.1秒として  10の位に小数点を出力します。  10進カウンタの値を、7セグメントLEDの  ビットパターンに変換するコードは、別に  定義しました。  4ビット入力7ビット出力の組合せ回路で  実現しました。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ledx is port ( -- input DIN : in std_logic_vector(3 downto 0); -- output DOUT : out std_logic_vector(6 downto 0) --; ); end ledx ; architecture Behavioral of ledx is signal iDOUT : std_logic_vector(6 downto 0) ; begin -- output DOUT <= iDOUT ; -- conversion -- abcdefg iDOUT <= "1111110" when ( conv_integer(DIN) = 0 ) else "0110000" when ( conv_integer(DIN) = 1 ) else "1101101" when ( conv_integer(DIN) = 2 ) else "1111001" when ( conv_integer(DIN) = 3 ) else "0110011" when ( conv_integer(DIN) = 4 ) else "1011011" when ( conv_integer(DIN) = 5 ) else "1011111" when ( conv_integer(DIN) = 6 ) else "1110010" when ( conv_integer(DIN) = 7 ) else "1111111" when ( conv_integer(DIN) = 8 ) else "1111011" when ( conv_integer(DIN) = 9 ) else "1111111" ; end Behavioral;  100msでラップを刻みますが、スタート/ゴールを横切った  ことをセンシングするためには、10ms周期のクロックを利用  した方が楽です。  複数のクロックを利用するので、クロックを扱うコードを  定義して利用します。  これまで利用してきたクロックジェネレータを利用します。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end clkgenx; architecture Behavioral of clkgenx is signal iSCNT : std_logic_vector(TOPX-1 downto 0); signal iCLK : std_logic ; begin -- output CLKOUT <= iCLK ; -- divider process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iSCNT <= (others => '0') ; iCLK <= '0' ; elsif rising_edge(CLOCK) then if ( conv_integer(iSCNT) = RMAX ) then iSCNT <= (others => '0') ; iCLK <= not iCLK ; else iSCNT <= iSCNT + '1' ; end if ; end if ; end process ; end Behavioral;  マシンが、スタート/ゴールを横切ったかどうかは  フォトセンサーでとらえるとします。  センシングには、シフトレジスタを利用した  シンクロナイザで対応します。  シフトレジスタのクロックは、10ms周期として  以下のようにしました。 process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iTRG_SFT <= "000" ; elsif rising_edge(iMCLK) then iTRG_SFT <= iTRG_SFT(1 downto 0) & iSETRG ; end if ; end process ; iTRG <= '1' when ( iTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ;  スタートとゴールのトリガーを同じにし  その間、ラップを刻むようにシーケンサ  を定義します。 iENABLE <= iSTATE(0) ; process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= "00" ; elsif rising_edge(iMCLK) then case conv_integer(iSTATE) is -- wait start trigger when 0 => if ( iTRG = '1' ) then iSTATE <= "01" ; end if ; -- automatic transfer when 1 => iSTATE <= "11" ; -- wait exit trigger when 3 => if ( iTRG = '1' ) then iSTATE <= "10" ; end if ; when 2 => iSTATE <= "00" ; -- default when others => iSTATE <= "00" ; end case ; end if ; end process ;  Johnson Counterを利用し、デコーダを不要にしています。  シーケンサの出力信号で、ラップを刻むカウンタを  動かします。  4ビットカウンタを、4つ用意して  カウントアップします。 process (nRESET,iPCLK) begin if ( nRESET = '0' ) then iA1000 <= 0 ; iA100 <= 0 ; iA10 <= 0 ; iA1 <= 0 ; elsif rising_edge(iPCLK) then if ( iENABLE = '1' ) then -- increment 100ms iA1 <= iA1 + 1 ; if ( iA1 = 10 ) then iA1 <= 0 ; iA10 <= iA10 + 1 ; end if ; -- clear 1s if ( iA10 = 10 ) then iA10 <= 0 ; iA100 <= iA100 + 1 ; end if ; -- clear 10s if ( iA100 = 10 ) then iA100 <= 0 ; iA1000 <= iA1000 + 1 ; end if ; -- clear 100s if ( iA1000 = 10 ) then iA1000 <= 0 ; end if ; end if ; end if ; end process ;  マスタークロックを1.8434MHzとし、CPLDにはXC9572XLを  利用します。全体をまとめると、以下です。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ledc is generic ( TOPX : integer := 10 ; RMAX : integer := 922 --; ); port( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- input SETRG : in std_logic ; -- output GLED : out std_logic ; DSPENABLE : out std_logic_vector(3 downto 0) ; LEDP : out std_logic_vector(7 downto 0) --; ); end ledc; architecture Behavioral of ledc is -- clock component component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; -- LED pattern generator component ledx is port ( -- input DIN : in std_logic_vector(3 downto 0); -- output DOUT : out std_logic_vector(6 downto 0) --; ); end component ; -- clock generator signal iMCLK : std_logic ; signal iPCLK : std_logic ; signal iDCLK : std_logic ; signal iCNT : integer range 0 to 50 ; -- latch trigger signal iSETRG : std_logic ; signal iTRG : std_logic ; signal iTRG_SFT : std_logic_vector(2 downto 0) ; -- run sequencer signal iSTATE : std_logic_vector(1 downto 0) ; signal iENABLE : std_logic ; -- counter signal iA1000 : integer range 0 to 10 ; signal iA100 : integer range 0 to 10 ; signal iA10 : integer range 0 to 10 ; signal iA1 : integer range 0 to 10 ; signal iDIN0 : std_logic_vector(3 downto 0) ; signal iDOUT0 : std_logic_vector(6 downto 0) ; signal iDIN1 : std_logic_vector(3 downto 0) ; signal iDOUT1 : std_logic_vector(6 downto 0) ; signal iDIN2 : std_logic_vector(3 downto 0) ; signal iDOUT2 : std_logic_vector(6 downto 0) ; signal iDIN3 : std_logic_vector(3 downto 0) ; signal iDOUT3 : std_logic_vector(6 downto 0) ; signal iDOUT : std_logic_vector(6 downto 0) ; -- 7 segment led controller signal iDSTATE : integer range 0 to 8 ; signal iDSPENABLE : std_logic_vector(3 downto 0) ; signal iLEDP : std_logic_vector(7 downto 0) ; begin -- clock generator CLKP : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iMCLK); -- LED pattern generator LEDPX0 : ledx port map (iDIN0,iDOUT0); LEDPX1 : ledx port map (iDIN1,iDOUT1); LEDPX2 : ledx port map (iDIN2,iDOUT2); LEDPX3 : ledx port map (iDIN3,iDOUT3); -- input iSETRG <= not SETRG ; -- output DSPENABLE <= iDSPENABLE ; LEDP <= iLEDP ; GLED <= not iENABLE ; -- internal handling iLEDP(7) <= '1' when( iDSTATE = 4 or iDSTATE = 5 ) else '0' ; iLEDP(6 downto 0) <= iDOUT ; -- clock divider process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iCNT <= 0 ; iPCLK <= '0' ; elsif rising_edge(iMCLK) then -- judge if ( iCNT = 50 ) then iCNT <= 0 ; iPCLK <= not iPCLK ; else -- increment iCNT <= iCNT + 1 ; end if ; end if ; end process ; -- trigger handler process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iTRG_SFT <= "000" ; elsif rising_edge(iMCLK) then iTRG_SFT <= iTRG_SFT(1 downto 0) & iSETRG ; end if ; end process ; iTRG <= '1' when ( iTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ; -- counter process (nRESET,iPCLK) begin if ( nRESET = '0' ) then iA1000 <= 0 ; iA100 <= 0 ; iA10 <= 0 ; iA1 <= 0 ; elsif rising_edge(iPCLK) then if ( iENABLE = '1' ) then -- increment 100ms iA1 <= iA1 + 1 ; if ( iA1 = 10 ) then iA1 <= 0 ; iA10 <= iA10 + 1 ; end if ; -- clear 1s if ( iA10 = 10 ) then iA10 <= 0 ; iA100 <= iA100 + 1 ; end if ; -- clear 10s if ( iA100 = 10 ) then iA100 <= 0 ; iA1000 <= iA1000 + 1 ; end if ; -- clear 100s if ( iA1000 = 10 ) then iA1000 <= 0 ; end if ; end if ; end if ; end process ; -- run sequencer iENABLE <= iSTATE(0) ; process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= "00" ; elsif rising_edge(iMCLK) then case conv_integer(iSTATE) is -- wait start trigger when 0 => if ( iTRG = '1' ) then iSTATE <= "01" ; end if ; -- automatic transfer when 1 => iSTATE <= "11" ; -- wait exit trigger when 3 => if ( iTRG = '1' ) then iSTATE <= "10" ; end if ; when 2 => iSTATE <= "00" ; -- default when others => iSTATE <= "00" ; end case ; end if ; end process ; -- display controller process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iDSTATE <= 0 ; elsif rising_edge(iMCLK) then -- counter handling if ( iDSTATE = 8 ) then iDSTATE <= 0 ; else iDSTATE <= iDSTATE + 1 ; end if ; end if ; end process ; iDIN0 <= conv_std_logic_vector(iA1000,4) ; iDIN1 <= conv_std_logic_vector(iA100 ,4) ; iDIN2 <= conv_std_logic_vector(iA10 ,4) ; iDIN3 <= conv_std_logic_vector(iA1 ,4) ; -- selector iDOUT <= iDOUT0 when ( iDSTATE = 0 ) else iDOUT1 when ( iDSTATE = 2 ) else iDOUT2 when ( iDSTATE = 4 ) else iDOUT3 when ( iDSTATE = 6 ) else (others => '0') ; -- exciter iDSPENABLE <= "1000" when ( iDSTATE = 0 or iDSTATE = 1 ) else "0100" when ( iDSTATE = 2 or iDSTATE = 3 ) else "0010" when ( iDSTATE = 4 or iDSTATE = 5 ) else "0001" when ( iDSTATE = 6 or iDSTATE = 7 ) else "0000" ; end Behavioral;  XC9572XLのピンアサインは、以下としました。 NET "nRESET" LOC = "P33" ; NET "CLOCK" LOC = "P1" ; # group A NET "LEDP<7>" LOC = "P36" ; NET "LEDP<6>" LOC = "P37" ; NET "LEDP<5>" LOC = "P38" ; NET "LEDP<4>" LOC = "P39" ; NET "LEDP<3>" LOC = "P40" ; NET "LEDP<2>" LOC = "P41" ; NET "LEDP<1>" LOC = "P42" ; NET "LEDP<0>" LOC = "P43" ; # group B NET "DSPENABLE<0>" LOC = "P34" ; NET "DSPENABLE<1>" LOC = "P32" ; NET "DSPENABLE<2>" LOC = "P31" ; NET "DSPENABLE<3>" LOC = "P30" ; # group C(7bits) NET "SETRG" LOC = "P7" ; NET "GLED" LOC = "P2" ;  動かしてみると、常に4けたに数値を表示しています。  省エネの観点から、ゼロプレス処理を入れました。  最下位けたは常に表示し、他のけたは、0であることを  判定して、エキサイタを動かすかどうかを決めます。  3つのけたが、0かどうかをフラグで設定します。 iZF3 <= '1' when ( iA1000 = 0 ) else '0' ; iZF2 <= '1' when ( iA100 = 0 ) else '0' ; iZF1 <= '1' when ( iA10 = 0 ) else '0' ;  エキサイタの各ビットを、判定条件を入れて1か0に  設定します。 iDSPENABLE(3) <= '1' when ( iDSTATE = 1 and iZF3 = '0' ) else '0' ; iDSPENABLE(2) <= '1' when ( iDSTATE = 3 and iZF3 = '0' ) else '1' when ( iDSTATE = 3 and iZF2 = '0' ) else '0' ; iDSPENABLE(1) <= '1' when ( iDSTATE = 5 and iZF3 = '0' ) else '1' when ( iDSTATE = 5 and iZF2 = '0' ) else '1' when ( iDSTATE = 5 and iZF1 = '0' ) else '0' ; iDSPENABLE(0) <= '1' when ( iDSTATE = 7 ) else '0' ;  まとめると、以下となります。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ledc is generic ( TOPX : integer := 10 ; RMAX : integer := 922 --; ); port( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- input SETRG : in std_logic ; -- output GLED : out std_logic ; DSPENABLE : out std_logic_vector(3 downto 0) ; LEDP : out std_logic_vector(7 downto 0) --; ); end ledc; architecture Behavioral of ledc is -- clock component component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; -- LED pattern generator component ledx is port ( -- input DIN : in std_logic_vector(3 downto 0); -- output DOUT : out std_logic_vector(6 downto 0) --; ); end component ; -- clock generator signal iMCLK : std_logic ; signal iPCLK : std_logic ; signal iDCLK : std_logic ; signal iCNT : integer range 0 to 50 ; -- latch trigger signal iSETRG : std_logic ; signal iTRG : std_logic ; signal iTRG_SFT : std_logic_vector(2 downto 0) ; -- run sequencer signal iSTATE : std_logic_vector(1 downto 0) ; signal iENABLE : std_logic ; -- counter signal iA1000 : integer range 0 to 10 ; signal iA100 : integer range 0 to 10 ; signal iA10 : integer range 0 to 10 ; signal iA1 : integer range 0 to 10 ; signal iDIN : std_logic_vector(3 downto 0) ; signal iDOUT : std_logic_vector(6 downto 0) ; signal iZF3 : std_logic ; signal iZF2 : std_logic ; signal iZF1 : std_logic ; -- 7 segment led controller signal iDSTATE : integer range 0 to 8 ; signal iDSPENABLE : std_logic_vector(3 downto 0) ; signal iLEDP : std_logic_vector(7 downto 0) ; begin -- clock generator CLKP : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iMCLK); -- LED pattern generator LEDPX0 : ledx port map (iDIN,iDOUT); -- input iSETRG <= not SETRG ; -- output DSPENABLE <= iDSPENABLE ; LEDP <= iLEDP ; GLED <= not iENABLE ; -- internal handling iLEDP(7) <= '1' when( iDSTATE = 4 or iDSTATE = 5 ) else '0' ; iLEDP(6 downto 0) <= iDOUT ; -- clock divider process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iCNT <= 0 ; iPCLK <= '0' ; elsif rising_edge(iMCLK) then -- judge if ( iCNT = 50 ) then iCNT <= 0 ; iPCLK <= not iPCLK ; else -- increment iCNT <= iCNT + 1 ; end if ; end if ; end process ; -- trigger handler process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iTRG_SFT <= "000" ; elsif rising_edge(iMCLK) then iTRG_SFT <= iTRG_SFT(1 downto 0) & iSETRG ; end if ; end process ; iTRG <= '1' when ( iTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ; -- counter process (nRESET,iPCLK) begin if ( nRESET = '0' ) then iA1000 <= 0 ; iA100 <= 0 ; iA10 <= 0 ; iA1 <= 0 ; elsif rising_edge(iPCLK) then if ( iENABLE = '1' ) then -- increment 100ms iA1 <= iA1 + 1 ; if ( iA1 = 10 ) then iA1 <= 0 ; iA10 <= iA10 + 1 ; end if ; -- clear 1s if ( iA10 = 10 ) then iA10 <= 0 ; iA100 <= iA100 + 1 ; end if ; -- clear 10s if ( iA100 = 10 ) then iA100 <= 0 ; iA1000 <= iA1000 + 1 ; end if ; -- clear 100s if ( iA1000 = 10 ) then iA1000 <= 0 ; end if ; end if ; end if ; end process ; iZF3 <= '1' when ( iA1000 = 0 ) else '0' ; iZF2 <= '1' when ( iA100 = 0 ) else '0' ; iZF1 <= '1' when ( iA10 = 0 ) else '0' ; -- run sequencer iENABLE <= iSTATE(0) ; process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= "00" ; elsif rising_edge(iMCLK) then case conv_integer(iSTATE) is -- wait start trigger when 0 => if ( iTRG = '1' ) then iSTATE <= "01" ; end if ; -- automatic transfer when 1 => iSTATE <= "11" ; -- wait exit trigger when 3 => if ( iTRG = '1' ) then iSTATE <= "10" ; end if ; when 2 => iSTATE <= "00" ; -- default when others => iSTATE <= "00" ; end case ; end if ; end process ; -- display controller process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iDSTATE <= 0 ; elsif rising_edge(iMCLK) then -- counter handling if ( iDSTATE = 8 ) then iDSTATE <= 0 ; else iDSTATE <= iDSTATE + 1 ; end if ; end if ; end process ; iDIN <= conv_std_logic_vector(iA1000,4) when ( iDSTATE = 0 or iDSTATE = 1 ) else conv_std_logic_vector(iA100 ,4) when ( iDSTATE = 2 or iDSTATE = 3 ) else conv_std_logic_vector(iA10 ,4) when ( iDSTATE = 4 or iDSTATE = 5 ) else conv_std_logic_vector(iA1 ,4) ; -- exciter iDSPENABLE(3) <= '1' when ( iDSTATE = 1 and iZF3 = '0' ) else '0' ; iDSPENABLE(2) <= '1' when ( iDSTATE = 3 and iZF3 = '0' ) else '1' when ( iDSTATE = 3 and iZF2 = '0' ) else '0' ; iDSPENABLE(1) <= '1' when ( iDSTATE = 5 and iZF3 = '0' ) else '1' when ( iDSTATE = 5 and iZF2 = '0' ) else '1' when ( iDSTATE = 5 and iZF1 = '0' ) else '0' ; iDSPENABLE(0) <= '1' when ( iDSTATE = 7 ) else '0' ; end Behavioral;  CPLDで動作確認できたので、マイコンでも実現しました。 #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define OFF 0 #define ON OFF+1 typedef unsigned char UBYTE ; typedef unsigned short UWORD ; #define SMAX 10 #define TMAX 100 #define MASKF0 0xf0 #define DSPA1000 0x08 #define DSPA100 0x04 #define DSPA10 0x02 #define DSPA1 0x01 #define DLAST 8 volatile UBYTE sft ; volatile UBYTE sflag ; volatile UBYTE iflag ; volatile UBYTE state ; volatile UBYTE scntx ; volatile UBYTE tcntx ; volatile UBYTE tflag ; volatile UBYTE dflag ; volatile UBYTE a1 ; volatile UBYTE a10 ; volatile UBYTE a100 ; volatile UBYTE a1000 ; volatile UBYTE dstate ; volatile UBYTE ledpat[10] ; volatile UBYTE izf3 ; volatile UBYTE izf2 ; volatile UBYTE izf1 ; /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); void dsp_proc(void); void trg_proc(void); void count_proc(void); /*------*/ /* main */ /*------*/ int main(void) { /* initialize monitor */ user_initialize(); /* enable interrupt */ sei() ; /* endless loop */ while ( ON ) { /* display */ if ( dflag == ON ) { /* clear flag */ dflag = OFF ; /* perform */ dsp_proc(); } /* trigger handling */ if ( sflag == ON ) { /* clear flag */ sflag = OFF ; /* perform */ trg_proc(); } /* master handling */ switch ( state ) { /* wait start trigger */ case 0 : if ( iflag ) { state = 1 ; PORTD &= ~0x40 ; } break ; /* auto transfer */ case 1 : state = 2 ; break ; /* wait goal trigger */ case 2 : if ( iflag ) { state = 3 ; PORTD |= 0x40 ; } break ; /* return first state */ case 3 : state = 0 ; break ; /* default */ default: break ; } /* count up */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* perform */ if ( state == 2 ) { count_proc(); } } } /* dummy */ return 0 ; } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ void user_initialize(void) { /* PORT B */ PORTB = 0b00000000 ; /* 00000000 */ DDRB = 0b11111111 ; /* oooooooo */ /* PORT D */ PORTD = 0b01010000 ; /* 00000000 */ DDRD = 0b11101111 ; /* ooiooooo */ /* initialize timer1 */ { /* clear counter */ TCNT1 = 0 ; /* set compare value */ OCR1A = 499 ; OCR1B = 999 ; /* inhibit compare match output , select CTC mode */ /* prescaler /8 => 500kHz */ TCCR1B = (1 << CS11) | (1 << WGM12); /* enable compare match */ TIMSK = (1 << OCIE1A) ; } /* clear */ sft = 0 ; sflag = OFF ; scntx = 0 ; state = 0 ; iflag = OFF ; dstate = 0 ; dflag = OFF ; tflag = OFF ; tcntx = 0 ; /* initialize counters */ a1 = 0 ; a10 = 0 ; a100 = 0 ; a1000 = 0 ; /* pattern */ *(ledpat+0) = 0b1111110 ; /* 0 */ *(ledpat+1) = 0b0110000 ; /* 1 */ *(ledpat+2) = 0b1101101 ; /* 2 */ *(ledpat+3) = 0b1111001 ; /* 3 */ *(ledpat+4) = 0b0110011 ; /* 4 */ *(ledpat+5) = 0b1011011 ; /* 5 */ *(ledpat+6) = 0b1011111 ; /* 6 */ *(ledpat+7) = 0b1110010 ; /* 7 */ *(ledpat+8) = 0b1111111 ; /* 8 */ *(ledpat+9) = 0b1111011 ; /* 9 */ /* set flags */ izf3 = OFF ; izf2 = OFF ; izf1 = OFF ; } void dsp_proc(void) { /* judge */ switch ( dstate ) { case 0 : PORTB = ledpat[a1000] ; PORTD &= MASKF0 ; break ; case 1 : if ( izf3 == OFF ) { PORTD |= DSPA1000 ; } break ; case 2 : PORTB = ledpat[a100] ; PORTD &= MASKF0 ; break ; case 3 : if ( izf3 == OFF || izf2 == OFF ) { PORTD |= DSPA100 ; } break ; case 4 : PORTB = 0x80 | ledpat[a10] ; PORTD &= MASKF0 ; break ; case 5 : if ( izf3 == OFF || izf2 == OFF || izf1 == OFF ) { PORTD |= DSPA10 ; } break ; case 6 : PORTB = ledpat[a1] ; PORTD &= MASKF0 ; break ; case 7 : PORTD |= DSPA1 ; break ; default: break ; } /* update */ dstate++ ; if ( dstate == DLAST ) { dstate = 0 ; } } void trg_proc(void) { /* shift */ sft <<= 1 ; sft &= 0x07 ; /* get data */ if ( PIND & 0x10 ) { sft |= ON ; } /* judge */ iflag = OFF ; if ( sft == 3 || sft == 1 ) { iflag = ON ; } } void count_proc(void) { a1++ ; if ( a1 == 10 ) { a1 = 0 ; a10++ ; } if ( a10 == 10 ) { a10 = 0 ; a100++ ; } if ( a100 == 10 ) { a100 = 0 ; a1000++ ; } if ( a1000 == 10 ) { a1000 = 0 ; } /* judge */ if ( a1000 == 0 ) { izf3 = ON ; } if ( a100 == 0 ) { izf2 = ON ; } if ( a10 == 0 ) { izf1 = ON ; } } /* timer0 comare match interrupt */ ISR(TIMER1_COMPA_vect) { /* display handling (1ms) */ dflag = ON ; /* 10ms handling */ scntx++ ; if ( scntx == SMAX ) { scntx = 0 ; sflag = ON ; } /* 100ms handling */ tcntx++ ; if ( tcntx == TMAX ) { tcntx = 0 ; tflag = ON ; } }  4MHzのクロックで動かす仕様にしてあります。  利用したマイコンは、ATMELのATTiny2313で、ピンアサインは  次のようにしました。 Port B PB7 led_pat7(Dp) PB6 led_pat6(a) PB5 led_pat5(b) PB4 led_pat4(c) PB3 led_pat3(d) PB2 led_pat2(e) PB1 led_pat1(f) PB0 led_pat0(g) Port D PD6 GLED <status green LED> PD5 (no connection) PD4 SGTRG <trigger> PD3 dspenable3 <select A1000> PD2 dspenable2 <select A100> PD1 dspenable1 <select A10> PD0 dspenable0 <select A1>  トリガー入力のデバイスは、以下の光電スイッチを  使います。
目次

inserted by FC2 system