スパイス  組み込み制御装置の受注製作

モニタプログラムを移植する
平成26年4月 6日

シリアルポートのプログラム(続き)
 z80SIOの仕様について調べていますが、日本語の資料が見当たらずかなり苦労しています。しかし、ユーザーズマニュアルには非同期通信での設定(書き込み)方法が手順表の形で示されています(P231辺りを参照)。これを元にプログラムしてみます。

z80SIOの概要
 まず、このLSIは非常に多くのレジスタを抱えています。2CHある通信ポートのそれぞれに対して書き込み用に8本、読み出し用に3本もあります。にもかかわらずIOアドレスは2バイト/ポート(全部で4バイト)しか占有しません。内一バイトはデータレジスタでデータの送受信用、残りの一バイトがコマンドレジスタで先の11バイト全てのレジスタが割り当てられています。個々ののレジスタを順に見ていきます。
 全部で8個ある書き込み用レジスタは、WR0〜7と命名されています。順に非同期通信に関係するレジスタを説明していきます。なお、非同期通信機能でもモニタプログラムが使用しない機能は設定方法のみの説明とします。
また、文書中の図表は先のユーザーズマニュアルよりの引用です。
 WR0レジスタは複数あるレジスタの選択とコマンドの指示が主な役割です。
ビット0〜2がレジスタ選択で、次回コマンドレジスタにアクセスしたときには該当するレジスタへの読み書きと判断されます。ビット3〜5がコマンドです。モニタプログラムで使用するコマンドだけを説明すると、
 Null Codeはレジスタ選択のみの時に指定します。
 Reset Ext/Status Interruptは後述するRR0レジスタにあるモデム関連のビットをクリアします。
 Channel Resetはリセット信号入力と同じ動作します。
 Error Resetは後述するRR1レジスタにある受信エラービットをクリアします
 ビット6〜7はNull Codeで使用します。
 WR1レジスタは割り込み関連の設定です。割り込みは使用しないので未設定または0で初期化とします。
 WR2レジスタは割り込みベクタレジスタです。未設定とします。
 WR3レジスタは下記のようになっています。
ビット0で受信許可。ビット6〜7で受信ビット長を選択します。ビット5のAuto Enablesは/DCD, /CTS入力を有効にするかどうか(1で有効)のようです。今回は無手順での通信を行いますので0に設定します。他の機能も使用しないので0とします。

 WR4レジスタは下記のようになっています。
 この中でビット6〜7のClock Modeはボーレートからx16になります。ビット4〜5の設定はビット2〜3を1ストップビットに設定するため無効になります(ビット2〜3が00のとき意味を持つ)。ビット0〜1のパリティ関連の設定はパリティなしのため00に設定します。説明書にはこのWR4レジスタを設定後に他の書き込みレジスタを設定するように指示があります(レジスタ選択のためのWR0への書き込みを除く)。

 WR5レジスタは下記のようになっています。なお、引用先の図ではビット5〜6の説明が間違っていましたので下記では訂正してあります。


 設定が必要なのは、ビット5〜6の送信ビット数とビット3のTx Enableです。それぞれ11, 1に設定します。

WR6, WR7レジスタはSDLC関連のレジスタです。未使用とします。

 読み出しレジスタはRR0〜2と命名されています。モニタプログラムで使用するビットのみ説明します。


 RR0ではビット0 Rx Charactor Availabe(受信データあり)、ビット2 Tx Buffer Empty(送信バッファ空き)を参照します。


RR1ではビット4〜6の通信エラービットを参照します。ちなみにビット0は送信完了(送信シフトレジスタも空)のようです。


 RR2は割り込みベクタです。割り込み未使用のため参照しません。

 やっとレジスタの説明が終わりました。これらのレジスタを初期化して通信できる状態にします。初期化の手順はユーザーズマニュアルで次のように示されています。
 ・WR0にてCHリセットを行う
 ・WR0にてポインタを2にセット
 ・WR2にて割り込みベクタを設定(CHBのみ)
 ・WR0にてExternal/Status Interruptをリセット、ポインタを4にセット
 ・WR4にて通信仕様を設定
 ・WR0にてポインタを3にセット
 ・WR3にて受信許可
 ・WR0にてポインタを5にセット
 ・WR5にて送信許可
 ・WR0にてExternal/Status Interruptをリセット、ポインタを1にセット
 ・WR1にて割り込みを許可
 これは割り込みを使用することを前提にしていますが、割り込みを使わない形でプログラムすると下記のようになります。最初にヘッダファイルaki80.hを定義します。
#ifndef AKI80_H
#define AKI80_H
/*-----------------------------------------------------------------------
* IO Addr
*---------------------------------------------------------------------*/
#define CTC0 0x10
#define CTC1 0x11
#define CTC2 0x12
#define CTC3 0x13
#define SIOA_DATA 0x18
#define SIOA_CMD 0x19
#define SIOA_STAT 0x19
#define SIOB_DATA 0x1A
#define SIOB_CMD 0x1B
#define SIOB_STAT 0x1B

#define PIOA_DATA 0x1C
#define PIOA_CMD 0x1D
#define PIOB_DATA 0x1E
#define PIOB_CMD 0x1F

#define PPI0_ADATA 0x30
#define PPI0_BDATA 0x31
#define PPI0_CDATA 0x32
#define PPI0_CMD 0x33

#define PPI1_ADATA 0x34
#define PPI1_BDATA 0x35
#define PPI1_CDATA 0x36
#define PPI1_CMD 0x37

#define WDT_MODE 0xf0
#define WDT_CMD 0xf1

#define INT_PRI 0xf4

/*-----------------------------------------------------------------------
* SIO Command
*---------------------------------------------------------------------*/
#define SIO_CMD_Null 0x00
#define SIO_CMD_SndAbt 0x08
#define SIO_CMD_RstExtInt 0x10
#define SIO_CMD_ChRst 0x18
#define SIO_CMD_EnIntNxt 0x20
#define SIO_CMD_RstTxIntPen 0x28
#define SIO_CMD_ErrRst 0x30
#define SIO_CMD_Reti 0x38

#endif //AKI80_H

 SIOの初期化ルーチンは下記になります。
void initSIOA(void)
{
outp(SIOA_CMD, SIO_CMD_Null | 0); //WR0を選択
outp(SIOA_CMD, SIO_CMD_ChRst | 0); //リセット
outp(SIOA_CMD, SIO_CMD_RstExtInt | 4); //RR0リセット後、WR4を選択
outp(SIOA_CMD, 0x44); //x16Clock, 1Stop, NoParity
outp(SIOA_CMD, SIO_CMD_Null | 3); //WR3を選択
outp(SIOA_CMD, 0xc1); //受信8bits, 許可
outp(SIOA_CMD, SIO_CMD_Null | 5); //WR5を選択
outp(SIOA_CMD, 0x68); //送信8bits, 許可
}


 ページ先頭へ 前へ 次へ ページ末尾へ