写真はテクノチップス販売のアルテラ10K30を使用した開発ボード
PLDのページ
最近各種電気系の雑誌でPLD、CPLD、FPGAなどの言葉をよく見かけませんか?自分の作りたいロジック回路をプログラム
(プログラムドロジックデバイス) でき 何回でも書き直しができてしかもコンパクト、
今まで74ロジックICをしこしこ半田付けしている私にとってはまるで夢のようなデバイスです 。
しかしこのデバイスをプログラミングする為にはHDL(ハードウェア記述言語)なる言語を
マスターしなければならないとなると 「この手の物はプロ用の物なんだ!」
とのんさやは最近まで思っていました、なにせC言語だって最近覚えたんですから^^;
だけど!!やってみると結構簡単です(マジメにやると相当奥が深いんでしょうけど)
デバイスもザイリンクスXC95XXクラスなら1000円以下、プログラミングツールも
フリーでダウンロードできますので やらない手はありません(^.^)
まずは各ウェブページで情報を入手致し勉強しましょう、もちろん気になるサイトはお気に入りに登録するのを忘れずに!
私の師匠のサイト、アルテラのボード販売、ダウンロードケーブルの製作など必見です! | |
各種デバイスの開発、評価ボードを販売。その他情報も充実しています | |
この中のFPGA入門でPLDの歴史その他が書いてあります。 | |
定番のサイトですがこの中のVHDLのページは勉強になります | |
これも定番です、私はこの中のCPLD入門でほぼ覚えました。 | |
デバイスメーカの日本語ホームページです | |
デバイスメーカの日本語ホームページです |
なんとなく解ってきたでしょうか?それならまず評価実験用ボード、ダウンロードケーブルを製作しましょう
XILINX実験ボード
クロック源としてトランジスタ技術2001/8月号の記事(P281)を参考にPIC12C509A
を使用致しました。
LEDスタテック点灯、ダイナミック点灯、ラジコンサーボのPWM発生、などの実験をくりかえすと
すぐに飽きてきます・・^^;
ラジコンサーボ多チャンネルコントローラの製作
実験に飽きたところでサーボコントローラを製作してみましょう、回路図はこれを使います。
タイマからの各PWMをPWM0、PWM1、PWM2。
I/Oポートからのセレクタ信号をA(BIT0)、B(BIT1)、C(BIT2)
サーボ出力としてQ(0)〜Q(7)、R(0)〜R(7)、S(0)〜S(7)とします。
以下VHDLソースリスト
library IEEE; --深く考えてはいけません、挨拶文のようなVHDLを使うお約束です
use IEEE.STD_LOGIC_1164.ALL; --上記と同じ
use IEEE.STD_LOGIC_ARITH.ALL; --上記と同じ
use IEEE.STD_LOGIC_UNSIGNED.ALL; --上記と同じ
entity serbo24 is
Port (A,B,C :in std_logic; --入出力のポートを指定します
pwm0,pwm1,pwm2 : in std_logic;
Q: out std_logic_vector(7 downto 0); --serbo out LEFT_8
R : out std_logic_vector(7 downto 0); --serbo out RIGHT_8
S : out std_logic_vector(7 downto 0));--serbo out other_8
end serbo24;
architecture Behavioral of serbo24 is
signal IN_DATA : std_logic_vector(2 downto 0); --内部信号定義
signal dec : std_logic_vector(7 downto 0);
begin
Q(0) <= pwm0 and dec(0); --3 TO 8デコーダの出力とPWM信号のANDを各サーボ出力先に指定します
Q(1) <= pwm0 and dec(1);
Q(2) <= pwm0 and dec(2);
Q(3) <= pwm0 and dec(3);
Q(4) <= pwm0 and dec(4);
Q(5) <= pwm0 and dec(5);
Q(6) <= pwm0 and dec(6);
Q(7) <= pwm0 and dec(7);
R(0) <= pwm1 and dec(0);
R(1) <= pwm1 and dec(1);
R(2) <= pwm1 and dec(2);
R(3) <= pwm1 and dec(3);
R(4) <= pwm1 and dec(4);
R(5) <= pwm1 and dec(5);
R(6) <= pwm1 and dec(6);
R(7) <= pwm1 and dec(7);
S(0) <= pwm2 and dec(0);
S(1) <= pwm2 and dec(1);
S(2) <= pwm2 and dec(2);
S(3) <= pwm2 and dec(3);
S(4) <= pwm2 and dec(4);
S(5) <= pwm2 and dec(5);
S(6) <= pwm2 and dec(6);
S(7) <= pwm2 and dec(7);
IN_DATA <= C & B & A; --セレクタ入力をまとめます
process(IN_DATA) begin --3to8 decoder ここから下は3TO8デコーダ
case IN_DATA is
when "000" => dec <= "00000001";
when "001" => dec <= "00000010";
when "010" => dec <= "00000100";
when "011" => dec <= "00001000";
when "100" => dec <= "00010000";
when "101" => dec <= "00100000";
when "110" => dec <= "01000000";
when "111" => dec <= "10000000";
when others => dec <= "XXXXXXXX";
end case;
end process;
end Behavioral;
ソースを打ち込み、ピン配置を以下のようにします。web pack
ICEなどの場合chip view を使用します。
TDI,TMS,TCK,TDOなどはプログラム用のピンで固定されています。
1 |
A
|
11 |
Q(3) |
21
|
VCC
|
31
|
GND
|
41
|
VCC
|
2
|
B
|
12 |
Q(4)
|
22
|
R(2)
|
32
|
VCC
|
42
|
未使用
|
3 |
C
|
13 |
Q(5)
|
23
|
GND
|
33
|
S(1)
|
43
|
未使用
|
4
|
PWM0
|
14 |
Q(6)
|
24
|
R(3)
|
34
|
S(2)
|
44
|
未使用
|
5
|
PWM1
|
15 |
TDI
|
25
|
R(4)
|
35
|
S(3)
|
||
6
|
PWM2
|
16 |
TMS
|
26
|
R(5)
|
36
|
S(4)
|
||
7
|
Q(0)
|
17 |
TCK
|
27
|
R(6)
|
37
|
S(5)
|
||
8
|
Q(1)
|
18 |
Q(7)
|
28
|
R(7)
|
38
|
S(6)
|
||
9
|
Q(2)
|
19 |
R(0)
|
29
|
S(0)
|
39
|
S(7)
|
||
10
|
GND
|
20 |
R(1)
|
30
|
TDO
|
40
|
未使用
|
以上のソースをコンパイル、ピン配置をすると下記のような配線で24chサーボコントローラが完成致します。
パスコンは書いておりませんので適当に入れておいたほうが無難です。
その前にサーボを24個購入するのが大変なんですが(・・;)
上記の回路で完成した24chサーボコントローラ、ROBO-ONEで使用致しました。
さて、CPLDの方の準備が整ったところで、コントロール側(今回の例ではH8−3048)のソースも解説致しましょう。
以下のソースはROBO-ONEで使用した物なので、タイマ以外の所は無視して下さい。
関係のある所だけ抜き出して掲載しています。
//各インクルードファイルを入れたところで変数定義です
//各グローバル変数
int ssel = 0; //グローバル変数--サーボセレクト変数を初期値0とします
int Q[]={2910,3450,3500,2252,2188,3100,3000,3000};//Q 左足サーボ位置データ 配列処理 Q0 Q1
Q2 Q3 Q4 Q5 Q6 Q7
int R[]={2910,2590,1768,2584,3262,2680,3000,3000};//R 右足サーボ位置データ 配列処理 R0 R1 R2 R3 R4 R5 R6 R7
int S[]={3000,3000,3000,3000,3000,3000,3000,3000};//S 各サーボ位置データ 配列処理 S0 S1 S2 S3 S4 S5 S6 S7
//配列変数として各サーボ24個分の位置データ(これは初期値)の変数を8個ずつQ R Sと定義します
/*--------------------------------------*/
/* H8の初期化 */
/*--------------------------------------*/
void inih8(void)
{
P1.DDR = 0xff; //テスト用出力 P10はブザー出力
P4.DDR = 0xff; //液晶用出力
P6.DDR = 0x00; //ポート6タッチスイッチ P60からP63まで
PB.DDR = 0xff; //サーボセレクタ出力 PB0-PB2 ☆ポートBをセレクタ出力とします
PA.DDR = 0xff; //サーボ用PWM出力 PA2,PA4,PA6 ☆各タイマの出力定義です
P3.DDR = 0x00; //スイッチボード入力 DIP SW
P2.DDR = 0x00; //スイッチボード入力 PUSH SW
P8.DDR = 0xff;
}
/*-----------------------------------------------------------*/
/*-------------------割り込み処理----------------------------*/
/*-----------------------------------------------------------*/
#pragma interrupt //ここで2500usごとのセレクタ信号の切り替えをします
void int_imia3(void) //ITU3で2500usごとに割り込みが発生するとここに飛んできます
{
ITU3.TSR.BIT.IMFA = 0; //ITU3の割り込みフラグ、TSRのIMFAをクリアします
ssel++; // セレクタ変数sselを一つ進めます
if(ssel == 8) //セレクタ変数が8ならばセレクタ変数を0にします
{
ssel=0;
}
ITU0.GRB = Q[ssel]; //セレクタ変数が指し示すQ配列のセレクタ変数番目のデータをITU0のDUTYに更新します
ITU1.GRB = R[ssel]; //セレクタ変数が指し示すR配列のセレクタ変数番目のデータをITU1のDUTYに更新します
ITU2.GRB = S[ssel]; //セレクタ変数が指し示すS配列のセレクタ変数番目のデータをITU2のDUTYに更新します
PB.DR.BYTE = ssel; //セレクタ変数をIOポートに出力します
}
/*------------------------------------------------------------*/
/* 各タイマの初期化 */
/*------------------------------------------------------------*/
void pwmset(void)
{
//タイマ同期
ITU.TSNC.BIT.SYNC0 = 1; //ITU0は同期カウンタ
ITU.TSNC.BIT.SYNC1 = 1; //ITU1は同期カウンタ
ITU.TSNC.BIT.SYNC2 = 1; //ITU2は同期カウンタ
ITU.TSNC.BIT.SYNC3 = 1; //ITU3は同期カウンタ
//ITU0の設定
ITU0.TCR.BYTE = 0x23; // メインカウンタの為GRAでカウンタクリアclock 1/8
ITU0.GRA = 6000; //ここはよく解っていません・・なぜ6000なんだろう?思い出せません・・^^;
ITU.TMDR.BYTE = 0x07; // 0,1,2,3CHは pwm
//ITU1の設定
ITU1.TCR.BYTE = 0x63; // セカンドカウンタの為ITU0のGRAでカウンタクリアclock 1/8
ITU1.GRA = 6000; //ここはよく解っていません・・なぜ6000なんだろう?思い出せません・・^^;
//ITU2の設定
ITU2.TCR.BYTE = 0x63; // セカンドカウンタの為ITU0のGRAでカウンタクリアclock 1/8
ITU2.GRA = 6000; //ここはよく解っていません・・なぜ6000なんだろう?思い出せません・・^^;
//ITU3の設定
ITU3.TCR.BYTE = 0x63;//セレクタ用インターバルタイマとして2500usごとに割り込みを発生させます
ITU3.GRA = 5000;
ITU3.TIER.BIT.IMIEA = 1; //GRAコンペアマッチ割り込み許可
//総合
ITU.TSTR.BYTE =0x0f; // 0,1,2CH 動作の開始
}
このようにプログラムすると、各配列の変数を変更するだけで2500usごと自動的に更新されたPWMパルスが発生します。
ITUX.GRA. = 6000 とありますが今となっては何でだか思い出せません、まぁ動けばよしとしましょう。