PCにシリアルに接続されたPICを経由して、フラッシュメモリのPCのファイルを書き込みます。
フラッシュメモリはPICにI2Cで接続されているものとします。
PCからPICに以下のようなコマンドを送ります
'h' num :メモリのROMアドレスの上位アドレスを指定します。numは1バイトのバイナリデータです。下位アドレスは0おにします。
'w' num :現在のROMアドレスから num バイトの値を書き込む。書き込む値はこのコマンドに続けて送ります。アドレスは自動的にnum
増加します。
'r' num :現在のアドレスから、num個のメモリの値をPCに送る。
次の手順で、PCからPIC経由で書き込みを行います。
PC側でファイルを選択する
h コマンドでROMアドレスを0にする
ファイルから num バイトを読み出し、 w コマンドでPICに送り書き込む
ファイルの中身が尽きるまで、繰り返す
送った内容を確認するには、h コマンドでアドレスを設定する
rコマンドで読み出し値を表示する
RS232Cとi2cのライブラリを利用します。main では 二つのバイトを受け取り、先頭バイトでコマンド、次のバイトを num のパラメータ値とします。'w'
コマンドの場合、buf[] にデータを受け取り writeMem 関数で書き込みます。書き込み番地は adrs の値を先頭にします。この変数は PCから
h コマンドで設定可能で、読み出しにも利用します。wコマンドでは、書き込みが終了したら、'1' を送ります。PCは この受信がないと、timeOut
のエラーを表示します(現在 TRACEで表示)。
'r' コマンドを受け取ると、readMem 関数を呼び出し、メモリを読みながらPCに値を送信します。'h' コマンドは、adrs の上位バイトを
num とします。
//Serial File Transmission #include <16f873a.h> #fuses HS,NOWDT,NOLVP //内部クロック、WDT,LVPなし #use delay(CLOCK=20000000) #use RS232(BAUD=9600,xmit=PIN_C6,rcv=PIN_C7)//use delayの後に配置する #use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW) // I2C使用宣言 void writeMem(long address); void readMem(long address); unsigned long adrs; char buf[64]; char num,cmnd; //w num :PCからデータを受け取りROMに書く //r num :ROMからデータを読みPCに送る //h num :アドレスの上位バイトを設定する //l num :アドレスの下位バイトを設定する main() { int i; //set_tris_b(0b11110010); adrs=0; while(1){ cmnd = getc(); num = getc(); switch (cmnd){ case 'w': for(i=0;i<num;i++){ buf[i]=getc(); //putc(cmnd); } //putc('2'); writeMem(adrs); adrs += num; putc('1'); break; case 'h': adrs = num<<8 ; break; case 'l' : adrs = (adrs & 0xF0) + num; break; case 'r': //putc('r'); readMem(adrs); /*for(i=0;i<num;i++){ putc(buf[i]); }*/ adrs += num; //putc('q'); break; } //putc(cmnd); //printf("1")ではバグル //write ROM } return 0; } //状態をチェックしてから書き込む void checkWrite(int data){ int state; while(1){ state=i2c_isr_state(); if(state>=0x80) { i2c_write(data); //delay_ms(2); return ; } } } //addressからROMに書き込む //chipアドレスは0に固定 void writeMem(long address) { //chipのメモリのaddress番地にdataを書く int i; i2c_start(); i2c_write(0xA0); i2c_write(address>>8 ); i2c_write(address); for(i=0;i<num;i++){ checkWrite(buf[i]); } i2c_stop(); delay_ms(5); //enable_interrupts(INT_RDA); //printf("wadrs:%lx\r\n",address); } //addressからデータを読みPCに送る void readMem(long address) { //chipのメモリのaddressを読み、その値を返す int i; i2c_start(); i2c_write(0xA0); i2c_write(address>>8); i2c_write(address); //printf("radrs:%lx:",address); i2c_start(); i2c_write(0xA0 | 0x01); for(i=0;i<num-1;i++){ putc(i2c_read(1)); } putc(i2c_read(0));//temp i2c_stop(); }
ダイアログ構成です。openでファイルを開き、send ボタンでファイルを送ります。SENDボタンでROMに書き込みます。メッセージエリアに経過が表示されます。書き込みはページサイズ(標準は64バイト)単位で行います。この値は、64、128、256、と2のべき乗にします。256kBitROMの場合 64、1Mbitの場合256が最大値です。
内容を確認するには、値を設定後、setAdrsH でPIC側のアドレスを指定し、RCV ボタンで読み取り表示します。
ダイアログ本体のCSerialFtpDlg と CRs232C クラスから構成されます。CRs232C には、バイナリを送受信する関数を追加しました。
Openボタンの処理をします。CFileDialog クラスを利用してファイルを選択し、パスを pathName に取得します。ファイルを開くときは、モードを rb
とします。b を指定しないと、ファイルの中に eof のコードがあると、そこで、ファイルが終了してしまいます。
fp = fopen(pathName,"rb")
また、fseek() 関数を利用してファイルのサイズを取得しています。また、h コマンドで PIC側のメモリアドレスを初期化します。
Send ボタンで起動します。SendFile() を呼び出し、ページ単位のファイル転送を開始します。タイマーをセットして、PIC からの応答を待ち、次のページを送ります。ページのサイズはダイアログで指定可能ですが、現在PIC側の事情で64バイト固定です。タイマー処理に実行中の処理を知らせるため mode を設定します。mode が f の場合、ファイル送信処理の実行中を示します。
ファイルから m_pgsize を読み、w コマンドを利用してPICに送ります。ファイルが尽きたら、endOfFile を1にし、ファイルを閉じます。また、タイマー2をセットし、応答がない場合の タイムアウト(エラー)処理を行います。
RS232Cの受信イベント処理ができないため、タイマーを利用しています。タイマー1では 100mS 毎に受信の有無をチェックしています。また、タイマー2 では、少し長い時間で タイムアウトのエラー処理をしています。タイマー2は受信が終了すると クリア します。この クリア処理( KillTimer(2) )が実行されないと、タイムアウトを表示して、処理を終了します。
タイマーの番号は SetTimer(1,100,NULL); で設定する最初のパラメータで指定します。この番号は、OnTimer(UINT
nIDEvent) 関数の nIDEvent で通知されます。
nIDEvent が2のときは、タイムアウトの表示を行い、ファイル送信を中断します。1の場合の処理は、mode の値がファイル送信(f)か、受信(r)かで処理が分かれます。
ファイル送信の場合は、次のページの送信を開始します。受信の場合は、ページサイズの受信を行い 16進表示を行います。
受信した内容を16進で表示を行います。メッセージボックスのフォントは標準ではプロポーショナルフォントなので、表示が揃いません。initDialog()
でフォントの設定を行っています。m_font はダイアログの変数として保持する必要があります。
m_font.CreatePointFont(9*10, _T("MS ゴシック"));
GetDlgItem(IDC_MSG)->SetFont(&m_font,TRUE);
テキストボックス内部での改行には、ボックスのプロパティで 「複数行」と「改行許可」の設定が必要です。
InInitDialog で次のように、com0 の初期設定を行います。SetCommPort はボーレートやビット数などのRS232Cのパラメータを指定します。
Rs.RsPort(0); Rs.RsOpen(); rc=Rs.InitCommPort(0,1024L,1024L);//バッファ長 rc=Rs.SetCommPort(9600,8,0,0,false,false);//設定
Buff[] のnumバイトを送信します。RsSend(CString sendBuff) を文字列の出力専用です。
受信済みのデータを配列に記録し、その受信バイト数を返す関数です。void CString RsRcv() は文字列受信専用です。
RS232C を閉じます。忘れないよう、デストラクタ
CSerialFtpDlg::~CSerialFtpDlg()
の中で呼び出します。この処理を忘れると、MicroCodeLoader が Rs232C を利用できません。この場合、MicroCodeLoaderを利用するにはダイアログを停止する必要があります。
音声用の保存ファイルはRIFF形式でチャンク構造になっています。fmt と data チャンク以外のチャンクを作成していない場合、音声データは2C番地から始まります。詳細はこちらを参照してください。