調歩同期通信について これまで,シリアル通信としては質問が多かった I2C バスについて,サンプルプログラムを 提供してきました。ここらで,目先を変えて同じシリアル通信で,もっと古くから使われてい る調歩同期通信に取り組んでいこうかと思います。そこで,最初に調歩同期通信について,さ っとおさらいをしてみます。(かなり,無駄な記述が多いですが,我慢してください。) [概要] 調歩同期通信は古くから使われているシリアル通信方式で,PC では RS-232-C が有名でした が,フロッピー・ディスクと並び”レガシー・インタフェース”と呼ばれ,今日ではほとんど見 なくなってしまいました。なお,PC ではほとんどの場合 RS-232-C は調歩同期通信の意味で 使われていましたが,本来は調歩同期通信(非同期通信)だけでなく,同期通信でもしようさ れる規格です。元々は,通信でモデムと端末を結ぶための 25 ピンのコネクタを用いた通信の ハードウェアを定めたものですが,PC ではいつの間にか 9 ピンになってしまいました。これ は,厳密には RS-232-C という規格ではないですが,慣例で RS-232-C と呼ばれています(伝 送関係者からは,マイコンや PC での使い方は本来の RS-232-C の使い方ではないと,怒られ たこともありました)。 PC ではほとんど見かけなくなりましたが,マイコンでは今日でも広く用いられています。た だし,調歩同期通信という呼び方ではなく,非同期通信や UART 通信などと呼ばれることがほ とんどです。本来は機器同士を結ぶためのインタフェースですが,取り扱いが簡単なために, いろんな場面で使われているようです。 CSI のようなクロック同期通信と比べると,回路が大きくなるので,昔は中位以上のマイコ ンにしか内蔵されていませんでしたが,今日ではロウエンドの MCU でもインタフェースが内 蔵されているのと,手順なし(無手順)でも使えるので,初めての人が比較的簡単に使えるよ うになっています。ロウエンド MCU の RL78 でも,一番小さい 10 ピンの RL78/G10 にもイ ンタフェース(UART)が内蔵されています。 調歩同期通信の一番の特徴は,クロックがなくてもデータを再生できることでしょう。その ため,送信データと受信データだけで(当然,グランドも必要ですが)双方向の通信が可能で す。送信と受信を切り替えながら通信する(半二重通信)なら,信号線は 1 本で済みます。こ れは,信号線を長く引っ張る場合にはありがたい特徴です。 それでは,調歩同期通信の信号について,簡単に触れたいと思います。調歩同期通信では, 送信側と受信側で通信条件が一致している必要があります。通信条件とは次の内容です。 ①信号レベルと論理 ②通信速度 ③データの長さ(通常は 8 ビット長ですが,7 や 9 ビットの場合もあり) ④転送順序(通常は LSB から順に転送する) ⑤パリティの選択 ⑥ストップビットの長さ(最近はほとんど 1 ビット)
このページは読み飛ばして構いません。 ①は通常はあまり意識しない(マイコンの端子ではほぼ決まっている)のですが,PC やその 他の機器と接続する場合に問題になります。前述の RS-232-C は±12V で駆動するインタフェ ースで,通常は論理が反転してマイコンに接続されます。最も古くからある TTY(テレタイプ 端末)では,20mA のカレントループ(電流駆動)も用いられていました。マイコン間をイン タフェースする場合には,CMOS レベルや TTL レベルが用いられるのがほとんどです。 ②は最も表に出てくる項目です。昔は TTY の 110 ボーや 300 ボーの倍数(600,1200, 2400,4800,9600,19200 等)の伝送周波数が主に用いられてきましたが,倍数から外れた 周波数も一部で使われています。 波形が全く崩れないとした場合でも,送信側と受信側の通信速度が 5%(実際は 4.5%程度) 以上あると正常な通信は実現できません。 古いマイコンでは動作クロックはほとんどが外付けの水晶発振子やセラミック振動子で, 4.9152MHz(マイコンは 2.5MHz 動作)や 18.432MHz(インテルが 9 分周して,2MHz 動作の 8080 用の CPU クロックを生成し,2.048MHz で動作させるようなスペックにしていた), 19.6608MHz(ボードを接続する標準バスのクロックが 10MHz でその倍)など調歩同期通信を 意識した発振周波数がよく使われていました。, ところが,最近のマイコンでは,32MHz や 20MHz と言った内蔵クロックをもつ MCU が増 え,ぴったりした周波数にならないだけでなく,精度も水晶発振子やセラミック振動子に比べ ると悪くなっているので,周波数の誤差についても注意が必要です。それでも,ここらは,数 字で出てくるのでかなり知れ渡っていますが,実際にやり取りする信号は,波形が鈍るとか, 反射の影響でノイズが出たりするとか,かなり崩れた波形になることがあります。 ③UART によって,使用できるビット長が異なりますが,ほとんどの場合に,データは 8 ビ ット長が使われます。 ④については,ほとんどの場合に LSB から順に転送されます。ここらは,I2C とは逆の順番 です。 ⑤パリティについては,パリティの有無や(1 のビットが)奇数か偶数かは UART では選択 できるので,合わせるだけです。 ⑥UART では,ストップビットは 1 ビットあれば機能として十分です。UART で 2 ビットに 設定した場合でも,送信では 2 ビット分送信されますが,受信では最初の 1 ビットだけがチェ ックされ,2 ビット目は無視されるのがほとんどです。前述の TTY では,全てメカで処理して いたので,2 ビット必要だったようです。TTY は ASCII コードを使用して,CR(0x0D:キャ リッジリターン)や LF(0x0A:ラインフィード)を用いていました。ヘッドが右側の方にあ ると,CR で行の先頭に戻るまでに時間が必要で,CR の直後に印字データを送ると,戻り切れ ずに途中で印字してしまいます。これを避けるには,必ず CR の後は LF とすることで対応し ていました。ところが,アセンブラで,最初に右側にソースを印字し CR 後に左側にアドレス や機械語を印字するものがあり,面食らったことがありました。
[信号のサンプリング] これらの条件が満足されていることとして説明を続けます。なお,実際の通信では,これ以 外に使用するコード体系も一致させることが必要ですが,通常はソフトでの処理部分になるの で,ここでは省略します。 調歩同期通信の信号の例を図 1 に示します。ロウレベルのスタートビット(ST)から始ま り,LSB(b0)から順に 8 ビットのデータが続き,最後はストップビット(SP)で終わってい ます。ストップビットの後は,次の通信が始まるまではストップビットと同じ極性(ハイレベ ル)が続きます。 では,図 2 のサンプリング・タイミングに示す波形を受信したときに,どのタイミングでデ ータを取り込む(ビット同期)かと取り込んだデータのどこからどこまでが一つのデータか (キャラクタ同期)をデータと通信条件から決める必要があります。 調歩同期通信では,このためにスタートビットとストップビットが定められています。この ため,8 ビットのデータをやり取りするのに,10 ビット分の時間が必要になり,その分通信速 度が低くなります。 データが通信されていない状態では,マイコンの端子の信号レベルはハイレベルになってい ます。通信が始まったことを示すために,信号レベルは 1 ビット分の期間ロウになります。こ れが,スタートビットで,データの始まりを示します(キャラクタ同期)。受信側では,スター トビットの始まり(立下り)を検出し,そのタイミングから 1/2 ビット分遅れたところ(ビッ トの中央)でデータを読みます。ビットの中央でデータを読めば,マージンが一番大きくなる ので,ここから,通信速度で決まる 1 ビットの時間ごとにデータを読めばビットを正しく読め るはずです。ビットの中央で読むことをビット同期と言います。 b0 b1 b2 b3 b4 b5 b6 b7 SP 図 1. 調歩同期通信信号の例 ST 図 2. サンプリング・タイミング シリアルデータ 間隔は決まっているが、正しいタイミングは分からない どのタイミング?
指定された数のビットを読むと受信完了ですが,その後にハイのストップビットがきます。 このストップビットが正しく読めて通信完了となります。ハイの状態は通信を始める前の状態 と同じです。通信後のハイの状態の最初の 1 ビット(または 2 ビット)がストップビットで, それに続くハイの状態は通信していない状態です。 実際の受信動作で,正しいデータを再生するには,通信条件が一致していること以外に,信 号の波形が崩れていないことが必要になります。通信する距離が長くなると,波形の崩れの影 響が大きくなってきます。波形の崩れ(主に波形の鈍り)を如何に抑えるかが受信マージンに 影響してきます。図 3 に受信マージンの考え方を示します。サンプリング点に対して,前後に どれだけ安定した期間があるかが受信マージンです。下側の拡大部では,波形の鈍りがある場 合を示しています。波形の鈍りがあると,スタートビットの立下りを検出(判断)する閾値に なるまでに遅延が発生します。検出したタイミングから 1/2 ビット経過したタイミングで,デ ータのサンプリングを行うので,後ろ側のマージンが小さくなってしまいます。 また,スタートビットを如何に早く検出できるかもマージンに影響してきます。(デバイスの マニュアルにはスタートビットの検出を行うクロックを通信速度の 6 倍以上などと記載されて いるのを見かけますが,最低 2 ケタ以上にすべきです。図 4 にスタートビット検出サンプリン グによる遅れを示します。最悪,1 サンプリング周期遅れてしまいます。 図 3. 受信マージン 受信マージン 受信マージン 図 4. スタートビット検出サンプリング遅延 最悪 1 サンプリング周期遅延
なお,これらのスタートビット検出遅れは,1 データで 1 回だけです。通信速度の誤差(ボ ーレート誤差)のようにビットごとに蓄積されるような性質の誤差ではありません。 UART によっては,ノイズ対策として複数回サンプリングして一致したら有効なデータと判 断する機能を搭載したののがあります。この場合,当然スタートビットの検出タイミングも遅 延しますが,受信データそのものが同じように遅延するので,無視して構いません。 [蓄積する誤差] 受信に大きな影響を及ぼすのが,ビットごとに誤差が蓄積していくボーレート誤差です。送 信側と受信側でボーレートに誤差がある場合がこれに該当します。スタートビットからストッ プビットまで 10 ビットの場合,ビットの誤差は最終的に 9.5 倍になります。逆に考えると,ス タートビットの検出誤差が 0 で,受信マージンが 50%と理想的な場合でも,最後のビットでの マージンは 50/9.5%となります。実際には,スタートビットの検出遅れや入力信号に対するセ ットアップ時間とホールド時間が存在するので,マージンは 4%程度になると考えられます。 UART で許容ボーレート誤差が 2~3%と言われているのはここらの結果からです。 ここらまでは,ハードウェア マニュアルのボーレート許容範囲として式が掲載されているこ とがありますので,興味のある方はマニュアルも眺めてみてください。 これに,波形の鈍り分が加わると,ボーレート誤差のマージンはもっと少なくなります。波 形の鈍り分は定量的には決まらないので,ハードウェア マニュアルにも記載されていないはず ですので,注意が必要です。 信号線が長くなって,波形が鈍ったときには,通信速度を低くする必要があります。ビット の幅が広くなれば,その分だけ影響が小さくなります。 ここまで,注意事項(というか,脅し文句)から離れたいと思います。 [ダブルバッファ] 現在では,ほとんどの UART の送受信部はシフトレジスタとバッファの 2 段構成になってい ます。中には,数バイトの FIFO をもった UART もあります。このような構成になっているの は,受信したデータのプログラムでの処理と次のデータの受信処理を並行してできるようにす るためです。ダブルバッファ構成になった受信回路のブロック例を図5に示します。 図 5. ダブルバッファ構成 シフトレジスタ サンプリング ノイズ除去 バッファレジスタ 受信データ
このブロック例では,受信データはサンプリングされ,ノイズ除去された結果がシフトレジ スタに取り込まれていきます。8 ビット分のデータ受信が完了したら,シフトレジスタからバ ッファレジスタにデータが転送され,受信完了割り込みが発生します。 引き続いて次のデータがくると,シフトレジスタは新しいデータを取り込んでいきます。 これをソフトウェアから見ると,データ受信完了割り込みが発生したので,バッファレジス タから受信データを読み出します。このときの読み出しタイミングとしては,次のデータの受 信が完了する前であればよいことになります。 新しいデータの受信が完了し,バッファレジスタが空なら新しく受信したデータをバッファ レジスタに転送します。バッファレジスタが空でなければ,オーバーラン・エラーとなりま す。このとき,新しく受信したデータがどうなるかは個々の UART で異なります。 [全二重通信と半二重通信] シリアル通信を行うときに,送信用の通信線と受信用の通信線が独立していれば,送信と受 信を独立に行わせることができます。送信と受信を同時に行うことが可能な通信を全二重通信 と言います。現在,ほとんどの UART では,全二重通信に対応しています。 これに対して,送信と受信を切り替えながら,交互に行うのが半二重通信です。UART で も,通信線が 1 本しかない場合には,半二重通信となります。 [フロー制御] 調歩同期通信では,手順(プロトコル)なしで,データを送受信する使い方がほとんどでは ないかと思います。しかし,それでは,前に述べたオーバーラン・エラーが発生する可能性が あります。このようなことを防止するためにプロトコル(フロー制御)を使用することがあり ます。 フロー制御には,RS-232-C で定義されている制御線(RTS と CTS)を用いたハードウェア による方法(ハードウェア・ハンドシェイク)と,ASCII コードで定義されている制御コード (XON と XOFF)を用いたソフトウェアによるものが一般的です。 PC やマイコンなどのデータ端末装置(DTE)間でハードウェア・ハンドシェイクを行う場合 には,互いの RTS と CTS を接続します。図 6 に RL78 マイコンでの接続例を示します。 P00/TxD0 P01/RxD0 P02 P137/INTP0 P00/TxD0 P01/RxD0 P02 P137/INTP0 マイコン マイコン RTS RTS CTS CTS 図 6. マイコンでのハードウェア・ハンドシェイク例
マイコンに内蔵された UART で CTS や RTS がサポートされていることはほとんどなく,汎 用ポート等を使って実現します。UART のハードウェアで CTS 信号をサポートしても,CTS 信号がオフになっても直ぐに送信が停止する訳ではなく,個々の場合で,その後に送信されて くるデータ数が変わってきます。(図 7 参照) 図 7. CTS 信号からのタイミング 通常,UART はダブルバッファ構成になっているので,連続送信機能を使っていると,それ だけで 1 キャラクタ分は送信されてしまいます。これにソフトウェア処理の遅延が加わってく るので,CTS 信号をオフしても直ちに送信は停止しないと考える必要があります。 そのため,CTS 信号を使った制御を行う場合には,送信側が CTS 信号のオフを検知して送信 を停止するまでに送られてしまうデータ数を十分に格納できるバッファ・メモリを持っておく 必要があります。 汎用の RL78 シリーズの SAU の UART 機能にはバッファ・メモリは内蔵されていないので, ソフトウェアで処理(リング・バッファを構成)する必要があります。図 8 に受信時のバッフ ァ管理の概要を示します。 図 8. ハードウェアによるハンドシェイクのバッファ管理 受信バッファに十分に空きがある場合には RTS 信号を立ち下げます。受信完了割り込み処理 プログラムで受信データのバッファ格納を繰り返し,受信バッファの空きが少なくなったとき には RTS 信号を立ち上げます。メイン処理プログラムがバッファからデータを読み出して,バ CTS 信号 RxD 信号 何キャラクタかは不定 受信バッファ バッファ先頭 読み出し用 オフセット 書き込み用 オフセット 受信データ 空のバッファ 受信完了 割り込み 受信データ 読み出し 空きが3キャラクタで RTSを立ち上げ データが3キャラクタ以下で RTSを立ち下げ
ッファに十分な空きができたら RTS 信号を立ち下げます。これを送信側は CTS 信号として確 認し,新たな送信の停止/再開を制御します。 図 9. ハードウェアでのハンドシェイク動作の概要 ソフトウェアによるフロー制御は,主にプリンタのようにバイナリデータではなく,表示可 能なデータを転送する場合に使用された方法として,ASCII コードで定義されている制御信号 XON/XOFF を使用する方法です。受信側が送信側に XON(0x11)を送信許可コード,XOFF (0x13)を送信禁止コードとして送信することで制御するものです。図 10 にフロー制御動作 の概要を示します。 図 10. ソフトウェアでのフロー制御動作の概要 ソフトウェアによるフロー制御では,制御コードの送信時間が余分に必要となるので,その 分はバッファに余裕を持たせておく必要があります。
RTS
CTS
バッファ 空き発生送信許可
INTP または ポート確認 バッファ 空き不足 受信側 処理 INTP または, ポート確認送信禁止
送信側
処理
送信側
受信側
空き発生 送信許可 XON 受信 空き不足 受信側 処理 送信禁止 送信側 処理送信側
受信側
バッフ ァ XON 送信 XOFF 送信 XOFF 受信 送信処理 送信許可 XON 受信 XON 送信 空き発生 送信処理 送信中止プリンタのようにデータの通信方向が一方向で,印字可能キャラクタが対象であれば,比較 的簡単な制御方法です。しかし,双方向にしたり,バイナリデータの転送をしたりするには, データと制御コードを明確に区別できる必要があり,そのための処理が必要になります。 [UART 関連のインタフェース] UART がサポートしている調歩同期通信から派生したインタフェースにも少し触れておきま す。古くは,赤外線通信の IrDA も UART の追加機能としてサポートされていました。新しい 規格の IrDA は UART ではなくなっているようです。
照明関係のインタフェースである DALI(Digital Addressable Lighting Interface)や DMX512 も UART の追加機能で実現されているようです。
基本的には,UART は 2 点間を結ぶインタフェースですが,これをシリアルのバスとして使 うようにしたのが,自動車関係で使用されている LIN(Local Interconnect Network)です。こ れは,単線での通信(単線 UART)方式になります。LIN は比較的低速(20kbps 以下)の通信 を行います。システムコストを抑えるために,マスタは比較的正確なクロックをもちますが, スレーブのクロックの精度はそれほど要求されません。その代わりに,通信の最初に通信速度 (通信クロック)を確定するためのシンク・フィールド(0x55 のデータ)をマスタが送信する ことで,スレーブはマスタの通信速度に合わせることが可能になります。 この 0x55(ASCII コードで”u”)を最初に送るのは昔からよく行われていました。もっとも, 昔は端末側で”u”のキーを押して,0x55 を送信し,マイコン側が受信したデータから 4800bps か 9800bps かなどを自動で判定するような使い方でした。 また,RL78 では,異電位(RL78 より電源電圧が低い)デバイスとの通信を行う機能が追加 されているチャネルがあります。通常,CMOS のハイレベルの入力閾値は電源電圧の 70%~ 80%と規定されています。異電位対応の入力は TTL 入力として 2.2V(電源電圧が 4V 以上時) になっています。出力はオープン・ドレイン出力になるので,電源電圧が低い方の電源に抵抗 でプルアップすることになります。 このような追加機能は個々のデバイスや,使用するチャネルによって異なるので,目的に応 じてデバイスやチャネルを選択する必要があります。 寄り道が長くなりましたが,次ページから RL78 での調歩同期通信について触れていきま す。
[RL78 の UART] RL78 での調歩同期通信を行う UART は SAU(シリアル・アレイ・ユニット)でサポートさ れています。RL78 には最大 4 チャネルのシリアル・チャネルで構成されたユニットが 1 また は 2 個内蔵されています。(図 11 は SAU0 と SAU1 で構成された例を示します。 クロック同期式シリアル(CSI)や簡易 I2C は 1 チャネルで一つのインタフェースとして動作 しますが,UART として使用する場合には,2 チャネルで 1 つの UART を構成します。これ は,CSI では全二重通信とは言っても送信と受信は同じクロックで行うために 1 個のシフトレ ジスタを共用できますが,UART では送信と受信は独立して行う必要があることから 2 個のシ フトレジスタが必要になるためです。 このため,送信側と受信側の両方のチャネルの設定を行う必要があります。このように送信 と受信で独立しているため,コード生成機能を使って動作モードを変更する場合に受信側のボ ーレートは変更したのに送信側の変更を忘れてしまい,自分自身の送信データを正常に受信で きないなんて話をよく聞きました。ここらは,コード生成が気をきかせて両方の設定を変更し てくれればいいのにというぼやきも聞いたことがありますが,基本的に UART で受信と送信は 異なる条件で動作可能である必要があるため不可能です。 SAU の制御では,初期設定の最初に周辺イネーブルレジスタ(PER0 等)でクロックを供給 した後にレジスタの設定を行うことになります。しかし,RL78/I1D では周辺リセット制御レジ スタ(PRR0)が追加されており,ひと手間かける必要があります。コード生成を使えば,そ の分のコードも生成されるので,あまり意識する必要はないかと思いますが。 [RL78 の UART 制御] RL78 の UART は初期設定完了後にシリアル・チャネル開始(SSm)レジスタで使用するチ ャネルの動作開始をトリガすることで,通信待機状態になります。これは,RxD 端子に信号が くれば,また,送信データが書き込まれれば,受信や送信ができる状態です。 チャネルの状態を示すために,チャネルごとにシリアル・ステータス・レジスタ(SSRmn) が準備されています。この中のフラグを使って UART 通信を制御できます。 チャネル 0 チャネル 1 チャネル 2 チャネル 3 チャネル 0 チャネル 1 チャネル 2 チャネル 3 ユニット 0(SAU0) ユニット 1(SAU1) SAU 図 11. RL78 の SAU
よく,「割り込みを使わないで制御したい」との要望がありますが,基本的にこの SSRmn を 使うことで実現可能です。使用するフラグは SSRmn のビット 5 のバッファレジスタ状態表示 フラグ(BFFmn)になります。このフラグは,バッファレジスタに有効なデータが入っている と”1”に,入っていないと”0”になります。ただ,SSRmn レジスタは 16 ビット(SSRmnL では 8 ビット)でのアクセスのみで,ビット操作(ビット名称での参照)ができないので,ビット 位置を意識しておく必要があります。 UART0 で,受信完了を待って受信データを読み出す場合の処理例は以下のようになります。 ここでは,while 文で SSR01L レジスタのビット 5 が 0 の間はループし,ビット 5 が 1 にな り,ループを抜けたら,シリアル・データ・レジスタ(SDR01)の下位 8 ビットからデータを 読み出します。なお,UART 受信時には SDR01 の下位 8 ビットは RXD0 の名称で使うことが できます。(この処理では,受信のエラーは無視しています。) 同様に送信は以下のようにすると,引数 tx_data のデータを送信できます。 なお,「割り込みを使わない」は,ほとんどの場合,ベクタ割り込みの意味で使われているよ うです。そうすると,割り込み要求フラグ(SRIF0 や STIF0)を使った制御も可能です。ただ し,ベクタ割り込みが発生しないように割り込みをマスク(SRMK0 = 1;や STMK0 = 1;)して おくか,割り込み禁止(DI();)にしておく必要があります。この場合の受信処理は以下のよう になります。
この方法は,他の周辺機能でも使うことが可能です。例えば,A/D では SRIF0 を ADIF に RXD0 を ADCR(ただし,work は uint16_t)に置き換えるだけです。 uint8_t UART_RX(void) { uint8_t work; while( 0 == ( SSR01L & 0x20 ) ) // 受信完了待ち { NOP(); } work = RXD0; // 受信データ読み出し return(work); }
void UART_TX(uint8_t tx_data) { while( 0 == ( SSR00L & 0x20 ) ) // 送信完了待ち { NOP(); } TXD0 = tx_data; // 送信データ設定 } uint8_t UART_RX(void) { while( 0 == SRIF0 ) // 受信完了割り込み待ち { NOP(); } SRIF0 = 0; // 割り込み要求フラグをクリア return(RXD0); // 受信データ読み出し }
なお,送信の場合には,そのままでは使えません。と言うのも,送信時はあくまで,送信完 了の割り込み割り込みであり,最初のデータに対しては,そのままでは使えません。同じよう にやろうとすると,初期化完了後にダミーで STIF0 を 1 にしておく必要があります。 受信処理でエラーも確認したいときには,戻り値を 16 ビットにして,その下位 8 ビットに受 信データ,上位 8 ビットに SSR01L の値を入れることが考えられます。 ここでは,特に断らない限り,コード生成のプロパティのファイル生成モードは「初期化関 数のみ出力する」に設定してあるものとしておきます。 [UART での受信エラー対応] 通常,UART を割り込みで処理していれば,オーバランは発生しません。そうすると,発生 する可能性があるエラーはパリティ・エラーとフレーミング・エラーです。この 2 つのエラー について考えてみます。 通常,マイコン同士の UART での通信では,対応しているマイコンで,リセットを解除して 初期化が完了,通信を開始するまでの時間が同じということはありません。必ず,どちらかが 先に初期化を完了して,メイン処理を開始することになります。 ハードウェア・ハンドシェイクしていなければ,先にメイン処理を開始した方が,そのまま UART での送信を開始してしまうと,受信側の準備が整っていない場合には,受信側でエラー が発生することがあります。また,エラーは発生しなくても,間違えたデータを受信してしま うことが考えられます。 STIF0 = 1; // ダミーの送信完了割り込みセット
void UART_TX(uint8_t tx_data) { while( 0 == STIF0 ) // 送信完了待ち { NOP(); } STIF0 = 0; // 割り込み要求フラグをクリア TXD0 = tx_data; // 送信データ設定 } uint16_t UART_RX(void) { uint16_t work; while( 0 == ( SSR01L & 0x20 ) ) // 受信完了待ち { NOP(); } work = SSR01; // ステータス読み出し SIR01 = work; // エラーフラグをクリア work = work << 8; // エラーフラグを上位に work |= RXD0; // 受信データ読み出し return(work); }
図 12 に,この時のタイミングを示します。ここでは,最初に 0x55 を送信し,その後 1 ビッ ト分の時間をおいて次のデータを送信する例を示しています。①のタイミングまでに受信が起 動されていれば,(ボーレートが合っていれば)正常に受信できます。しかし,②のタイミング で受信を起動すると,b1 をスタートビットと解釈して受信動作を開始します。すると,次のデ ータのスタートビットがストップビットと解釈され,フレーミング・エラーが発生することに なります。このように,キャラクタ同期ができていないと,エラーが発生することがありま す。 その後も,ビットずれでデータ 0 をスタートビットと解釈してしまい,受信データがおかし くなったり,フレーミング・エラーが発生したりします。 この状態から抜け出すためには,1 キャラクタ分以上の時間送信しないようにするだけです。 こうすると,送信していない時間の信号はハイレベルが保持され,その間に受信は完了してス タートビット待ちとなり,その後はきちんとスタートビットを検出できます。 RL78 のハードウェア マニュアルには「受信動作を停止して,・・・」とありますが,その必 要はなく,送信側に送信停止要求を送り,一定時間データが送信されてこなくなったら (SSRmn の TSFmn ビットが一定時間 0 なら),そこまでの受信データを捨てて,送信側に送 信許可を通知すれば大丈夫です。ここらは,クロック同期式の CSI よりは簡単です。 似たような問題として,RxD 信号がロウレベルの状態で受信が起動された場合があります。 RxD の立下りでスタートビット検出といっているのに,UART によってはロウレベルだけでス タートビットとみなしていることがあります(昔はほとんどの UART がそうなっていまし た)。RL78 では,きちんと立下りエッジを検出しているようです。 話がそれましたが,エラーの話に戻ります。調歩同期通信で,ボーレートに誤差があると, 後ろの方のビットからおかしくなります。つまり,フレーミング・エラーが出る状態が,少し 誤差がある状態で,パリティ・エラーはさらに誤差が大きい状態です。パリティの設定があっ ているのにパリティ・エラーが発生する時にはボーレート誤差も疑ってみる必要があります。 思いついた内容を書いてきましたが,そろそろおしまいにします。次は実際のサンプルコー ドをアップしていきます。 以上 図 12. UART スタート時の問題 RxD 信号 受信起動 ① ST b0 b7 SP ST ② b1 正常終了