SCIの使い方(その1)
調歩同期式シリアル通信
シリアル通信は、非同期式(調歩同期式)と同期式(クロック同期式)とに大別することができる。
I2C通信は、クロック信号を持つ同期式のシリアル通信である。
調歩同期式のシリアル通信は、クロック信号を持たないシリアル通信方式である。RS-232Cが有名であり、PCの9ピンD-subコネクタは、RS-232C準拠の通信コネクタである。
MEMEsのSH7085は、シリアル通信のためのSCI(Serial Communication Interface)を内蔵している。SCIはレジスタ設定により、非同期式にも同期式にも使用することができる。
※1:一般的に使われるUART(Universal Asynchronous Receiver / Transmitter)やUSART(Universal Synchronous / Asynchronous Receiver / Transmitter)という言葉も覚えておくと良い。SCIはUSARTの一種である。
I2Cは、クロック信号のSCK、データのSDAの二本の信号を使って通信をしていた。一本だけのデータ信号線を、信号の向きを変えながら通信するので、半二重通信となる。
SCIの調歩同期式通信においては、データ線としてTxDとRxDの二本をもつ。よって、送信しながら受信もできる、全二重通信になる。
このように、SCIのTxD(送信データ)を相手のRxD(受信データ)に接続する。調歩同期式であるのでクロック信号は存在しない。
次に、SCIを用いた調歩同期式シリアル通信のデータフォーマットを示す。
この図では、0xb4をシリアル転送している。
無通信状態のとき、データ線はHレベルである。
通信開始時にはスタートビットを送る。これは1ビット分の幅(時間)をもつLレベルの信号で、受信側にデータ送信開始を知らせるものである。受信側はこれによりデータ受信を開始する。
続いて、データを8ビット(1バイト)分順次送信している。ここではLSBファーストとなっている。LSBファーストとMSBファーストがあり、I2CではMSBファーストであった。調歩同期式の場合、LSBファーストが主に用いられている。
データ送信が終わると、ストップビットとしてHレベルを送り、1バイト分の送信が完了する。
設定によって、パリティビットを加えたり、ストップビットを2ビット幅とすることも可能である。
次の波形は、”ABCDEFG”を連続送信した時の実測波形である。
通信速度は38400bpsであり、波形上の二本のカーソル間が文字’A’である。スタートビットを’S’、ストップビットを’P’と表示している。LSBファーストであることを考慮すると、データは2進数で0100_0001、16進数で0x41となり’A’であることが確認できる。
無通信状態の後、’A’のスタートビット→LSB→・・・→MSB→ストップビット(’A’の送信完了)→’B’のスタートビット→・・・と続いている。このように、連続送信した場合は文字と文字との間に待ち時間などはなく、受信側ではスタートビットとストップビットを手掛かりにタイミングをとっている。(ハードウェアが処理しているので、ソフト側では考慮する必要はない)。
SH7085のSCI
SH7085には、SCI0~SCI2の3系統のSCIが内蔵されている。
MEMEsにおいて、各SCIは次のように接続されている。
SCI0 | ||
SCI1 | USB | UART-USB変換ICに接続、PCへ |
SCI2 | SDカード | SPI通信に設定し、SDカードに接続 |
・SCIの構成
SCIの概略構成図を次に示す。
データを受信する際は、RxD信号がLSB→MSBの順にSCRSR(レシーブシフトレジスタ)に格納されていく。8bit分正常受信すると、SCRSRはSCRDR(レシーブデータレジスタ)にコピーされる。CPUは受信完了を待ち、コピーされたSCRDRを読み込む。
なおSCRSRはCPUがリード/ライトすることはできない。受信した結果はSCRDRに転送されたものをリードする。
送信の場合は、SCTSR(トランスミットシフトレジスタ)が空になると(送信が完了すると)、SCTDR(トランスミットデータレジスタ)に書き込まれたデータをSCTSRにコピーし、送信動作を始める。
SCTSRもCPUからリード/ライトすることはできない。送信データはSCTDRに書き込むだけであり、トランスミットシフトレジスタの値(送信動作中は刻一刻と変化している)はCPUから操作できない。
図の右側のレジスタ群は、SCIの制御を行うレジスタである。
・STBCR3(スタンバイコントロールレジスタ3)
他の機能モジュールと同様に、SCIモジュールも初期状態ではクロック供給が止められて、低消費電力状態になっている。
iodefine.hでは次のように定義されている。
struct st_stb { /* struct STB */ : union { /* STBCR3 */ unsigned char BYTE; /* Byte Access */ struct { /* Bit Access */ unsigned char _IIC2:1; /* IIC2 */ unsigned char _SCIF:1; /* SCIF */ unsigned char _SCI2:1; /* SCI2 */ unsigned char _SCI1:1; /* SCI1 */ unsigned char _SCI0:1; /* SCI0 */ unsigned char _SSU :1; /* SSU */ } BIT; } CR3; : }
HEWでは、次のように記述する。
STB.CR3.BIT._SCI1 = 0; /* SCI1モジュールスタンバイ解除 */
・SCSMR(シリアルモードレジスタ)
SCIの動作モードを決めるレジスタであり、SCI0~SCI2それぞれに存在する。
キャラクタ長、パリティ、ストップビット長の設定や、後述するSCBRR(ビットレートレジスタ)と組み合わせて通信速度の設定を行う。
・SCBRR(ビットレートレジスタ)
SCSMR.CKSビットと組み合わせて、通信速度の設定を行う。
調歩同期式モードでは、
B:ビットレート(bit/s)
N:SCBRRの設定値
Pφ:20MHz
n:SCSMR.CKSの値(0~3)
とすると、
という関係が成立する。
例えばPφ=20.0MHz、n=0の時、9600bit/sの速度にする場合
N=64となる。
・SCSCR(シリアルコントロールレジスタ)
送受信動作の禁止/許可、割り込み要求の禁止/許可などを設定するレジスタである。
TE, REの各ビットは、送信動作/受信動作の禁止/許可を設定するビットである。通信条件の設定が完了した後、これらのビットを1にして、送受信を許可しておく。
割り込みに関しては、必要になった時点で説明をする。
・SCSSR(シリアルステータスレジスタ)
SCIの状態を示すフラグが格納されるレジスタである。
・TDRE(トランスミットデータレジスタエンプティ) :SCTDR(トランスミットデータレジスタ)からSCTSR(トランスミットシフトレジスタ)にデータ転送が行われ、SCTDRに次のシリアル送信データを書き込むことが可能になったことを示す。
・RDRF(レシーブデータレジスタフル) : 受信したデータがSCRDR(レシーブデータレジスタ)に格納されていることを示す。
・ORER(オーバランエラー) : 受信時にオーバランエラーが発生して、異常終了したことを示す。SCSSR.RDRFが1にセットされたまま次のデータ受信を完了した時に発生する。
・FER(フレーミングエラー) : 受信時にフレーミングエラーが発生して、異常終了したことを示す。ストップビットが0であった時に発生する。
・PER(パリティエラー) : 受信時にパリティエラーが発生して、異常終了したことを示す。
・TEND(トランスミットエンド) : 送信キャラクタの最終ビットの送信時にSCTDRに有効なデータがなく、送信を終了したことを示す。
TDREとTENDは似ているが、TENDは最終ビットを送り出して送信動作が完了した時点で1になるのに対し、TDREは最後のバイトの送信開始の時点で1になる。TDREを監視することにより、切れ目なく送信動作を続けることが可能になる。
送受信手順
・1バイト送信
1バイト(1文字)送信のフローチャートを次に示す。
SCSSR.TDRE(トランスミッタデータレジスタエンプティ)をリードし、TDRE=1(エンプティを示している)であれば、送信データを書き込む。書き込んだ後、TDREビットを0クリアしておく(TDREビットは自動でクリアされないので、ここでクリアしないと次回リード時に1のままである)。
このフローチャートを抜けた状態では、TxD信号線上はまだデータが送られている途中である可能性がある。本当に送信が完了したことを検出したい場合は、SCSSR.TENDビットを確認する。
・複数バイト送信
複数バイト送信のフローチャートを次に示す。
1バイト送信(SCTDRに送信データを書き込んだ)後、TDRE=1(送信データレジスタが空になった)を待ち、次の1バイトを書き込む。全データを書き込んだら、送信完了である。
1バイト送信と同様に、TxD信号線上も送信完了したことを検出したい場合は、SCSSR.TENDビットを確認する。
・1バイト受信
1バイト受信のフローチャートを次に示す。
まず、SCSSR.RDRF(レシーブデータレジスタフル)をリードする。RDRF=0の時は未受信状態を示している。受信を完了するとRDRF=1になるので、SCRDR(受信データレジスタ)を読み出し、RDRFフラグを0クリアしておく。
複数バイト受信する場合は、この手順を必要なだけ繰り返せばよい。
このフローチャートでは、エラー処理を一切省いてある。信頼性の高いプログラムにはエラー処理が必須であるが、今回は基本技術習得を目的とすること、MEMEsボード内での通信であることなどからエラーについては考慮していない。
演習
次のワークスペースをダウンロードし、展開する。
SCI1.zip
・演習1
SCI1_1.cの関数sci1_putch()SCI1に1バイト送信する関数であるが、未完成である。上のフローチャートを参考にして、この関数を完成せよ。
正常動作すると、Htermに’A’と表示される。
・演習2
SCI1_1.cの関数sci1_putstr()はSCI1に文字列を送信する関数であるが、未完成である。上のフローチャートを参考にして、この関数を完成せよ。
正常動作すると、Htermに”BCDEFG”と表示される。
・演習3
SCI1_1.cの関数sci1_getch()はSCI1から1バイト読み込む関数であるが、未完成である。上のフローチャートを参考にして、この関数を完成せよ。
正常動作すると、Htermから送信した文字がMEMEsのLCDに表示される。