[新連載]CPLD入門!
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使うことになるだろうと思ってはいたのですが。
何を今頃になって、というようなものですが。
ようやく本気で、CPLDと四つに取り組みます。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第103回]
●プッシュスイッチカウントプログラム(2)
前回からの続きです。
その続きのところでは1/1000秒、1/100秒、1/10秒のクロックを作り出しています。
。
--1/1000 process(cntr1(11)) begin if cntr1(11)'event and cntr1(11)='0' then tm1<=tm1+"0001"; end if; if tm1="1010" then tm1<="0000"; end if; end process; -- 1/100sec process(tm1(3)) begin if tm1(3)'event and tm1(3)='0' then cntrss0<=cntrss0+"0001"; end if; if cntrss0="1010" then cntrss0<="0000"; end if; end process; -- --1/10sec process(cntrss0(3)) begin if cntrss0(3)'event and cntrss0(3)='0' then cntrss1<=cntrss1+"001"; end if; if cntrss1="1010" then cntrss1<="0000"; end if; end process; |
tm1の1クロックは1/1000秒(つまり1KHz)です。
tm1は0〜9までカウントして0に戻ります。
tm1は1桁(バイナリ4ビット)の10進カウンタです。
ここはその次の1/100秒のカウンタが必要なので、その前処理として書いています。
次の1/100秒のところも1/1000のところと同じ処理です。
cntrss0は1桁(バイナリ4ビット)の10進カウンタです。
その次の1/10秒も同じ処理です。
ここのところのクロックはプッシュスイッチのチャタリング回避のために使用しています。
当初は1/10秒のクロックを使ったのですが、それだとちょっと遅すぎてプッシュスイッチを押しても応答しないときがでてきたので、1/100秒を使うように改めました。
下がその部分です。
-- ******* sw in counter ****** --sw on check process(cntrss0(3))--10ms begin if cntrss0(3)'event and cntrss0(3)='1' then swbon<=SWB; swcon<=SWC; end if; end process; |
何をやっているのかわかりにくいかもしれません。
メカニカルなスイッチにはチャタリングがあります。
そのため何も対策をしないと1回押しただけなのに数回から数十回もカウントしてしまいます。
チャタリング除去のためにはスイッチと並列に0.1〜1μF程度のコンデンサを入れるのが簡便な方法です。
最初はそれも試してみたのですが、だめでした。
EPM7128SLC84の入力回路にはシュミットトリガ回路がありませんから、コンデンサのために入力信号がなまってしまうと、かえって誤動作してしまいます。
そこで上のプログラムの方法を考えました。
cntrss0(3)が1になるタイミングは0111から1000になるときですから、それは0.1秒に1回のタイミングです。
0.1秒に1回スイッチBとスイッチCの状態をそれぞれswbonとswconに入れます。
こうやって説明を書くのはなかなかに手間がかかって大変なのですが、しかしこのようにして整理しながら書くことで、はじめて考えの誤りに気が付くこともよくあります。
ここのところは私は0.01秒に1回、のつもりでプログラムを書きました。
でもこうやって整理してみると、cntrss0は1/100秒のカウンタですから、そのカウンタが10回に1回、0111から1000になるわけですから、それは0.01秒に1回ではなくて0.1秒に1回、ということなのでした。
うーん。
ちょんと押しただけではカウントアップしないときがあるかもしれません。
気持ちとしては、0.1秒以上押す、ということにすれば、問題はないはずです。
チャタリングが0.1秒もあることは考えられませんから、このくらいの値のほうが安全かもしれません。
皆様で、ここのところはcntrss0の代わりにtm1に置き換えて試してみてください(チャタリングの影響が出るかどうか)。
次のところではスイッチBのカウント処理をしています。
--cntrb -- process(SWA,swbon) begin if swbon'event and swbon='0' then swcntrb0<=swcntrb0+"0001"; end if; if swcntrb0="1010" or SWA='0' then swcntrb0<="0000"; end if; end process; -- process(swcntrb0(3)) begin if swcntrb0(3)'event and swcntrb0(3)='0' then swcntrb1<=swcntrb1+"0001"; end if; if swcntrb1="1010" or SWA='0' then swcntrb1<="0000"; end if; end process; |
swcntrb0、swcntrb1はそれぞれ4ビットのバイナリカウンタです。
10回カウントすると(1010になると)0000にクリアします。
つまり1桁の10進カウンタです。
スイッチAを押したときも0000にクリアしますからそこのところも加えてあります。
次はスイッチCのカウント処理です。
--cntrc -- process(SWA,swcon) begin if swcon'event and swcon='0' then swcntrc0<=swcntrc0+"0001"; end if; if swcntrc0="1010" or SWA='0' then swcntrc0<="0000"; end if; end process; -- process(swcntrc0(3)) begin if swcntrc0(3)'event and swcntrc0(3)='0' then swcntrc1<=swcntrc1+"0001"; end if; if swcntrc1="1010" or SWA='0' then swcntrc1<="0000"; end if; end process; |
ここはスイッチBの処理と全く同じです。
最後に7セグメントLEDの表示用データバッファに各カウントデータを送ります。
--7seg disp -- leddatabf3<=swcntrc0; leddatabf2<=swcntrc1; leddatabf1<=swcntrb0; leddatabf0<=swcntrb1; -- |
leddatabf0〜leddatabf3は前回説明しました。
leddatabf0〜leddatabf3の値は7セグメントの表示データに変換されたあと、7セグメントLEDに出力されます。
下は前回お見せしたプログラムのソースファイルです。
trngswcntr1c.txt
[第91回]の通りに作業してください。
今回新規作成するフォルダはtrngswcntr1cです。
作業が済んだら[第92回]以後のところを参考にして、コンパイル、端子名ファイルのコピー作業を行なってください。
CPLDトレーニングキットはまだ準備作業中です。
お待たせして申し訳ありません。
手元に届きましたら、[第96回]を参考にしながら、実際にEPM7128SLC84にプログラムを書き込んでみてください。
CPLD入門![第103回]
2019.8.28upload
前へ
次へ
ホームページトップへ戻る