前回LEDの点灯関数として以下を作成しました。
void set_LED_R(int on){
if(on!=0)
PE.DRL.BIT.B0=1;
else
PE.DRL.BIT.B0=0;
}
int get_sw1(void){
return PE.DRL.BIT.B2;
}
入出力の点数が少ない場合はこの様な関数で問題無いと思います。
しかし、入出力の点数が多い場合はどうでしょう。
たとえば入力が
50ピン、出力が
50ピンあった場合。
1端子につき1つ関数を作るならこれだけで
100個もの関数を作る羽目になります。
これは労力の無駄です。
そこで、入力と出力をまとめて操作する関数を作成します。
今回は未設定の部分を新規に使用するのでまずは初期化関数の変更から
初期化関数の更新
/*============= マイコン端子の初期化関数 =============*/
void hardware_setup(void){
//ポートEの特殊機能設定 //今回はポートEの0~15を全て汎用IOに設定する(特殊機能不使用) PFC.PECRL4.WORD = 0x0000;
//PE15-12 PFC.PECRL3.WORD = 0x0000;
//PE11-08 PFC.PECRL2.WORD = 0x0000;
//PE07-04 PFC.PECRL1.WORD = 0x0000;
//PE03-00 //ポートEの入出力を設定する //7,6,3,2を入力それ以外は出力 ⇒ 訂正:3,2を入力それ以外は出力 //1111 1111 1111 0011(2進数) // F F F 3(16進数) PFC.PEIORL.WORD = 0xFFF3;
// !!!注意!!! //ベースボードを接続する場合PE02は出力に設定しないこと。 //ポートAの特殊機能設定 PFC.PACRL4.WORD = 0x0000;
//PA15-12 PFC.PACRL3.WORD = 0x0000;
//PA11-08 //ポートAの入出力を設定する PFC.PAIORL.WORD = 0x0000;
//全部入力}
コメントあるポートを使用したい場合には本来どの設定を変更するかはベースボード付属CDの「資料」フォルダ内にある
ハードウェアマニュアルを調べる必要があります。
ハードウェアマニュアルはマイコンCPUの取扱説明書に相当しますが、マイコンの種類によって
数百ページ~
数千ページあります。しかもこの内容はマイコンの種類ごとのに異なります。このサイトを見てマイコンの勉強を始めた人にこの
ハードウェアマニュアルから
特定の情報を探し出すことは困難だと思います。
現時点ではハードウェアマニュアルは気にせず、そのままコピー&ペーストで動かしてしまってもかまわないと思います。※私の手元にあるファイルでは「rjj09b0249_sh7125_7124hm.pdf」となっていました。
ハードウェアマニュアルは時々更新されるので「rjj09b0249」の部分はベースボードの
出荷時期によって異なるかと思います。
※SH7125の最新版ハードウェアマニュアルはルネサスのHPからダウンロードできます。
この設定が何を意味するかは
秋月sh7125サンプルプログラム解説を参照ください。
入力関数の作成
/*============= PortA入力関数 =============*/
int get_PortA_bit(int bit){
int state=0;
//変数を宣言しておく int outdata=0;
//変数を宣言しておく if( bit<10 || bit>15 )
//関係ない端子を指定した場合 return -1;
//0,1以外の数値を返して強制終了 state = PA.DRL.WORD&(0x0001<<bit);
//0または0以外の値として取得 outdata = (state==0)? 0 : 1 ;
//0-1に変換 return outdata;
//指定したポートの状態を返す}
<解説>
ビット演算も合わせてご参照ください。
state = PA.DRL.WORD&(0x0001<<bit);
スイッチを1つずつ読む場合は
PE.DRL.
BIT.B2と書いていましたが、今回はポートAを一度に読む機能を使用するため
PA.DRL.
WORDとしてアクセスします。
(0x0001<<bit)
この部分はビットシフト演算です。
例えばbitの値が12(13番目)だった場合を考えます。
分かりやすくするため0x0001を2進数で表記してみます
0b000000000000000
1 <<
12↓
0b000
1000000000000
ヒットシフトを行うとこの様にビットの位置がずれます。
PA.DRL.WORD&ビットシフト値
これによりビットシフトした場所の情報を抜き出すことができます。
0b011
0111000100110
& 0b000
1000000000000
↓
0b000
0000000000000
0b100
1010100111001
& 0b000
1000000000000
↓
0b000
1000000000000
ビットシフトした場所のビットが
0だった場合は
0になります。
ビットシフトした場所のビットが
1だった場合は
0以外(ビットシフト値)になります。
outdata
= (state==0)
? 0
: 1 ;
?と
:の組み合わせは
三項演算子と呼ばれています。
内部処理で良く使われていますが、授業で目にすることはほとんど無いでしょう。
三項演算子の使い方は以下となります。
出力先変数
=(条件)
? 条件が一致した場合の値
: 一致しない場合の値;
if文に置き換えると
if(state==0) outdata=1;
else outdata=0;
となります。
また、3項演算子はelse ifの要領で連結することができます。
出力先変数
=(条件1)
? 条件1が一致した場合の値
: (条件2)
? 条件1が一致せず、条件2が一致した場合の値
: (条件3)
? 条件1,2が一致せず、条件3が一致した場合の値
: (条件4)
? 条件1~3が一致せず、条件4が一致した場合の値
: どの条件にも一致しない場合の値;
出力関数の作成
/*============= PortE 4-7出力関数 =============*/
void set_PortE_bit(int bit,int on){
int outdata=0;
if( bit<4 || bit>7 )
//関係ない端子を指定した場合 return;
//ここでこの関数を強制終了 outdata=0x0001<<bit;
if(on==0){
//OFFする場合 PE.DRL.WORD &=~outdata;
//OFF 指定したビットのみ0にする }else{
PE.DRL.WORD |= outdata;
//ON 指定したビットのみ1にする }
}
<解説1>
state=0x0001<<bit;までは入力の場合と一緒です。
同じく
ビット演算も合わせてご参照ください。
まずは簡単な
elseの方の中身から。
問題となるのはこの部分
PE.DRL.WORD
|= outdata;
これをもう少し分かりやすく書くと
PE.DRL.WORD = PE.DRL.WORD
| outdata;
PE.DRL.WORDとoutdataの
OR演算を行い、この結果をPE.DRL.WORDに代入します。
0b011
0111000100110
| 0b000
1000000000000
↓
0b011
1111000100110
0b100
1010100111001
| 0b000
1000000000000
↓
0b100
1010100111001
特定のビットを
1で上書きすることができます。
<解説2>
ちょっと難しい方
PE.DRL.WORD
&=~outdata;
これをもう少し分かりやすく書くと
PE.DRL.WORD = PE.DRL.WORD
&~outdata;
この部分
~outdata;
~はビット反転の演算子で、ビットに対して0→1、1→0の処理となります。
~ 0b000
1000000000000
↓
0b111
0111111111111
この様に
特定のビットのみを簡単に0にすることができます。
このビット反転したビットシフト値とビットAND演算を行っています。
0b011
0111000100110
& 0b111
0111111111111
↓
0b011
0111000100110
0b100
1010100111001 &
& 0b111
0111111111111
↓
0b100
0010100111001
この手順により
特定のビットを
0で上書きすることができます。
<解説3>
ORや
NOT+
ANDを用いなくてもビットシフトした値の
加算、
減算するだけで
なんとかなりそうな気がします。演算してみます。
1にする(加算) 0b011
0111000100110
+ 0b000
1000000000000
↓
0b011
1111000100110
成功
0b10
01010100111001
+ 0b000
1000000000000
↓
0b10
10010100111001
失敗
ビットを足す先に1があったため、
1つ上のビットが変化してしまいました。
更に本来
1としたい部分が0になってしまいました。
0にする(減算) 0b01
10111000100110
- 0b000
1000000000000
↓
0b01
01111000100110
失敗
0b100
1010100111001
- 0b000
1000000000000
↓
0b100
0010100111001
成功
今度はビットを引く先が0だったため、
1つ上のビットが変化してしまいました。
更に本来
0としたい部分が1になってしまいました。
この様に加算減算のみではビットを変化させたい部分の状態によって関係ない箇所を変化させてしまいます。
ビットを変化させたい箇所の状態に応じて処理方法を変えることで対応は可能ですが、行数(無駄な処理)が増えてしまいます。
特定のビットのみ変化させたい場合は
ORと
NOT+ANDの組み合わせを用いるのがスマートです。
今回の内容を記載したファイルを置いておきます。
sw4.c 4ポート操作