Hatena::ブログ(Diary)

お前動けよ。

2010-03-11

SHTinyでシリアル通信をしましょう

 皆さんお元気ですか、僕は元気じゃないです、らいす人です、おはようございます、もうだめです。

 SH7144Fがまだ死んでいなかった時代に、TekuRobo工作室のバッファつきシリアル通信のプログラムが便利で、使っていました(これ)が、秋月のSH7125を使うようになったので、レジスタの名前とかをSH7125のに書き換えたものをつくって使うようになりました。どうやら、TekuRobo工作室のポリシー的に、それを公開しても大丈夫そうな感じなので、続きに置いときますから、みんな使えばいいとおもいます。

 使い方も、全部そのままなので、ここを参考にしてください。


//7125sio.h
//下のコメントは元のやつです

/**********************************************************
7144fsio.h                                        2006.12.5
                                                     RIKIYA
SH2_7144F
バッファ付きSIO1 送受信動作
/*********************************************************/
#define BUFF_SIZE 256

void sci1_init(unsigned short,unsigned char,unsigned char,unsigned char);
char sci1_putchar(char);
void sci1_putstr(char *);
char sci1_getchar(void);

typedef struct {                      // バッファデータ型構造体宣言
    unsigned short remain;            // バッファ中の残データ数
    unsigned short read;              // 書込み位置
    unsigned short write;             // 読出し位置
   char            *buff;             // 読書きデータ
} BUFF;

static char rx1buff[BUFF_SIZE];       // 受信データバッファ
static char tx1buff[BUFF_SIZE];       // 送信データバッファ
static BUFF rx1;                      // BUFF型受信データ構造体
static BUFF tx1;                      // BUFF型送信データ構造体


// SCI1割り込み関数プロトタイプ宣言 ///////////////////////

void int_sci1_eri1(void);
#pragma interrupt INT_SCI1_ERI1
void INT_SCI1_ERI1(void){
int_sci1_eri1();}

void int_sci1_rxi1(void);
#pragma interrupt INT_SCI1_RXI1
void INT_SCI1_RXI1(void){
int_sci1_rxi1();}

void int_sci1_txi1(void);
#pragma interrupt INT_SCI1_TXI1
void INT_SCI1_TXI1(void){
int_sci1_txi1();}

void int_sci1_tei1(void);
#pragma interrupt INT_SCI_TEI1
void INT_SCI1_TEI1(void){
int_sci1_tei1();}


/* SCI1初期化 ********************************************/

#define PCLOCK 25000000

void sci1_init(unsigned short bps,unsigned char bit,unsigned char parity,unsigned char stopbit){
// bps 4800 / 9600 / 14400 / 19200 / 28800 / 31250 / 38400
// bit 8 / 7
// parity 0:無し / 1:偶数パリティ / 2:奇数パリティ
// stopbit 1 / 2

// RX FIFO 初期化
    rx1.remain  = 0;
    rx1.read    = 0;
    rx1.write   = 0;
    rx1.buff    = rx1buff;

// TX FIFO 初期化
    tx1.remain  = 0;
    tx1.read    = 0;
    tx1.write   = 0;
    tx1.buff    = tx1buff;

    STB.CR3.BIT._SCI1 = 0;             // SCI1 スタンバイ解除
    INTC.IPRL.BIT._SCI1 |= 0x000A;          // SCI1 割込みLEVEL = 10
    SCI1.SCSCR.BYTE = 0x00;              // rx,tx割り込み送受信禁止

// 通信フォーマット設定
    // SMR設定
    SCI1.SCSMR.BYTE = 0;                // SMR通信設定白紙

    if(bit == 7){
        SCI1.SCSMR.BIT.CHR = 1;         // データ長7bit設定
    }
    if(parity == 1){
        SCI1.SCSMR.BIT._PE = 1;         // パリティ付加
        SCI1.SCSMR.BIT.OE = 0;          // 偶数パリティ付加

    }
    else if(parity == 2){
        SCI1.SCSMR.BIT._PE = 1;         // パリティ付加
        SCI1.SCSMR.BIT.OE = 1;          // 奇数パリティ付加
    }
    if(stopbit == 2){
        SCI1.SCSMR.BIT.STOP = 1;        // ストップビット 2bit
    }

    // BRR設定
    SCI1.SCBRR = (PCLOCK/(32*bps))-1;   // BRR設定計算

    // PFC設定
    PFC.PACRL1.BIT.PA3MD=1;           // 入力端子PA3 → RXD1 有効
    PFC.PACRL2.BIT.PA4MD=1;           // 出力端子PA4 → TXD1 有効

    // SSR設定
    SCI1.SCSSR.BYTE &= 0x87;            // RDRF / ORER / FER / PER クリア

    // SCR設定
    SCI1.SCSCR.BIT.TIE = 0;             // 送信割り込み禁止
    SCI1.SCSCR.BIT.RIE = 1;             // 受信割り込み許可
    SCI1.SCSCR.BIT.TE = 1;              // 送信許可
    SCI1.SCSCR.BIT.RE = 1;              // 受信許可

}

/* 一文字送信バッファへ格納 ******************************/

char sci1_putchar(char data){
char txdata;

    txdata = -1;                             // エラー時の戻り値

    if(data > 0){

        SCI1.SCSCR.BIT.TIE = 0;                // 送信割り込み禁止

        if(tx1.remain < BUFF_SIZE){          // データ量がバッファより少なければ
            tx1.buff[tx1.write] = data;      // データをバッファに書き込み
	    tx1.remain ++;                   // データ残数を1増
	    tx1.write ++;                    // 書込み位置を1増
	    if(BUFF_SIZE <= tx1.write){      // 書込み位置とバッファサイズの比較
	        tx1.write = 0;               // 大きければ書込み位置を0に。
            }
	    txdata = data;                   // 戻り値用の代入処理
        }
        SCI1.SCSCR.BIT.TIE = 1;                // 送信割り込み許可
    }
    return txdata;                           // txdataを返す
}

/* 文字列送信バッファへ格納 *****************************/
void sci1_putstr(char *str){
    while(*str != '\0'){                     // Nullの検出で終了
        if(*str == '\n'){                    // 改行処理
	    sci1_putchar(0x0a);              // LFラインフィード
            sci1_putchar(0x0d);              // CRキャリッジリターン
        }
	else{
            sci1_putchar(*str);              // 一文字送信処理
	}
	str++;                               // ポインタの1増
    }
    return;
}

/* 送信割り込み *****************************************/

void int_sci1_txi1(void){

char data;

    if(tx1.remain > 0){                      // データ残量が0より大きければ
        data = tx1.buff[tx1.read];           // バッファからデータを読出し
	tx1.remain --;                       // データ残数を1減
	tx1.read ++;                         // 読出し位置を1増
	if(tx1.read >= BUFF_SIZE){           // 読出し位置とバッファサイズの比較
	    tx1.read = 0;                    // 大きければ読出し位置を0に。
        }
        while(SCI1.SCSSR.BIT.TDRE == 0){}      // 送信レジスタが空になるまで待つ。 
	SCI1.SCTDR = data;                     // 読み出したデータを送信レジスタへ。
	SCI1.SCSSR.BIT.TDRE = 0;               // 送信レジスタエンプティフラグのクリア
    }
    else {
        SCI1.SCSCR.BIT.TIE = 0;                // データ残がなければ送信割り込み禁止
    }
}

/* 送信終了割り込み *************************************/

void int_sci1_tei1(void){

    SCI1.SCSCR.BIT.TEIE = 0;                   // 送信終了割り込み禁止

}

/* 一文字受信バッファから読出し**************************/

char sci1_getchar(void){

char data;

    SCI1.SCSCR.BIT.RIE = 0;                    // 受信割り込み禁止

    if(rx1.remain == 0){                     // バッファデータが無ければ
        data = -1;                           // -1を戻り値とする。
    }
    else {                                   // バッファデータがあれば
        data = rx1.buff[rx1.read];           // データのバッファ読み出し
	rx1.remain --;                       // データ残数を1減
	rx1.read ++;                         // 読出し位置を1増
	if(BUFF_SIZE <= rx1.read){           // 読出し位置とバッファサイズの比較
	    rx1.read = 0;                    // 大きければ読出し位置を0に。
	}
    }
    SCI1.SCSCR.BIT.RIE = 1;                    // 受信割り込み許可

    return data;                             // 戻り値 data
}

/* 受信割り込み ****************************************/

void int_sci1_rxi1(void){

char data;

    data = SCI1.SCRDR;                         // 受信データ取り込み
    SCI1.SCSSR.BIT.RDRF = 0;                   // 受信レジスタフルフラグクリア

    if(rx1.remain < BUFF_SIZE){              // データ量がバッファより少なければ
        rx1.buff[rx1.write] = data;          // 受信データをバッファに書込み
	rx1.remain ++;                       // データ残数を1増
	rx1.write ++;                        // 書込み位置を1増
	if(rx1.write >= BUFF_SIZE){          // 書込み位置とバッファサイズの比較
	    rx1.write = 0;                   // 大きければ書込み位置を0に。
        }
    }
}

/* 受信エラー割り込み **********************************/

void int_sci1_eri1(void){

    SCI1.SCSSR.BYTE &= 0x87;      // RDRF / ORER / FER / PER クリア

}

上のは、一応"7125sio.h"ということになってます。コピペしてworkspaceフォルダの直下にそれをぶち込んで、HEWのプロジェクトのメインのファイルから、

#include "../../7125sio.h"

とかやれば、いいんじゃないすかね。まあ、TekuRobo工作室の例が丁寧であてになると思います。

あと、「そんなややこしいことはどうでもいいから、とにかくAD変換の値を俺は見たいんだあああああああああ」な方向けに、「これをコピペすればできるぜ!」みたいなメインのファイルのプログラムもおいておきます。

/***********************************************************************/
/*                                                                     */
/*  FILE        :sensortest.c                                          */
/*  DATE        :Thu, Oct 01, 2009                                     */
/*  DESCRIPTION :Main Program                                          */
/*  CPU TYPE    :SH7125                                                */
/*                                                                     */
/*  This file is generated by Renesas Project Generator (Ver.4.13).    */
/*                                                                     */
/***********************************************************************/

#include "iodefine.h"
#include "../../7125sio.h"
#include "../../itoa.h"

#define MTUCLOCK 6250000

#define SENDADSPEED 500

void init();
void getad(int cycle);
void sendad(void);

int ad[8];


void main(void){
	init();
	while(1);
}



void init(void){
	int i;
	
	PFC.PEIORL.BIT.B8 = 1;
	PFC.PEIORL.BIT.B9 = 1;
	PFC.PEIORL.BIT.B10 = 1;
	PFC.PEIORL.BIT.B11 = 1;
	
	PE.DRL.BIT.B8 = 0;
	PE.DRL.BIT.B9 = 0;
	PE.DRL.BIT.B10 = 0;
	PE.DRL.BIT.B11 = 0;

//Wakeup!!!
	STB.CR4.BIT._AD0 = 0;
	STB.CR4.BIT._AD1 = 0;
	STB.CR4.BIT._MTU2 = 0;         // MTUスタンバイ解除
	
	AD0.ADCSR.BIT.ADM = 0x01;
	AD1.ADCSR.BIT.ADM = 0x01;
	AD0.ADCSR.BIT.CONADF = 1;
	AD1.ADCSR.BIT.CONADF = 1;
	AD0.ADCSR.BIT.CH = 0x03;
	AD1.ADCSR.BIT.CH = 0x03;

	MTU2.TSTR.BYTE = 0;           //MTUストップ
	INTC.IPRD.WORD |= 0xFFFF;    // MTU0,1 割込みLEVEL = 16
	MTU20.TCR.BYTE = 0x01;        // 25MHz/4
	MTU20.TIER.BYTE = 0x08;       //MTU0割り込み許可
	MTU20.TGRD = 6250;
	MTU2.TSTR.BIT.CST0 = 1; //カウントスタート
	
	sci1_init(9600,8,0,1);	//9.6kbps,data8bit,parity0,stop1bit
	sci1_putstr("Hello, World!\n");
	
	for( i = 0; i < 8; i++ ){
		ad[i] = 0;
	}
}




void getad(int cycle){
	int i;
	int tmp[8];
	
	for( i = 0; i < 8; i++ ){
		tmp[i] = 0;
	}
	for( i = 0; i < cycle; i++ ){
		AD0.ADCR.BIT.ADST = 1;		//StartADconvert
		AD1.ADCR.BIT.ADST = 1;		//StartADconvert
		while( AD0.ADCSR.BIT.ADF == 0 || AD1.ADCSR.BIT.ADF == 0 ){}	//Wait for end convert
		tmp[0] += AD0.ADDR0 >> 6;//GetADconvertResult
		tmp[1] += AD0.ADDR1 >> 6;//GetADconvertResult
		tmp[2] += AD0.ADDR2 >> 6;//GetADconvertResult
		tmp[3] += AD0.ADDR3 >> 6;//GetADconvertResult
		tmp[4] += AD1.ADDR4 >> 6;//GetADconvertResult
		tmp[5] += AD1.ADDR5 >> 6;//GetADconvertResult
		tmp[6] += AD1.ADDR6 >> 6;//GetADconvertResult
		tmp[7] += AD1.ADDR7 >> 6;//GetADconvertResult
		AD0.ADCSR.BIT.ADF = 0;		//ResetADconvertEndFlag
		AD1.ADCSR.BIT.ADF = 0;		//ResetADconvertEndFlag
	}
	for( i = 0; i < 8; i++ ){
		ad[i] = tmp[i]/cycle;
	}
}

void sendad(void){
	int i;
	
	for( i = 0; i < 8; i++){
		sci1_putstr(itoa(ad[i]));
		sci1_putstr("\t");
	}
	sci1_putstr("\n");
}


void mtu20d(void){
	int i;
	static int sendadcount = 0;
	static int task = 0;
	
	MTU20.TSR.BIT.TGFD = 0;
	MTU20.TGRD += 6250;
	
	switch( task ){
		case 0 :
			task++;
			PE.DRL.WORD |= 0x0100;
			for( i = 0; i < 100; i++ );
			AD0.ADCR.BIT.ADST = 1;		//StartADconvert
			while( AD0.ADCSR.BIT.ADF == 0 );	//Wait for end convert
			PE.DRL.WORD &= 0xFeFF;
			ad[0] = AD0.ADDR0 >> 6;//GetADconvertResult
			break;
		case 1 :
			task++;
			PE.DRL.WORD |= 0x0200;
			for( i = 0; i < 100; i++ );
			AD0.ADCR.BIT.ADST = 1;		//StartADconvert
			while( AD0.ADCSR.BIT.ADF == 0 );	//Wait for end convert
			PE.DRL.WORD &= 0xFdFF;
			ad[1] = AD0.ADDR1 >> 6;//GetADconvertResult
			break;
		case 2 :
			task++;
			PE.DRL.WORD |= 0x0400;
			for( i = 0; i < 100; i++ );
			AD0.ADCR.BIT.ADST = 1;		//StartADconvert
			while( AD0.ADCSR.BIT.ADF == 0 );	//Wait for end convert
			PE.DRL.WORD &= 0xFbFF;
			ad[2] = AD0.ADDR2 >> 6;//GetADconvertResult
			break;
		case 3 :
			task = 0;
			PE.DRL.WORD |= 0x0800;
			for( i = 0; i < 100; i++ );
			AD0.ADCR.BIT.ADST = 1;		//StartADconvert
			while( AD0.ADCSR.BIT.ADF == 0 );	//Wait for end convert
			PE.DRL.WORD &= 0xF7FF;
			ad[3] = AD0.ADDR3 >> 6;//GetADconvertResult
			break;
	}
	AD0.ADCSR.BIT.ADF = 0;		//ResetADconvertEndFlag
	
	
	sendadcount++;
	if( sendadcount == SENDADSPEED ){
		sendadcount = 0;
		sendad();
	}
}

intprg.cも、ちょっと細工を。

// 91 MTU2_0 TGID0
void mtu20d();
void INT_MTU2_0_TGID0(void){mtu20d();}

こんな感じにかえてください。

かなりいい加減です。作った本人がいい加減だというのだから相当いい加減です。

なぜなら、PortEの8-11で、変なパルスをついでに出してます。

ああそうだ、itoa.hを忘れてた。これもいい加減ですけど、それで動いてるのでいいやみたいな感じで放置してます。これもworkspaceフォルダの直下にぶち込みます。

//itoa.h

char *itoa( int i );

char *itoa ( int i ){
	static char buf[16];
	char *p;
	
	p = buf+sizeof(buf)-1;
	*p = '\0';
	do{
		p--;
		*p = i % 10 + '0';
		i = i / 10;
	}while( i > 0 );
	return p;
}

なんかもうまとまらない感じなんですけど、シンプルにしてみたやつもおいときます。

/***********************************************************************/
/*                                                                     */
/*  FILE        :sensortest.c                                          */
/*  DATE        :Thu, Oct 01, 2009                                     */
/*  DESCRIPTION :Main Program                                          */
/*  CPU TYPE    :SH7125                                                */
/*                                                                     */
/*  This file is generated by Renesas Project Generator (Ver.4.13).    */
/*                                                                     */
/***********************************************************************/

#include "iodefine.h"
#include "../../7125sio.h"
#include "../../itoa.h"

#define MTUCLOCK 6250000

#define SENDADSPEED 500

void init();
void getad(int cycle);
void sendad(void);

int ad[8];

void main(void){
	init();
	while(1);
}



void init(void){
	int i;

//Wakeup!!!
	STB.CR4.BIT._AD0 = 0;
	STB.CR4.BIT._AD1 = 0;
	STB.CR4.BIT._MTU2 = 0;         // MTUスタンバイ解除
	
	AD0.ADCSR.BIT.ADM = 0x01;
	AD1.ADCSR.BIT.ADM = 0x01;
	AD0.ADCSR.BIT.CONADF = 1;
	AD1.ADCSR.BIT.CONADF = 1;
	AD0.ADCSR.BIT.CH = 0x03;
	AD1.ADCSR.BIT.CH = 0x03;

	MTU2.TSTR.BYTE = 0;           //MTUストップ
	INTC.IPRD.WORD |= 0xFFFF;    // MTU0,1 割込みLEVEL = 16
	MTU20.TCR.BYTE = 0x01;        // 25MHz/4
	MTU20.TIER.BYTE = 0x08;       //MTU0割り込み許可
	MTU20.TGRD = 6250;
	MTU2.TSTR.BIT.CST0 = 1; //カウントスタート
	
	sci1_init(9600,8,0,1);	//9.6kbps,data8bit,parity0,stop1bit
	sci1_putstr("Hello, World!\n");
	
	for( i = 0; i < 8; i++ ){
		ad[i] = 0;
	}
}

void getad(int cycle){
	int i;
	int tmp[8];
	
	for( i = 0; i < 8; i++ ){
		tmp[i] = 0;
	}
	for( i = 0; i < cycle; i++ ){
		AD0.ADCR.BIT.ADST = 1;		//StartADconvert
		AD1.ADCR.BIT.ADST = 1;		//StartADconvert
		while( AD0.ADCSR.BIT.ADF == 0 || AD1.ADCSR.BIT.ADF == 0 ){}	//Wait for end convert
		tmp[0] += AD0.ADDR0 >> 6;//GetADconvertResult
		tmp[1] += AD0.ADDR1 >> 6;//GetADconvertResult
		tmp[2] += AD0.ADDR2 >> 6;//GetADconvertResult
		tmp[3] += AD0.ADDR3 >> 6;//GetADconvertResult
		tmp[4] += AD1.ADDR4 >> 6;//GetADconvertResult
		tmp[5] += AD1.ADDR5 >> 6;//GetADconvertResult
		tmp[6] += AD1.ADDR6 >> 6;//GetADconvertResult
		tmp[7] += AD1.ADDR7 >> 6;//GetADconvertResult
		AD0.ADCSR.BIT.ADF = 0;		//ResetADconvertEndFlag
		AD1.ADCSR.BIT.ADF = 0;		//ResetADconvertEndFlag
	}
	for( i = 0; i < 8; i++ ){
		ad[i] = tmp[i]/cycle;
	}
}

void sendad(void){
	int i;
	
	for( i = 0; i < 8; i++){
		sci1_putstr(itoa(ad[i]));
		sci1_putstr("\t");
	}
	sci1_putstr("\n");
}


void mtu20d(void){
	int i;
	static int sendadcount = 0;
	
	MTU20.TSR.BIT.TGFD = 0;
	MTU20.TGRD += 6250;

	getad(1);
	
	sendadcount++;
	if( sendadcount == SENDADSPEED ){
		sendadcount = 0;
		sendad();
	}
}

なんか最初っからこっちだけにすればよかったんじゃないかという感じですが、さっきのパルス出すやつはマイクロマウスのセンサ用なので、マイクロマウスやる人は適当に使ってみてもいいんじゃなかろうかと思いました。


おしまい。

ところで、SH7125使ってる人たちは多分、こんな程度のプログラム自前で持ってるに決まってますね。いまさらだけど誰得

SH7125でSPIとI2Cが使いたいです。前者は秋月で売ってるADコンバータに、後者はEEPROMに使いたい。

あと、16文字*2行のディスプレイとかに、シリアルケーブルとか通じて送られてくる文字を表示してって、EEPROMにデータを蓄積するみたいなの作ってみたい。

yutayuta 2010/03/12 01:02 7125に標準でI2C付けてくれればホントにどれだけ良かったか。

licepersonliceperson 2010/03/12 06:55 >>yuta先輩
お久しぶりです。7144Fにはちゃっかりついてるんですよね。
ところで、知能ロボコンは200g以下になるとか恐ろしいことをどこかで言われていたような…

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/liceperson/20100311/1268298987