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番地から始まります。詳細はこちらを参照してください。