ColdFire V1 とチャット - シリアル・インターフェースの実験 [ColdFire (ColdeFire) V1]
DEMOQE128には、シリアルインターフェースが付属しています。 これを利用して、通信を行ってみます。
お便利関数の宣言
このプログラムでは、SCIを使った通信を行います。 通信の最も低レベルな関数群をここで宣言しています。 実際の関数の中身は、後ろのほうで定義しています。
#include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */ // お便利関数の宣言 int getc(void); void putc(int ch); void puts(const char *s);
大域変数の宣言
続いて、大域変数を宣言していますが、 このプログラムでは、文字バッファひとつだけです。
// 大域変数の宣言 int c; // 文字バッファ
初期設定
メイン関数は、初期設定から始まります。
// メイン関数 void main(void) { // 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
いつものように、SOPT1レジスタを設定して、 COPを黙らせます。
// ICSを設定する // REFCLK = 38,400Hz // DCO = 39,321,600Hz // BUSCLK = 19,660,800Hz ICSTRM = NVICSTRM; ICSSC_FTRIM = NVFTRIM_FTRIM; ICSC2_BDIV = 0; // BDIV 1/1 ICSSC_DRST_DRS = 1; // FLL x1024
このプログラムでは、バス・クロックの周波数をボーレートの512倍に設定することにより、 通信エラーが起きにくいようにしています。 このため、デバッガでプログラムを書き込むときに、 内部参照クロックのトリム値を38,400Hzにあわせるのを忘れないようにしなくてはなりません。 バス・クロックは、19.8808MHzとかなり高速動作させています。
// SCI1を設定する // BAUD = 38,400 // BR = BUSCLK / BAUD / 16 = 32 SCI1BD_SBR = 32; // BUSCLK / BAUD / 16 SCI1C2_TE = 1; // 送信機能を有効にする SCI1C2_RE = 1; // 受信機能を有効にする EnableInterrupts; /* enable interrupts */ /* include your code here */
SCIは、ボーレートを38,400baudに合わせています。 バス・クロックを合わせこんだため、 SBRレジスタは、32というキリの良い数値になっています。
for(;;) { puts("\nReady* "); // プロンプトを表示する for (;;) { c = getc(); // 一文字受信する if (c == '\n') break; // 行末文字なら脱出 putc(c); // 受信した文字を送信する } } /* loop forever */ /* please make sure that you never leave main */ }
メイン関数は、二つの無限ループから構成されています。 外側のループは、一行入力ごとに回ります。 内側のループは、一文字入力ごとにまわり、 行末を見つけたらbreak文で脱出します。
お便利関数の定義
ここから、お便利関数の定義が並びます。
// 一文字受信ルーチン int getc(void) { int ch; // 受信バッファがいっぱいになるのを待つ while (!SCI1S1_RDRF) { // Do nothing } ch = SCI1D; // 一文字受け取る if (ch == '\r') { // Enterキーは、 ch = '\n'; // 行末文字に変換する } return ch; // 受け取った文字を返す }
一文字受信ルーチンでは、 RDRFフラグで文字の到着を待ち、 到着した文字を受け取ります。 Enterキーが検出されたら、行末文字に変換して値を返します。
// 一文字送信ルーチン 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に一文字送信する }
一文字送信ルーチンは、 送信バッファが空いたのを確認してから文字をSCIに引き渡します。 このルーチンでは、行末文字を見つけたら、 CR+LFに変換して送信します。
// 文字列送信ルーチン void puts(const char *s) { while (*s) { // 文字列末でなければ、 putc(*s++); // 一文字送信する } }
文字列送信ルーチンでは、 文字列末まで一文字ずつ値を取り出して、一文字送信ルーチンを呼び出しています。
ツール・キットを入手しよう
プログラムを書き込んだら、シリアル・インターフェースをPCとつなぎます。 この時、通常であればPCにシリアル・インターフェースを準備しなくてはならないのですが、 DEMOQE128には、USB接続に使われているHCS12チップが シリアルインターフェースのフリをしてくれる機能があります。 ところが、 この機能は、どうやら規格が公になっているのではないらしいので、 P&Eが提供するアプリケーション・ソフトウェア(ツール・キット)を使用する必要があります。
DEMOQE128のクイック・スタート文書などには、同梱のDVD-ROMに アプリケーション・ソフトウェアが入っているという表現が見られるのですが、 少なくとも私のところに来たDVD-ROMでは、 該当するアプリケーションを見つけられませんでした。
ツール・キットは、以下の場所から入手できます。 http://www.pemicro.com/fixedlinks/DEMOQEToolkit.cfm このページに並んでいる、"Terminal"が目的のアプリケーション・ソフトウェアです。 注意書きに従って、ダウンロード、実行すると、端末ウィンドウが開きます。
是非、putc、getcを低水準入出力として登録して、printf、scanfを実現して、マイコンでもhello worldできるようにしてください。
by hamayan (2008-01-24 07:57)
printf や scanf は、性に合わないので、もっぱら write や read を使っていました。 hello world は、ぜひ別の方法で。
今回のプロンプトがヒントです。
次は、リング・バッファに挑戦の予定。
by noritan (2008-01-24 08:32)