関連:
シリアル通信関連記事一覧PCで送受信できることが確認できたのでSH7125のシリアル通信の設定を行っていきます。
SH7125でのシリアル通信の機能名は
SCI(
Serial
Communication
Interface)です。
ピン設定の確認
ベースボードに付いているコネクタを使ってシリアル通信を行います。
って事でその
コネクタに繋がっている端子を制御する必要があります。
ベースボードキットの取説を確認してみます。
手元にない人は
秋月のページからダウンロードしてください
最後のページの回路図を見ます。
右の方にある楕円(表記JP3)がRS232Cのコネクタです。
2本配線が伸びてIC2に接続されています。
IC2は
前々回説明した電圧変換ICです。
さらにJP2へ配線が伸びています。
これはCPUボードを外すと見えるジャンパピンです。
ジャンパピンが刺さっていると1と2、3と4がつながります。
さらにたどっていくとPA3とPA4に繋がっています。
要するに
PA3と
PA4が制御すべき端子です。
続いてCPUボードの取説またはハードウェアマニュアルを見てみます。
TXDと
RXDがそれぞれシリアル通信のデータ送信(
Transmit
Data)とデータ受信(
Recive
Data)の機能です。
PA3が
RXD1、
PA4が
TXD1となっています。
SH7125では
SCI0、
SCI1、
SCI2の合計3系統のシリアル通信機能が搭載されています。
今回使う
RXD1、
TXD1は番号の通り
SCI1の機能に該当します。
という事で、付属のコネクタで通信を行うには
SCI1の機能を設定する必要があります。
プログラムの作成
まずは割り込みを使わない方式で文字送信を試みます。
初期設定
初期化関数を作ります。
設定1、モジュールのスタンバイ解除とピン設定
<設定>void init_SCI1(void){
STB.CR3.BIT._SCI1=0;
//モジュールスタンバイ解除 PFC.PACRL1.BIT.PA3MD=1;
//PA3をRXD1入力に設定 PFC.PACRL2.BIT.PA4MD=1;
//PA4をTXD1出力に設定 SCI1.SCSCR.BYTE=0x00;
//設定中のため送受信割込禁止、送受信禁止<用語>SCSCR:シリアルコントロールレジスタ
シリアル通信にかかわる機能や割り込みの有効/無効を設定ます。
PACRL1の設定方法は
PWMなどに設定する場合と一緒です。
設定2、通信条件の設定
<設定> SCI1.SCSMR.BYTE=0x00;
//とりあえず全部0(標準設定)にしておく SCI1.SCSMR.BIT._PE = 1;
// パリティー有効:1/無効:0 SCI1.SCSMR.BIT.OE = 0;
// パリティー奇数:1/偶数:0// 25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80 // SCI1.SCBRR=80; //9600bps// SCI1.SCBRR=39; //19200bps SCI1.SCBRR=19; //38400bps
// SCI1.SCBRR=6; //115200bps<用語>SCSMR:シリアルモードレジスタ
シリアル通信の通信条件を設定します。
0:調歩同期式モード / 1:クロック同期式モード
0:8ビットデータ / 1:7ビットデータ
0:パリティ無効 / 1:パリティ無効
0:偶数パリティ / 1:奇数パリティ
0:1ストップビット / 1:2ストップビット
0:マルチプロセッサモード無効 / 1:マルチプロセッサモード有効
00:Pφクロック 01:Pφ/4クロック 10:Pφ/16クロック 11:Pφ/64クロック
調歩同期式モード(受信側がストップビット基準で同期をとってくださいモード)たぶん
クロック同期式モード(データ以外にクロックを別途送るのでそれで同期をとってくださいモード)
マルチプロセッサモードは知りません。
一番最後のクロック選択はPWMやCMTでのクロック選択を同じような考え方です。
その他は
PCでシリアル通信を行ったときに出てきた項目に該当します。
SCBRR:ビットレートレジスタ
シリアル通信の通信速度を設定します。設定する値Nは以下で求めます。
N = (
Pφ)×10^6 ÷ (64×2^(2
n-1)×
B) - 1
Pφ:25MHz
n:クロックセレクトを00に設定したので0
を入れると
N = 25000000 ÷ (32×
B) - 1
Bはビットレートです
B=38400bpsだと
N=19.34
N=
19に設定→通信誤差1.7%
B=115200bpsだと
N=5.78
N=
6に設定→通信誤差3%
設定3、通信開始<設定> SCI1.SCSCR.BIT.TE = 1;
// トランスミットイネーブル:送信動作を許可 SCI1.SCSCR.BIT.RE = 1;
// レシーブイネーブル:受信動作を許可 これで1文字ずつ送受信の準備ができました。
送信プログラム
起動時に文字'A'を送信してみます。
<設定>void main(){
init_SCI1();
//シリアル通信1の初期化 SCI1.SCTDR='A';
//送信データを設定 SCI1.SCSSR.BIT.TDRE = 0;
//送信開始 while(1){
//無限ループ開始 }
}
<用語>SCTDR:トランスミットデータレジスタ
送信するデータをここに入れます。
TDRE:トランスミットデータレジスタエンプティ
送信できる文字が無いとき1になります。
0に設定すると送信が開始され、
送信が完了すると送信できる文字が無いため1になります。
全部まとめるとこんな感じ
<設定>#include "iodefine.h"
//シリアル通信1初期化関数void init_SCI1(void){
STB.CR3.BIT._SCI1=0;
//モジュールスタンバイ解除 PFC.PACRL1.BIT.PA3MD=1;
//PA3をRXD1入力に設定 PFC.PACRL2.BIT.PA4MD=1;
//PA4をTXD1出力に設定 SCI1.SCSCR.BYTE=0x00;
//設定中のため送受信割込禁止、送受信禁止 SCI1.SCSMR.BYTE=0x00;
//とりあえず全部0(標準設定)にしておく SCI1.SCSMR.BIT._PE = 1;
// パリティー有効:1/無効:0 SCI1.SCSMR.BIT.OE = 0;
// パリティー奇数:1/偶数:0// 25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80 // SCI1.SCBRR=80; //9600bps// SCI1.SCBRR=39; //19200bps SCI1.SCBRR=19; //38400bps
// SCI1.SCBRR=6; //115200bps SCI1.SCSCR.BIT.TE = 1;
// トランスミットイネーブル:送信動作を許可 SCI1.SCSCR.BIT.RE = 1;
// レシーブイネーブル:受信動作を許可 }
//メイン関数void main(){
init_SCI1();
//シリアル通信1の初期化 SCI1.SCTDR='A';
//送信データを設定 SCI1.SCSSR.BIT.TDRE = 0;
//送信開始 while(1){
//無限ループ開始 }
//end while}
//end main
動作確認
書き込みが完了したらマイコンから出力される文字を
TMZで受信してみます。
※FDTでデバイスとの切断を行っていないとTMZで「ポートをオープンできませんでした」が出ます。めんどくさいのでFDTのオプション→自動切断にチェックを入れておくと便利です。TMZの設定は
前回に引き続き
ビットレート :38400
文字サイズ :8
フロー制御 :制御なし
パリティービット:偶数パリティー
停止ビット :1ビット
エコー :OFF
この状態でマイコンを起動してTMZにAが表示されれば成功です。
マイコンの電源入れ直し、またはリセットボタンを押す度にAが表示されるはずです。
ASCIIコードを理解する
SCI1.SCTDR=
'A';
を
SCI1.SCTDR=
0x42;
へ変換して実行してみます。
※TMZを終了してCOMポートを開放しておかないとFDTで「ポートのオープンエラー」が出てプログラムを書き込むことができません。今度はTMZに
Bが表示されるはずです。
0x41とすると
Aが表示されます。
これは文字コード
0x41(10進数の65)が
文字のAに相当するからです。
※sprintf等の関数は文字列が文字コードに変換しています。
この文字コードは
ASCIIコード(アスキーコード)と呼ばれるものです。
シリアル通信で文字を送る場合はこのASCIIコードが適用されます。
文字を送る通信を
テキスト通信数値をそのまま送る通信を
バイナリ通信といった呼び方をします。
今後は主にテキスト通信を扱っていくものとします。
文字を受信する
送信ができたので受信してみます。
メイン関数を以下の様に変更します。
<設定>void main(){
init_SCI1();
//シリアル通信1の初期化 SCI1.SCTDR='A';
//送信データを設定 SCI1.SCSSR.BIT.TDRE = 0;
//送信開始 while(1){
//無限ループ開始 if(SCI1.SCSSR.BIT.RDRF){ //何か受信した SCI1.SCSSR.BIT.RDRF=0; //受信フラグを下す SCI1.SCTDR=SCI1.SCRDR; //受信文字を送信データに設定 SCI1.SCSSR.BIT.TDRE = 0; //送信開始 }//end if }
//end while}
//end main<用語>RDRF:レシーブデータレジスタフル
何かデータを受信すると1になる。
一度1になると、0を入れないの1のまま
<解説>if文で受信が来ているか確認し、受信があれば
とりあえず受信フラグを下す
受信したデータを送信用データとして設定
送信開始
動作確認
起動時に'A'が表示されることに変わりはありません。
ここでTMZから文字を送信してみます。
TMZから送信した文字がTMZに表示されれば成功です。
通信を使った簡単な制御
文字を使ってLEDの制御をしてみます。
汎用IO設定ソース:
io_setup.c 汎用IO設定ヘッダ:
io_setup.hを読み込みます。
io_setupは割り込みを使用していないのでそのまま読み込むだけで使えます。
文字
'W'で赤点灯、緑点灯
文字
'A'で赤消灯、緑点灯
文字
'D'で赤点灯、緑消灯
文字
'S'で赤消灯、緑消灯
とします。
<設定>
#include "iodefine.h"
#include "io_setup.h"
//シリアル通信1初期化関数void init_SCI1(void){
STB.CR3.BIT._SCI1=0;
//モジュールスタンバイ解除 PFC.PACRL1.BIT.PA3MD=1;
//PA3をRXD1入力に設定 PFC.PACRL2.BIT.PA4MD=1;
//PA4をTXD1出力に設定 SCI1.SCSCR.BYTE=0x00;
//設定中のため送受信割込禁止、送受信禁止 SCI1.SCSMR.BYTE=0x00;
//とりあえず全部0(標準設定)にしておく SCI1.SCSMR.BIT._PE = 1;
// パリティー有効:1/無効:0 SCI1.SCSMR.BIT.OE = 0;
// パリティー奇数:1/偶数:0// 25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80 // SCI1.SCBRR=80; //9600bps// SCI1.SCBRR=39; //19200bps SCI1.SCBRR=19; //38400bps
// SCI1.SCBRR=6; //115200bps SCI1.SCSCR.BIT.TE = 1;
// トランスミットイネーブル:送信動作を許可 SCI1.SCSCR.BIT.RE = 1;
// レシーブイネーブル:受信動作を許可 }
//メイン関数void main(){
hardware_setup(); //汎用IOの初期化
init_SCI1();
//シリアル通信1の初期化 SCI1.SCTDR='A';
//送信データを設定 SCI1.SCSSR.BIT.TDRE = 0;
//送信開始 while(1){
//無限ループ開始 if(SCI1.SCSSR.BIT.RDRF){
//何か受信した SCI1.SCSSR.BIT.RDRF=0;
//受信フラグを下す SCI1.SCTDR=SCI1.SCRDR;
//受信文字を送信データに設定 SCI1.SCSSR.BIT.TDRE = 0;
//送信開始 if(SCI1.SCRDR=='W'){ set_LED_R(1); set_LED_G(1); } if(SCI1.SCRDR=='A'){ set_LED_R(0); set_LED_G(1); } if(SCI1.SCRDR=='D'){ set_LED_R(1); set_LED_G(0); } if(SCI1.SCRDR=='S'){ set_LED_R(0); set_LED_G(0); } }
//end if }
//end while}
//end main送信した文字に応じてLEDの点灯が変われば成功です。
次回、文字列を連続して送信するために割り込み処理を設定します。
更にややこしくなります。