歩き遍路 平成19年春(J1) 記録の準備
SPIでUSB( 6) H8のSPI での
   MSB Firstデータ転送をハードウエア化

 SPIでUSB( 5)でH8のハードウエアSPIのデータ出力は、LSBファースト固定なのでソフトウエアでビットスワップを実現したプログラムを記録したのですがハードウエアで実現できたので、それを実験しました。

●MSB Firstデータ転送をハードウエア化

 ひょんなことから解決しました。朝メールを見ていると「RXファミリの第一弾製品 RX610グループがいよいよ登場」とあります。
 いよいよ登場かと思いながらハードウエアマニュアルを眺めていると、奇妙な説明が目に入りました。
 「クロック同期式シリアル通信のデータフォーマット(LSBファーストの場合)」の(LSBファーストの場合)です。
 さすが、最新のマイコンは進んでいるな!と感心してレジスタの説明を見ると、SCMRレジスタのSDIRビットを・・・とあります。SCMRレジスタはH8/3067にも有ったのではと見るとあります。小さく注釈があり・・・。

 と云う訳で、ビットスワップをハードウエアで実現できました。


 

 因みに、シングルチップのH8/3694にはSCMRレジスタはありません。

●SPIマスタのプログラム  ハードウエアによるビットスワップ版

 SPIマスタのプログラムを次に示します。このプログラムは、PIC18F4520プログラムのSPI部分をH8/3067用に変更しました。
 プログラムの動きは、 H8/3067に接続してある4個のスイッチを読み取りSPIでMCP23S08に送りLEDを制御します。
 次に、MCP23S08に接続してある4個のスイッチをSPIで読み取り、H8/3067に接続してある4個のLEDを制御します。
 
 イエローソフト社のCコンパイラでは、I/Oポート定義はユーザーで定義するようになっているのでここではプログラムファイルで定義しています。
 SPIマスタはSCI2を使ってハードウエアで実現しました。SPIクロックは1MHzです。ハードウエアによるビットスワップ版です。

/**************************************************************
*
* AkiH8/3067のSCI2を使ってMCP23S08とSPI接続
*
* AkiH8/3067接続のSWでMCP23S08接続のLEDを制御
* MCP23S08接続のSWでAkiH8/3067接続のLEDを制御
*
***************************************************************

/** I N C L U D E S *******************************************/
#include <sysio.h>


#define P4DR (*((volatile unsigned char *)(0xffffd3)))
#define P4DDR (*((volatile unsigned char *)(0xfee003)))
#define P7DR (*((volatile unsigned char *)(0xffffd6)))
#define PADR (*((volatile unsigned char *)(0xffffd9)))
#define PADDR (*((volatile unsigned char *)(0xfee009)))
#define PBDR (*((volatile unsigned char *)(0xffffda)))
#define PBDDR (*((volatile unsigned char *)(0xfee00a)))

#define SMR2 (*((volatile unsigned char *)(0xffffc0)))
#define BRR2 (*((volatile unsigned char *)(0xffffc1)))
#define SCR2 (*((volatile unsigned char *)(0xffffc2)))
#define TDR2 (*((volatile unsigned char *)(0xffffc3)))
#define SSR2 (*((volatile unsigned char *)(0xffffc4)))
#define RDR2 (*((volatile unsigned char *)(0xffffc5)))
#define SCMR2 (*((volatile unsigned char *)(0xffffc6)))
// ********************
// ***** 時間遅延関数
void TD10CY(void){
char i,Tmp;

for (i=0; i<10; i++) {
Tmp = i; // ダミー動作
}
}

void TD10CYx(char data){
char i;

for (i=0; i<data; i++) {
TD10CY(); //時間待ち
}
}
// ***** ビットスワップ関数
char BitSwap(char data){
char Temp = 0x00;

if(data & 0x80) Temp = Temp + 0x01;
if(data & 0x40) Temp = Temp + 0x02;
if(data & 0x20) Temp = Temp + 0x04;
if(data & 0x10) Temp = Temp + 0x08;
if(data & 0x08) Temp = Temp + 0x10;
if(data & 0x04) Temp = Temp + 0x20;
if(data & 0x02) Temp = Temp + 0x40;
if(data & 0x01) Temp = Temp + 0x80;
return(Temp); //ビットスワップデータ戻り
}
// ***** SPI送受信関数 SSピン制御無し
char SpiTxRx(char data){
char Temp;

Temp = SSR2; //シリアルステータスレジスタ読出し
while((Temp & 0x80)== 0x00) { //送信バッファ空か
TD10CY(); //時間待ち
Temp = SSR2; //シリアルステータスレジスタ読出し
}

// Temp = BitSwap(data); //送信データをビットスワップ
TDR2 = data; //送信データ設定
SSR2 = 0x00; //送信指令

Temp = SSR2; //シリアルステータスレジスタ読出し
while((Temp & 0x40)== 0x00) { //受信完了化
Temp = SSR2; //シリアルステータスレジスタ読出し
}

data = RDR2; //受信データ読み出し
// Temp = BitSwap(data); //送信データをビットスワップ
return(data); //受信データ戻り
}
// ********************
// ***** メイン
void main()
{
char tempData;
char tempData2;
char tempData3;

_ei(); /* 割込み許可 */

//ポートデータ初期値設定
P4DR = 0xFF; // データ
PADR = 0xFF; // データ
PBDR = 0xFF; // データ

//ポート方向設定 TPxDDR 0 = IN, 1 = OUT
P4DDR = 0xFF; // bit7-0は出力
PADDR = 0x0F; // bit7-4は入力、 bit3-0はLED出力
PBDDR = 0xFF; // SPIポート

// *** SCI2初期設定 Spiマスター、クロック:1Mbps
SCR2 = 0x00; // 送受信不許可、クロック出力:シリアルコントロールレジスタ
SMR2 = 0x80; // クロック同期モード:シリアルモードレジスタ
BRR2 = 0x04; // 1Mbps@20MHz:ビットレートレジスタ
TD10CY();
SCR2 = 0x30; // 送受信許可、クロック出力:シリアルコントロールレジスタ
SCMR2 = 0xFA; // MsbFirst送信を設定


// ************ H8のSPIは、LSB先頭なのでデータを逆に設定している。
// *** MCP23S08の方向Reg設定 Bit7-4:Input,3-0:Output
PBDR = (P4DR & ~0x10); //SSピンLow


SpiTxRx(0x40); //SPI送受信 Writeオペコード
SpiTxRx(0x00); //SPI送受信 方向RegAdrs
SpiTxRx(0xF0); //SPI送受信 1:Input,0:Output
PBDR = (PBDR | 0x10); //SSピンHigh
TD10CYx(100);

/// メインループ
while(1)
{
/// スイッチを読込みPSI通信でデバイスに送信
tempData= P7DR; // スイッチ状態を読込み
PBDR = (PBDR & ~0x10); //SSピンLow
SpiTxRx(0x40); //SPI送受信 オペコード
SpiTxRx(0x0A); //SPI送受信 ラッチRegAdrs
SpiTxRx(tempData); //SPI送受信 スイッチData
PBDR = (PBDR | 0x10); //SSピンHigh
TD10CY();

/// デバイスからPSI通信でスイッチを受信して、LEDに表示
PBDR = (PBDR & ~0x10); //SSピンLow
SpiTxRx(0x41); //SPI送受信 オペコード
SpiTxRx(0x09); //SPI送受信 GPIORegAdrs
tempData2 = SpiTxRx(tempData); //SPI送受信 スイッチData
PBDR = (PBDR | 0x10); //SSピンHigh

PADR = tempData2>> 4; //LEDデータ抽出

TD10CYx(5);

}//END of while(1)
}//END of main



●プログラムの実行と結果

 問題無くスイッチを操作するとLEDは動きました。 


ホームへ戻る