歩き遍路 平成19年春(J1) 記録の準備
SPIでUSB( 3)
 MAX3420を制御するPIC18F4520のソフト

 MAX3420用のアプリケーションノート 3690のプログラムは、コントローラMAXQ2000の命令で書かれているHIDクラスのプログラムでデバイスドライバはWINDOWSに組み込まれています。
 私は、コントローラMAXQ2000を知ったのは今回が初めてなのでプログラムが読めるか危惧したのですが、プログラムがCコードで600行と短くブロック的に書かれている事と、日本語版の丁寧な説明書とレジスタの説明書が有るのでチャレンジしました。又、書き換える処は、プログラムの最後に纏めていただいてることとそれは150行程度です。

●プログラムをPIC18F4520用に書き換え

 ダウンロードした AN3690_BF1_Code の EnumAppNote_BF1.C EnumApp_enum_data.h MAX3420E_BF1.h の内書換えが必要なのは EnumAppNote_BF1.C だけで他のヘッダファイルはそのまま使います。
 私は、 EnumAppNote_BF1.C を Max3420Pic18EnumAn_BF1.C と名前を替えて使っています。
 ここに Max3420Pic18EnumAn_BF1.C のコードを置きます。

・ヘッダファイルの追加
 PIC18F用の次のヘッダファイルを追加します。
 #include <p18cxxx.h> //PIC18F
 #include <spi.h> //PIC18F
 #include "delays.h" //PIC18F

・コードの書替え
 480行目近辺の次の部分以下の主にSPIハード制御のコードをPIC18F用に書替えします。
 コントローラMAXQ2000のコードを知らないので意味を考えて書き換えました。意味は、コードを見れば容易に理解できました。
 

// ------------------------------------------------------------
// The code below customizes this app for the MAXQ2000
// microprocessor and the Rowley compiler. Only this
// section changes if you use a different uP and/or compiler.
// ------------------------------------------------------------
  以下がコードを書き替える処


 コードの最後に次の関数が有ります。これは、単独でMAX3420のレジスタを読み書きする診断用です。
 私はこれを変更して、スイッチやLEDをアクセスしてハードの検査をしました。

void test_SPI(void) // Use this to check your versions of the rreg and wreg functions


●プログラムの理解とアプリケーションのポイント


 プログラムを理解するた全リストを小さい文字(8ポイント)で印刷して切り貼りしました。A3用紙に貼り込みましたが、4枚で貼り込めました。関係部位を線で結んだり色分けして理解を助けました。

 次の写真は、2/4のMAINの部分です。大きな写真をここに置きます。




・アプリケーションのポイント


 次左は実行結果です。
 デバイスのスイッチを押す毎にUSBデバイスからホストに一行の文字列を送ります。これはスイッチを6回押しました。



 プログラム追いかけて見ると
@MAINは永久ループしている。ループ毎にカウントして20mSを検出する。
A20mS毎にデバイスのスイッチ押下を調べる。スイッチ押下なら inhibit_send = 0x00; を行う。
BHID動作のホストからの定期問合せ時に、do_IN3関数で次の EnumApp_enum_data から送信データを取り出しホストに送信する。1回で3バイト送信する。次のデータとの間に、キーアップの3バイトの 00h を送信する。

 EnumApp_enum_data のデータは、コメントの // each letter is 3 bytes--shiftcode, 00, HID keycode の様にUSBキーボードで使われているコードで、「HID Usage Tables」に記載されています。
 例えば、
  0x00,0x00,0x28, // (cr) は、0x28 がリターンを表しています。
  0x02,0x00,0x17, // T (02 is shift) は、先頭の 0x02 がシフトキー押下を、0x17 が t 又は T を押下です。


// ***********************************EnumApp_enum_data.h の一部 *******************************************

const unsigned char Message[]={ // each letter is 3 bytes--shiftcode, 00, HID keycode
0x00,0x00,0x28, // (cr)
0x02,0x00,0x17, // T (02 is shift)
0x00,0x00,0x0B, // h
0x00,0x00,0x08, // e
0x00,0x00,0x2C, // (sp)
0x02,0x00,0x10, // M
0x02,0x00,0x04, // A
0x02,0x00,0x1B, // X
0x00,0x00,0x20, // 3
0x00,0x00,0x21, // 4
0x00,0x00,0x1F, // 2
0x00,0x00,0x27, // 0
0x02,0x00,0x08, // E
0x00,0x00,0x2C, // (sp)
0x00,0x00,0x07, // d
0x00,0x00,0x12, // o
0x00,0x00,0x08, // e
0x00,0x00,0x16, // s
0x00,0x00,0x2C, // (sp)
0x02,0x00,0x18, // U
0x02,0x00,0x16, // S
0x02,0x00,0x05, // B
0x02,0x00,0x1E, // !
0x00,0x00,0x28}; // (cr)



// ************************************************************************************
// This endless loop checks for two high priority events (every time through the loop):
// 1. USB suspend ("Suspended" flag = 1). If suspended, checks for resume signaling.
// 2. A MAX3420E pending interrupt.
//
// Every 20 msec, it reads the "SEND" pushbutton. Every half second, it blinks
// the "Loop Active" light.
//
// *********************************** MAIN *******************************************
void main(void)
{
initialize_MAX();
while(1) // endless loop
{
if(Suspended)
check_for_resume();
if (MAX_Int_Pending())
service_irqs();
msec_timer++;
if(msec_timer==TWENTY_MSEC)
{
msec_timer=0;
if((rreg(rGPIO) & 0x10) == 0) // Check the pushbutton on GPI-0
{
inhibit_send = 0x00; // Tell the "do_IN3" function to send the text string
L0_ON // Turn on the SEND light
}
blinktimer++; // blink the loop active light every half second
if(blinktimer==BLINKTIME)
{
blinktimer=0;
L3_BLINK
}
}// msec_timer==ONE_MSEC
} // while(1)
}// main


// *********************************** do_IN3 *******************************************
void do_IN3(void)
{
if (inhibit_send==0x01)
{
wreg(rEP3INFIFO,0); // send the "keys up" code
wreg(rEP3INFIFO,0);
wreg(rEP3INFIFO,0);
}
else
if (send3zeros==0x01) // precede every keycode with the "no keys" code
{
wreg(rEP3INFIFO,0); // send the "keys up" code
wreg(rEP3INFIFO,0);
wreg(rEP3INFIFO,0);
send3zeros=0; // next time through this function send the keycode
}
else
{
send3zeros=1;
wreg(rEP3INFIFO,Message[msgidx++]); // load the next keystroke (3 bytes)
wreg(rEP3INFIFO,Message[msgidx++]);
wreg(rEP3INFIFO,Message[msgidx++]);
if(msgidx >= msglen) // check for message wrap
{
msgidx=0;
L0_OFF
inhibit_send=1; // send the string once per pushbutton press
}
}
wreg(rEP3INBC,3); // arm it
}



ホームへ戻る