人の“フンドシ”でマイコン・システムを拡張する方法S08ではじめるマイコン制御プログラミング(6)(3/4 ページ)

» 2009年04月13日 00時00分 公開
[高田浩,@IT MONOist]

ボードのジャンパ設定

 ここで、連載第1回「マイコン・システムでどんなことができるのか?」で紹介したデモ・プログラムを思い出してみてください。PC上で動作する専用のアプリケーションに、加速度センサの値をグラフ表示させました。しかし、そのデモではシリアルケーブルはつないでいませんでしたよね。これは一体どういうことでしょうか?

 実はこのデモ・ボードに搭載されているオン・ボード・デバッガには、疑似的にシリアル通信を行う機能があったのです。そして、これはP&E Microcomputer Systems社が独自に追加した機能なんです(念のため、仕様を問い合わせましたが、教えてもらえませんでした……)。そのため、今回は汎用的なシリアル通信インターフェイス(SCI:Serial Communications Interface)を使います。SCIを使うには、デモ・ボードのジャンパ・ピンの設定を変更する必要があります(表2)(図17)。

 マイコンのPCT5ピンは、RS-232のレベル変換用ICのON/OFF制御に使いますのでLEDの制御には使えなくなります。つまり、8ビット値の表示に関して、前回のようにデモ・ボードのLEDで表示させることができなくなりますが、今回はPCに値を表示させますので心配ありません。

ジャンパ設定 J6 J7 J8 J9
変更前 2&3 2&3 2&3 1&2、3&4、5&6、7&8、9&10、11&12、13&14、15&16
変更後 1&2 1&2 1&2 1&2、3&4、5&6、7&8、9&10、13&14、15&16
表2 SCI使用時のジャンパ設定

ジャンパの変更場所 図17 ジャンパの変更場所

 突然ですが、皆さんは会社のPCのカレンダーや時計の日付・時間を自分で合わせていますか? 多くの方は、そんなことはしていないと思います。しかし、その割には誤差が少ないですよね。こうしたケースでは、PCが社内サーバやインターネットのタイム・サーバと同期して時間を自動調整(同期処理)していることがほとんどです。

 一方、同期処理がなされていないような普通の掛け時計や腕時計はどうでしょうか? 同期機能を持っていないものは、基本的に自立している状態でできるだけ正確に時を刻むことを求められます。そうしないと、秒単位で管理されている電車のダイヤなど、生活に影響が出てきます。時計が遅れていたせいで電車に間に合わず、デートに遅刻してしまってはシャレになりませんよね。

 マイコンの世界でも同じようなことがいえます。非同期式では、文字通りPCに接続された信号線には同期用のクロック信号がありません。そのため、接続するもの同士、通信パラメータをそろえる必要があり、そのパラメータ(ボーレート)は、なるべく正確でなければなりません(正確でないと正しく通信できません)。

 SCIは、マイコンのバス・クロックをクロック・ソースとして使います。これまでの連載では、処理を簡単にするためタイマ(つまりクロック)の誤差については、あまり気にしないことにしてきました。しかし、今回はマイコン・ボード以外の装置と通信する必要があるので、なるべく正確なクロックを生成して、余裕を持って通信できるようにします。

 そこで、今回は連載第4回「LEDの制御に時間の概念を取り入れる」で少し触れた、「トリミング」という操作をすることでマイコンごとの“ばらつき”を抑え、±2%以内の誤差で内部クロックを生成するようにします。

 これまでのデモでは、デバッガを起動してプログラムをダウンロードするときに、図18のようなダイアログが出てきたと思います。いままでは、何も気にしないで[Connect]ボタンをクリックして、Flash書き込みを行っていたと思いますが、よく見ると「Trim Control」という項目があり、何やら“デフォルトの内部基準クロック(reference frequency)は、31.25kHz(31250.00Hz)ですよ”というようなことが書かれています。実はこれ、デバッガのデフォルト値である31.25kHzに内部基準クロックをトリミングしてくれるという意味なのです(ちなみに、MC9S08QE128は工場出荷時に32.768kHzでトリミングされます)。

デバッガのトリミング機能 図18 デバッガのトリミング機能

 デバッガでトリミングされた値をマイコンの初期状態のまま使うと、CPUクロックは8MHz、バス・クロックはその半分ですので4MHzになります。なお、本連載では複雑過ぎるので扱いませんが、MC9S08QE128の性能としては、レジスタの設定を変更することでCPUクロックの上限である、50.33MHzまで引き上げることが可能です。詳しくはリファレンス・マニュアルの「ICS(Internal Clock Source)」の章を参照してください。

 では、PCに文字を送り、ターミナル・ソフトウェアに表示させてみましょう。ここでは、シンプルに“H”という文字を一文字だけ表示させることにします。まず、プログラムのmain関数付近を見てみましょう(リスト1)。

リスト1 リスト1

 リスト1①は、関数のプロトタイプ宣言です。リスト1②はおなじみのレジスタの初期化関数、リスト1③はSCIで1文字送信する関数です。ここでは“H”を送信しています。

 次に、レジスタの初期化を行うmcu_init関数を見てみましょう(リスト2)。

リスト2 リスト2

 リスト2①の部分でトリミングした結果を設定しています。NVICSTRMとNVFTRIM_FTRIMの値は先ほどの説明のようにデバッガが自動的にトリム値を保存したものです。デモ・ボードのジャンパ設定でPTC5の機能をLED制御からRS-232用レベル変換ICのON/OFF制御に切り替えてあります。リスト2②の処理では、レベル変換ICをONにしています。そして、SCIに通信パラメータの設定を行います。これは、ターミナル・ソフトウェアに行った設定に合わせる必要があります。

baud rate = BUSCLK / (16 * BR) 

という関係式があります。ボーレートの設定は、SCIxBDH/SCIxBDLレジスタ(図19)のSBR[12:0]に対してBRを書き込むことで行います。ボーレートは「9600」、バス・クロックは「4MHz」ですので、計算すると一番近い値が「26」になります。リスト2③の書き方でSCI1BDH/SCI1BDLの2バイトのレジスタに「26」を書き込みます。ほかのパラメータは、デフォルト設定のままで合致していますので特に設定の必要はありません。

ボーレート・レジスタ 図19 ボーレート・レジスタ(リファレンス・マニュアルより)

 SCIの通信は送信/受信ともに可能なのですが、今回は送信の機能だけ使用します。SCIxC2レジスタのTEビットを「1」にしてください(図20)(リスト2④)。

SCIコントロール・レジスタ2 図20 SCIコントロール・レジスタ2(リファレンス・マニュアルより)

 データを送信するには、送信したい文字を送信バッファに格納します。それを行うのが、SCIxDレジスタ(図21)です。バッファに格納可能な状態かどうかはSCIxS1レジスタのTDREビット(図22)で判断します(リスト3)。

SCIデータ・レジスタ 図21 SCIデータ・レジスタ(リファレンス・マニュアルより)
SCIステータス・レジスタ1 図22 SCIステータス・レジスタ1(リファレンス・マニュアルより)
リスト3 リスト3

 それではプログラムをビルドして、実行してみましょう。ターミナル・ソフトウェアは接続状態にしておいてください。いかがでしょうか? 画面に“H”という文字が表示されるはずです(図23)。

ハイパーターミナルの出力画面 図23 ハイパーターミナルの出力画面

 文字が送信できるようになったところで、今度は文字列表示に挑戦してみましょう。SCI_putcを利用して、文字列を表示する関数SCI_putsを定義します(リスト4)。

リスト4 リスト4

 ターミナル・ソフトウェアで表示するのは文字です。そのため、SCI_puts関数では表示させたい内容を文字列として送信します。A/Dコンバータで取得した値は、8ビット・データですが文字コードではなくバイナリ値です。そのままでは、表示できないのでASCII形式の文字コードに変換します。確か、こういうときに便利なANSIライブラリ関数がありましたよね? そうです。printf系の関数『sprintf』です。printfは標準出力に対して文字列を出力しましたが、sprintfは指定したバッファに文字列データを出力します。そのデータをSCI_putsで送信すればよいのです。

 リスト5は、SCI_putsで文字列を送信する例です。

リスト5 リスト5

 sprintfで10進数の「123」を10進数と16進数の文字列に変換しています。ANSIライブラリsprintfを使っているので、標準ヘッダ「stdio.h」をインクルードしています。また、main関数内に文字列バッファ用の配列bufを定義しています。ここではサイズを50文字分にしていますが、各自変換した文字列を格納できるサイズに指定しておいてください。

※注:標準状態では、スタック・エリアのサイズは200Hバイトです。スタック・エリアは自動変数以外にも使われるのでオーバー・フローしないよう注意してください。また、ここではプログラムを簡単にするためにsprintfを使っています。しかし、一般的にprintf系の関数は高機能なため、プログラム・サイズが大きくなりがちです。実務でプログラミングする場合、この部分を自作することでプログラム・サイズを抑えることができます。


 では、プログラムを実行してみてください。図24のように表示されるはずです。

ハイパーターミナルの出力画面 図24 ハイパーターミナルの出力画面(文字列)

 「123」という値が、10進数(123)と16進数(7B)の文字列に変換されて表示されたはずです。いかがでしょうか? これでデータの送信もばっちりですね。

Copyright © ITmedia, Inc. All Rights Reserved.