ColdFire V1 - 一行入力ルーチン [ColdFire (ColdeFire) V1]
昨日の一文字送受信を拡張して、一行入力ルーチンをプログラムしてみました。
ソース・コード
#include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */
このプログラムでは、一行分の文字列をラインバッファに入れます。 ラインバッファの長さをBUF_LENGTHで宣言します。
// 定数の宣言 #define BUF_LENGTH (72) // 大域変数の宣言 char lineBuf[BUF_LENGTH]; // ラインバッファ
お便利関数に一行入力ルーチンgetLine(void)を加えました。
// お便利関数の宣言 int getc(void); void putc(int ch); void puts(const char *s); char *getLine(void);
メイン関数で使用する変数は、今回はすべて局所変数にしました。 一行入力ルーチンからのポインタを入れる変数として、 sを用意しました。
// メイン関数 void main(void) { char *s; // 行へのポインタ // SOPT1を設定する SOPT1 = 0 | SOPT1_WAITE_MASK // Enable WAIT instruction | SOPT1_RSTOPE_MASK // Enable RSTO* port | SOPT1_BKGDPE_MASK // Enable BKGD port | SOPT1_RSTPE_MASK ; // Enable RESET* port
前回は、内部参照クロックを38400Hzに設定して、 ボーレートをちょうどいい値に合わせたのですが、 今回は、デフォルトの31250Hzを使用することにしました。
バス・クロック周波数は、かなり高めの24MHzに設定しています。
// ICSを設定する // REFCLK = 31,250Hz // DCO = 48,000,000Hz // BUSCLK = 24,000,000Hz ICSTRM = NVICSTRM; ICSSC_FTRIM = NVFTRIM_FTRIM; ICSC2_BDIV = 0; // BDIV 1/1 ICSSC_DRST_DRS = 2; // FLL x1536 // SCI1を設定する // BAUD = 115200 // BR = BUSCLK / BAUD / 16 = 13 SCI1BD_SBR = 13; // BUSCLK / BAUD / 16 SCI1C2_TE = 1; // 送信機能を有効にする SCI1C2_RE = 1; // 受信機能を有効にする EnableInterrupts; /* enable interrupts */ /* include your code here */
メインループは、一行ずつの処理に変更しました。 かなり、簡単になりました。
for(;;) { puts("\n*READY"); // プロンプトを表示する s = getLine(); // 一行受信する puts(s); // 受信した文字を送信する } /* loop forever */ /* please make sure that you never leave main */ }
今回、新規に書き起こした一行入力ルーチンです。
// 一行受信ルーチン char *getLine(void) { char *p; // バッファポインタ char c; // 一文字バッファ for (;;) { putc(':'); // プロンプト出力 p = lineBuf; // バッファの先頭を指示 for (;;) { c = (char)getc(); if (c == 8) { // Back Spaceの処理 putc(c); // カーソルをもどす p--; // 一文字戻す // ポインタがバッファの先頭に達したら、 // プロンプト出力からやりなおす。 if (p < lineBuf) break; } else if (c == '\n') { // Enterの処理 putc(c); // 改行出力 *p = 0; // 文字列末文字を書き込む return lineBuf; // バッファへのポインタを返す } else if (c < ' ') { // その他のコントロール文字 continue; // 単に無視する } else if (c == 127) { // DELETE文字の処理 putc('\n'); // 改行出力 break; // プロンプト出力からやりなおす } else { // 通常の文字の処理 putc(c); // エコーバック *p++ = c; // バッファに書き込む // バッファを使い切ったら、 if (p >= &lineBuf[BUF_LENGTH]) { putc('\n'); // 改行出力 break; // プロンプト出力からやりなおす } } } } }
一文字戻す"Back space"キーと一行やりなおす"DELETE"キーを 特殊なキーとして、使用しています。 それ以外のコントロール文字は、無視しています。
残りの部分は、前回と同様です。
// 一文字受信ルーチン int getc(void) { int ch; // 受信バッファがいっぱいになるのを待つ while (!SCI1S1_RDRF) { // Do nothing } ch = SCI1D; // 一文字受け取る if (ch == '\r') { // Enterキーは、 ch = '\n'; // 行末文字に変換する } return ch; // 受け取った文字を返す } // 一文字送信ルーチン void putc(int ch) { if (ch == '\n') { // 行末文字の前にCRを付ける // 送信バッファが空くのを待つ while (!SCI1S1_TDRE) { // Do nothing } SCI1D = '\r'; // SCIにCR文字を送信する } // 送信バッファが空くのを待つ while (!SCI1S1_TDRE) { // Do nothing } SCI1D = (byte)ch; // SCIに一文字送信する } // 文字列送信ルーチン void puts(const char *s) { while (*s) { // 文字列末でなければ、 putc(*s++); // 一文字送信する } }
使ってみよう
プログラムは、プロンプトを出した後、一行入力して、それを一行出力するだけのものです。
*READY:10 i=1,100 10 i=1,100 *READY:20 @=i+1 20 @=i+1 *READY:30 #=-1 30 #=-1 *READY:
コメント 0