[H8-ML(3269)] Re: 割込みによるシリアル通信について(ビットフィールド話)
From: Amaike takehiro <tanpa@xxxxxxxxx>
Date: 2003年05月26日(月)00時53分51秒
こんばんわ、天池です。

出掛けていたらいつの間にかスレが肥大化してどこをレス元にして良いのかも判
らない状態に・・・(^^;

【鈴木様への話は下にあります】

私、昨日は3069をルネサスヘッダで遊んでみました。
でも、慣れていなかったせいかそれほどの利点を感じられず、元の
read-modify-writeに戻してしまいました。

-----
私がYCH8とビットフィールドの話を振ってしまった訳ですが、スレの流れがあま
り良い方向に進んでいないのでちょっと皆さん落ち着きましょう。

あるコンパイラが「ビットフィールドに弱い?」とか「アセンブラレベルでどう
変換されるか不明瞭」とかいう話はH8に限らずあるのだと思いますので、この際
「動く」事を前提にして「こっちの方法だとこう便利だよ」とか「こういう実装
方法もあるよ」などのテクニックを皆さんで出した方が発展的で良いのではない
でしょうか。
マイコン初心者の方などでは、C言語も初心者である人もいると思います。
そういう人にも有益な情報が出ると良いなと思います。

ちなみに私はマクロ派なので
#define		LCD_E(c)	P9DR = (P9DR & ~(0x10)) | (c & 0x10)
#define		LCD_RS(c)	P9DR = (P9DR & ~(0x20)) | (c & 0x20)
#define		LCD_DATA(c)	PADR = (PADR & 0x0F) | ((c << 4) & 0xF0)
こんな感じのマクロを組んで書き込んだりしてます。

# ↑結局LCDのバスアクセスは諦めたらしい。
# 動かない時のの検証はロジアナ無いと無理っぽ(;_;)

===== 話をまた戻しまして =====

> その他の関数は、
> (1)シリアルポート0の初期化関数 [3239]に記述。
> (2)割り込み時の動作関数 []
>   ・割込みで1文字受信する関数
>     char intrxi0(void){
>       char data;/* 受信データ変数宣言 */
>       switch(SCI0.SSR.BIT.RDRF)/* 受信状態判定 */
>         {
>           case 1:/* RDRF=1 正常受信 */
>             SCI0.SSR.BIT.RDRF = 0;/* 受信フラグクリア*/
>             data = SCI0.RDR;/* data 取り出し */
>             return(data);
>           default:/* エラー発生時 */
>             SCI0.SSR.BYTE &= 0xc7;/* エラーフラグクリア */
>             return(0xff);
>         }
>     }
> 
>   ・受信文字列を変数に保存する関数
>       -- (YelowSoftのProjectに割り込みを登録する関数)--
>     int str_read(){
> 	int i;
> 	char rx_data;/*受信データ*/
> 	char *p;/*ポインタ変数*/
> 	p = &STR;
>         do{
>           rx_data = intrxi0();	/* 1文字受信 */
>           if(rx_data != 0xff){
>             *p = rx_data;/* 1文字を文字列に格納 */
>             p++;/* 次の文字アドレスへ 
>         }while(rx_data != '\0');
>         FLG = 1;/**/	
>     }

えっとですね。数点あります。

1. 割り込み関数について
受信割り込み時に呼ばれる関数が intrxi0(void) ですね?
割り込み関数には返値(return)はありません。終わったらただ抜けてしまいます。
よって、全ての情報はグローバル変数に残しておく必要があります。

2. 受信エラー割り込みベクタは受信データフル割り込みベクタとは別です。

私のやり方を書きます(3048の例です)

/* グローバル変数 */
unsigned char RXBUF[50];			/* 受信バッファ */
unsigned char rx_len;				/* 受信用MSG長 */
unsigned char rx_phase;				/* 0:待機 1:受信中 */

/* SCI0受信データフル割込み */
interrupt void RXI0_Interrupt(void) {
	if (rx_phase == 2) {
		SSR0 &= ~(0x40);		/* RDRFフラグをクリア */
		return;				/* 受信データ処理中なら無視 */
	}
	while((SSR0 & 0x40) == 0x40){		/* RDRF(受信データフル)の確認 */
		RXBUF[rx_len++] = RDR0;		/* バッファへの書き込み */
		rx_phase = 1;			/* 受信データがあるよん */
	}
	SSR0 &= ~(0x40);			/* RDRFフラグをクリア */
}

/* SCI0受信エラー割り込み */
interrupt void ERI0_Interrupt(void) {
	rx_phase = 0;				/* 受信やり直し */
	rx_len = 0;				/* ポインタリセット */
	SSR0 &= ~(0x38);			/* ORER/FER/PER フラグクリア */
}

void main(void) {
	Init_Serial();
	Init_Timer();
	
	/* 受信開始 */
	tx_phase = 0;
	rx_phase = 0;
	_ei();	
	while(1) {
		if (rx_phase == 1) {
			rx_phase = 2;		/* 処理中にする */
			... RX_BUFのでーたを使った処理を書く
			rx_phase = 0;
			rx_len = 0;		/* 受信開始 */
		}
	}
}

この例は、データの送られ方が規則的なのでこうやっていますが、本当ならリン
グバッファを組むべきと思います。(デバッグ用RAMが足らなかった・・・)
バッファ構成とメイン処理は自分で工夫してみてください。

-----
たんぱぁ@ShootingStarLAB(天池岳雄)
mail: tanpa@xxxxxxxxx
URL: http://www.ss-lab.com/


スレッド概略
[3245(R)](起点)
 └[3268(U)]
   └[表示中]
     ├[3274(1)]
     └[3285(2)]


投稿順に移動
[←前の記事へ(P)]
[→次の記事へ(N)]


リスト表示へ
[このスレッド(T)]
[本記事の前後(L)]