目次
前
次
スタートゲートセンサー
SHARPのPDSは、スタートゲートセンサーとして
よく利用されているようですが、人と同じもの
は使いたくないと思い、秋月電子で販売されて
いる、超音波センサーが使えるかテストです。
5ピンのLタイプピンを半田付けし、5ピンケーブル
で、相手のマイクロコンピュータに接続します。
LEDがある側に、+5V。その下にRxD、TxD、
MODE、GNDとピンが配置されています。
秋月電子のサイトから、リンクをたどり、次の
仕様がわかりました。
- +5Vで送受信一体タイプ
- 同じ通信線に、センサーを16台接続可能
- シリアルインタフェース、IICバスのどちらでも動作可能
- シリアルインタフェースでは、TTLレベルの振幅利用
- シリアルでは、9600bps、2ストップビット、パリティなし、フロー制御なし
- シリアルでは、各センサーに0から15までのアドレスを与えられる
- 出荷時のセンサーアドレスは0
- 距離をインチ、センチ、マイクロ秒のいずれかで取得可能
シリアルインタフェースで、H8/3052Fに
接続してテストすることに。
接続は、次のようにしてあります。
テストには、H8のSCIをPersonalComputerと
超音波センサーに接続します。
テストは、PC側からSCI_1を通してコマンドを与え
超音波センサーが、SCI_0を介して応答する方式に
します。
ファームウエアの開発環境は、GDLを利用することに
して、SCIの初期化を考えます。
SCI_1
データ転送速度9600bps、1ストップビット、パリティなし
フロー制御なしに設定します。これを関数にまとめます。
void init_sci_0(TBaudRate x)
{
UWORD i;
/* SCR : Serial Control Register
7 bit TIE -> 0 Transmit Interrupt Enable(disable)
6 bit RIE -> 0 Receive Interrupt Enable(disable)
5 bit TE -> 0 Transmit Enable(disable)
4 bit RE -> 0 Receive Enable(disable)
3 bit MPIE -> 0 Multi Processor Interrupt Enable(disable)
2 bit TEIE -> 0 Transmit End Interrupt Enable(disable)
1 bit CKE1 -> 0 Clock Source (Use Internal Baud Rate Generator)
0 bit CKE0 -> 0
*/
SCI0.SCR.BYTE = 0 ;
/* SMR : Serial Mode Register
7 bit C/nA -> 0 Communication Mode(Asynchronous)
6 bit CHR -> 0 data Charactor (8 bits)
5 bit PE -> 0 Parity Enable(disable)
4 bit O/nE -> 0 Parity Mode(even)
3 bit STOP -> 1 Stop Bit(2 bit)
2 bit MP -> 0 Multi Processor(disable)
1 bit CKS1 -> 0 Clock Source ( φ )
0 bit CKS0 -> 0
*/
SCI0.SMR.BYTE = 0x08 ;
/* data transfer speed */
SCI0.BRR = x ;
/* wait 1 frame */
for (i = 0; i < 3000 ; i++) ;
/* enable Transmmit and Receive with receive interrupt */
SCI0.SCR.BYTE = 0x70 ;
}
SCI_1
データ転送速度9600bps、2ストップビット、パリティなし
フロー制御なしに設定します。これを関数にまとめます。
void init_sci_0(TBaudRate x)
{
UWORD i;
/* SCR : Serial Control Register
SCI0.SCR.BYTE = 0 ;
/* SMR : Serial Mode Register
3 bit STOP -> 1 Stop Bit(2 bit)
*/
SCI0.SMR.BYTE = 0x08 ;
/* data transfer speed */
SCI0.BRR = x ;
/* wait 1 frame */
for (i = 0; i < 3000 ; i++) ;
/* enable Transmmit and Receive with receive interrupt */
SCI0.SCR.BYTE = 0x70 ;
}
PCから操作するために、コマンドを定義して
コマンドインタプリタを作成します。
超音波センサーのコマンドを調べ、次の4種
を実装することに。
- 0x51 cm単位で距離を出力
- 0x5D 内蔵ファームウエアのVersionを出力
- 0x5E 距離を2バイトの16進数で出力
- 0x5F 最小検出距離を2バイトの16進数で出力
シリアルインタフェースで、コマンドを与える
には、センサー番号を先に与える仕様です。
センサー番号(16進数)+コマンド値(16進数)
2バイトのコマンドをSCI_0から出力する関数を
定義します。
void send_cmd(UBYTE xadr,UBYTE xcmd)
{
/* address */
rs0_putchar(xadr) ;
/* command */
rs0_putchar(xcmd) ;
}
1バイトをSCI_0から出力する関数を利用して
いるので、その関数を定義します。
void rs0_putchar(UBYTE x)
{
/* wait data transfer */
while ( SCI0.SSR.BIT.TDRE == OFF ) ;
/* put */
SCI0.TDR = x ;
SCI0.SSR.BIT.TDRE = OFF ;
}
SCI_0からの送信ができたので、受信を考えます。
超音波センサーからは、非同期で1バイトあるいは
2バイトデータが返ってきます。取りこぼさない為
には、受信割込みを使います。
また、リングバッファに受信データを格納します。
リングバッファは、32バイトを用意し、リードと
ライトポインタを使い管理します。
#define RINGMAX 32
typedef unsigned char UBYTE ;
UBYTE rdptr ;
UBYTE wtptr ;
UBYTE ring[RINGMAX] ;
受信割込みは、次のように定義すれば充分でしょう。
void int_rxi0(void)
{
UBYTE dummy ;
/* clear flag */
dummy = SCI0.SSR.BYTE ;
SCI0.SSR.BIT.RDRF = OFF ;
/* store */
*(ring+wtptr) = SCI0.RDR ;
/* update pointer */
wtptr++ ;
if ( wtptr == RINGMAX ) { wtptr = 0 ; }
}
リングバッファから、1バイトのデータを取り出す
関数も定義します。
UBYTE get_ring(void)
{
UBYTE xresult ;
/* load */
xresult = *(ring+rdptr) ;
/* update */
rdptr++ ;
if ( rdptr == RINGMAX ) { rdptr = 0 ; }
return xresult ;
}
ここまでで、SCI_0に必要な内容は作成できたので
SCI_1に関する関数を定義します。
受信割込み処理
PCからの指示を格納しておくバッファを用意します。
#define SBUFMAX 16
UBYTE sbuf[SBUFMAX] ;
UBYTE sindex ;
1文字受信するごとに、バッファに格納し
1レコード受信終了で、フラグ通知します。
void int_rxi1(void)
{
UBYTE ch,dummy ;
/* clear flag */
dummy = SCI1.SSR.BYTE ;
SCI1.SSR.BIT.RDRF = OFF ;
/* get a character */
ch = SCI1.RDR ;
/* store */
*(sbuf+sindex) = ch ;
sindex++ ;
/* check */
if ( ch == '\r' ) {
*(sbuf+sindex) = 0 ;
sindex = 0 ;
uflag = ON ;
}
}
1レコードの終了は、'\r'としています。
1文字送信
関数名はputcharを入れ、SCI_1を利用している
ことがわかるようにします。
void rs1_putchar(UBYTE x)
{
/* wait data transfer */
while ( SCI1.SSR.BIT.TDRE == OFF ) ;
/* put */
SCI1.TDR = x ;
SCI1.SSR.BIT.TDRE = OFF ;
}
文字列送信
関数名はputsを入れ、SCI_1を利用している
ことがわかるようにします。
void rs1_puts(UBYTE *x)
{
while ( *x ) {
/* send 1 charactors */
rs1_putchar(*x);
x++ ;
}
}
改行
改行はcarriage return+line feedとして、crlf
を入れ、SCI_1を利用していることがわかるよう
にします。
void rs1_crlf(void)
{
rs1_putchar('\r');
rs1_putchar('\n');
}
通信に関連する関数を作成したので、コマンドインタプリタ
を定義していきます。
- ? ヘルプ
- A 超音波センサーのアドレス変更
- V 内蔵ファームウエアのVersionを出力
- D 距離を2バイトの16進数で出力
- M 最小検出距離を2バイトの16進数で出力
- C リングバッファ関係変数初期化
- R リングバッファの内容を16進数で表示
?、C、Rはパラメータを不要とし、それ以外は
超音波センサーのアドレスを続けて入力します。
コマンドAだけは、現アドレスと希望アドレスの
2パラメータを使います。
アドレスは、'0'〜'9'と'A'〜'F'にします。
コマンドインタプリタは、レコード受信の通知で
動作するように構成します。
while ( ON ) {
/* command interpreter */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
rs1_crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* clear buffer and pointer */
if ( cmd == 'C' ) { clear_ring() ; }
/* change address */
if ( cmd == 'A' ) {
/* now address */
myadr = get_hex( *(sbuf+1) );
/* desired address */
i = get_hex( *(sbuf+2) );
/* judge */
if ( is_correct_adr(myadr) > 0 && is_correct_adr(i) > 0 ) {
/* update */
put_adr( myadr , i );
}
}
/* measure */
if ( cmd == 'D' || cmd == 'M' ) {
/* get address */
myadr = get_hex( *(sbuf+1) );
/* judge */
if ( is_correct_adr(myadr) ) {
/* send command */
send_cmd( myadr , CMD_SET_CM ); /* with cm format */
/* delay */
delay_ms(100);
tmp = CMD_DISTANCE ;
if ( cmd == 'M' ) { tmp = CMD_MINIMUM ; }
send_cmd( myadr , tmp ); /* distance */
/* delay */
delay_ms(200);
/* get 2 byte */
i = get_ring() ;
tmp = get_ring() ;
/* show */
show_decimal( i , tmp );
}
}
/* get version */
if ( cmd == 'V' ) {
/* get address */
myadr = get_hex( *(sbuf+1) );
/* judge */
if ( is_correct_adr(myadr) ) {
/* send command */
send_cmd( myadr , CMD_VERSION );
/* delay */
delay_ms(100);
/* get version */
tmp = get_ring() ;
/* separate */
i = (tmp >> 4) & MASK0F ;
tmp &= MASK0F ;
/* show */
rs1_puts("0x");
rs1_putchar( asc_hex[i] ) ;
rs1_putchar( asc_hex[tmp] ) ;
rs1_crlf();
}
}
/* show buffer */
if ( cmd == 'R' ) { show_ring(); }
}
}
PCからコマンドを与えて、超音波センサーが
反応するまでに、時間がかかるので、1ms
単位で待つ関数delay_msを用意します。
関数delay_msを実現するため、システムカウンタを
用意し、1msごとに+1していきます。
関数は、次のように定義します。
void delay_ms(UWORD x)
{
ULONG target ;
/* calculate last value */
target = timcnt + x ;
/* wait */
while ( timcnt < target ) ;
}
システムカウンタtimcntは、1msごとに発生する
コンペアマッチ割込みで、インクリメントします。
void int_imia1(void)
{
UBYTE dummy ;
/* clear flag */
dummy = ITU1.TSR.BIT.IMFA ;
ITU1.TSR.BIT.IMFA = OFF ;
/* increment */
timcnt++ ;
}
タイマー割込みは、タイマー1を利用することに。
初期化用関数を定義します。
#define ITU1_AREG 24999
#define MASKFFFF 0xffff
void init_timer1(void)
{
/* stop timer */
ITU.TSTR.BIT.STR1 = OFF ;
/* TOER : Timer Output Enable Register
7 **** -> 0
6 **** -> 0
5 EXB4 -> 0
4 EXA4 -> 0
3 EB3 -> 0
2 EB4 -> 0
1 EA4 -> 0
0 EA3 -> 0
*/
ITU.TOER.BYTE = 0 ;
/* TIOR : Timer I/O Control Register
7 **** -> 0
6 IOB2 -> 0 GRB is not output compare match register
5 IOB1 -> 0
4 IOB0 -> 0
3 **** -> 0
2 IOA2 -> 0 GRA is not output compare match register
1 IOA1 -> 0
0 IOA0 -> 0
*/
ITU1.TIOR.BYTE = 0 ;
/* TCR : Timer Control Register
7 **** -> 0
6 CCLR1 -> 0 clear TCNT if GRA = TCNT
5 CCLR0 -> 1
4 CKEG1 -> 0 rising edge
3 CKEG0 -> 0
2 TPSC2 -> 0 φ利用
1 TPSC1 -> 0
0 TPSC0 -> 0
*/
ITU1.TCR.BYTE = 0x20 ;
/* TIER : Timer Interrupt Enable Register
7 **** -> 0
6 *** -> 0
5 *** -> 0
4 *** -> 0
3 *** -> 0
2 OVIE -> 0
1 IMIEB -> 0
0 IMIEA -> 1 select compare match interrupt
*/
ITU1.TIER.BIT.IMIEA = ON ;
/* reference */
ITU1.GRA = ITU1_AREG ;
ITU1.GRB = MASKFFFF ;
/* counter */
ITU1.TCNT = 0 ;
/* start timer */
ITU.TSTR.BIT.STR1 = ON ;
}
利用するH8/3052Fは、秋月電子で販売されている
25MHzの基板を利用します。
ソースコードは、以下。
#include "3052.h"
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef unsigned long ULONG ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
/*----------------*/
/* user variables */
/*----------------*/
#define ITU1_AREG 24999
#define MASKFFFF 0xffff
#define MASKFF 0xff
#define MASK0F 0x0f
#define OFF 0
#define ON OFF+1
#define RINGMAX 32
#define SBUFMAX 16
#define CMD_SET_CM 0x51
#define CMD_VERSION 0x5D
#define CMD_DISTANCE 0x5E
#define CMD_MINIMUM 0x5F
ULONG timcnt ;
UBYTE uflag ;
/* SCI_1 buffer */
UBYTE sindex ;
UBYTE sbuf[SBUFMAX];
UBYTE cmd ;
UBYTE asc_hex[SBUFMAX] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} ;
/* ring buffer parameters */
UBYTE rdptr ;
UBYTE wtptr ;
UBYTE ring[RINGMAX] ;
/*-------------------------*/
/* user functions protoype */
/*-------------------------*/
void init_sci_0(TBaudRate x);
void init_sci_1(TBaudRate x);
void rs0_putchar(UBYTE x);
void rs1_putchar(UBYTE x);
void rs1_crlf(void);
void rs1_puts(UBYTE *x);
void show_help(void);
void user_initialize(void);
void init_timer1(void);
UBYTE get_hex(UBYTE x);
void delay_ms(UWORD x);
UBYTE get_ring(void);
void show_ring(void);
void clear_ring(void);
void send_cmd(UBYTE xadr,UBYTE xcmd);
void put_adr(UBYTE x,UBYTE y);
void show_decimal(UBYTE xh,UBYTE xl);
UBYTE is_correct_adr(UBYTE x) ;
/*------*/
/* main */
/*------*/
int main(void)
{
UBYTE tmp ;
UBYTE i ;
UBYTE myadr ;
/* disable interrupt */
DI ;
/* initialize */
user_initialize();
/* enable interrupt */
EI ;
/* opening message */
rs1_puts("Hello");
rs1_crlf();
/* loop */
while ( ON ) {
/* command interpreter */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
rs1_crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* clear buffer and pointer */
if ( cmd == 'C' ) { clear_ring() ; }
/* change address */
if ( cmd == 'A' ) {
/* now address */
myadr = get_hex( *(sbuf+1) );
/* desired address */
i = get_hex( *(sbuf+2) );
/* judge */
if ( is_correct_adr(myadr) > 0 && is_correct_adr(i) > 0 ) {
/* update */
put_adr( myadr , i );
}
}
/* measure */
if ( cmd == 'D' || cmd == 'M' ) {
/* get address */
myadr = get_hex( *(sbuf+1) );
/* judge */
if ( is_correct_adr(myadr) ) {
/* send command */
send_cmd( myadr , CMD_SET_CM ); /* with cm format */
/* delay */
delay_ms(100);
tmp = CMD_DISTANCE ;
if ( cmd == 'M' ) { tmp = CMD_MINIMUM ; }
send_cmd( myadr , tmp ); /* distance */
/* delay */
delay_ms(200);
/* get 2 byte */
i = get_ring() ;
tmp = get_ring() ;
/* show */
show_decimal( i , tmp );
}
}
/* get version */
if ( cmd == 'V' ) {
/* get address */
myadr = get_hex( *(sbuf+1) );
/* judge */
if ( is_correct_adr(myadr) ) {
/* send command */
send_cmd( myadr , CMD_VERSION );
/* delay */
delay_ms(100);
/* get version */
tmp = get_ring() ;
/* separate */
i = (tmp >> 4) & MASK0F ;
tmp &= MASK0F ;
/* show */
rs1_puts("0x");
rs1_putchar( asc_hex[i] ) ;
rs1_putchar( asc_hex[tmp] ) ;
rs1_crlf();
}
}
/* show buffer */
if ( cmd == 'R' ) { show_ring(); }
}
}
return 0 ;
}
/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
/* initialize */
init_timer1();
/* clear flags */
uflag = OFF ;
/* clear SCI_1 buffer */
*(sbuf+0) = 0 ;
sindex = 0 ;
/* initialize */
timcnt = 0 ;
clear_ring() ;
/* initialize SCI */
init_sci_0(br9600);
init_sci_1(br9600);
}
void init_timer1(void)
{
/* stop timer */
ITU.TSTR.BIT.STR1 = OFF ;
/* TOER : Timer Output Enable Register
7 **** -> 0
6 **** -> 0
5 EXB4 -> 0
4 EXA4 -> 0
3 EB3 -> 0
2 EB4 -> 0
1 EA4 -> 0
0 EA3 -> 0
*/
ITU.TOER.BYTE = 0 ;
/* TIOR : Timer I/O Control Register
7 **** -> 0
6 IOB2 -> 0 GRB is not output compare match register
5 IOB1 -> 0
4 IOB0 -> 0
3 **** -> 0
2 IOA2 -> 0 GRA is not output compare match register
1 IOA1 -> 0
0 IOA0 -> 0
*/
ITU1.TIOR.BYTE = 0 ;
/* TCR : Timer Control Register
7 **** -> 0
6 CCLR1 -> 0 clear TCNT if GRA = TCNT
5 CCLR0 -> 1
4 CKEG1 -> 0 rising edge
3 CKEG0 -> 0
2 TPSC2 -> 0 φ利用
1 TPSC1 -> 0
0 TPSC0 -> 0
*/
ITU1.TCR.BYTE = 0x20 ;
/* TIER : Timer Interrupt Enable Register
7 **** -> 0
6 *** -> 0
5 *** -> 0
4 *** -> 0
3 *** -> 0
2 OVIE -> 0
1 IMIEB -> 0
0 IMIEA -> 1 select compare match interrupt
*/
ITU1.TIER.BIT.IMIEA = ON ;
/* reference */
ITU1.GRA = ITU1_AREG ;
ITU1.GRB = MASKFFFF ;
/* counter */
ITU1.TCNT = 0 ;
/* start timer */
ITU.TSTR.BIT.STR1 = ON ;
}
/*+++++++++++++++++++++++++++++++++++++*/
/* ITU1 interrupt with compare match A */
/* 1ms interval */
/*+++++++++++++++++++++++++++++++++++++*/
void int_imia1(void)
{
UBYTE dummy ;
/* clear flag */
dummy = ITU1.TSR.BIT.IMFA ;
ITU1.TSR.BIT.IMFA = OFF ;
/* increment */
timcnt++ ;
}
/*+++++++++++++++++++++++++*/
/* SCI_0 receive interrupt */
/*+++++++++++++++++++++++++*/
void init_sci_0(TBaudRate x)
{
UWORD i;
/* SCR : Serial Control Register
7 bit TIE -> 0 Transmit Interrupt Enable(disable)
6 bit RIE -> 0 Receive Interrupt Enable(disable)
5 bit TE -> 0 Transmit Enable(disable)
4 bit RE -> 0 Receive Enable(disable)
3 bit MPIE -> 0 Multi Processor Interrupt Enable(disable)
2 bit TEIE -> 0 Transmit End Interrupt Enable(disable)
1 bit CKE1 -> 0 Clock Source (Use Internal Baud Rate Generator)
0 bit CKE0 -> 0
*/
SCI0.SCR.BYTE = 0 ;
/* SMR : Serial Mode Register
7 bit C/nA -> 0 Communication Mode(Asynchronous)
6 bit CHR -> 0 data Charactor (8 bits)
5 bit PE -> 0 Parity Enable(disable)
4 bit O/nE -> 0 Parity Mode(even)
3 bit STOP -> 1 Stop Bit(2 bit)
2 bit MP -> 0 Multi Processor(disable)
1 bit CKS1 -> 0 Clock Source ( φ )
0 bit CKS0 -> 0
*/
SCI0.SMR.BYTE = 0x08 ;
/* data transfer speed */
SCI0.BRR = x ;
/* wait 1 frame */
for (i = 0; i < 3000 ; i++) ;
/* enable Transmmit and Receive with receive interrupt */
SCI0.SCR.BYTE = 0x70 ;
}
/*+++++++++++++++++++++++++*/
/* SCI_0 receive interrupt */
/*+++++++++++++++++++++++++*/
void int_rxi0(void)
{
UBYTE dummy ;
/* clear flag */
dummy = SCI0.SSR.BYTE ;
SCI0.SSR.BIT.RDRF = OFF ;
/* store */
*(ring+wtptr) = SCI0.RDR ;
/* update pointer */
wtptr++ ;
if ( wtptr == RINGMAX ) { wtptr = 0 ; }
}
/*+++++++++++++++*/
/* SCI_0 putchar */
/*+++++++++++++++*/
void rs0_putchar(UBYTE x)
{
/* wait data transfer */
while ( SCI0.SSR.BIT.TDRE == OFF ) ;
/* put */
SCI0.TDR = x ;
SCI0.SSR.BIT.TDRE = OFF ;
}
/*+++++++++++++++++++++++++*/
/* SCI_1 receive interrupt */
/*+++++++++++++++++++++++++*/
void init_sci_1(TBaudRate x)
{
UWORD i;
/* SCR : Serial Control Register
7 bit TIE -> 0 Transmit Interrupt Enable(disable)
6 bit RIE -> 0 Receive Interrupt Enable(disable)
5 bit TE -> 0 Transmit Enable(disable)
4 bit RE -> 0 Receive Enable(disable)
3 bit MPIE -> 0 Multi Processor Interrupt Enable(disable)
2 bit TEIE -> 0 Transmit End Interrupt Enable(disable)
1 bit CKE1 -> 0 Clock Source (Use Internal Baud Rate Generator)
0 bit CKE0 -> 0
*/
SCI1.SCR.BYTE = 0 ;
/* SMR : Serial Mode Register
7 bit C/nA -> 0 Communication Mode(Asynchronous)
6 bit CHR -> 0 data Charactor (8 bits)
5 bit PE -> 0 Parity Enable(disable)
4 bit O/nE -> 0 Parity Mode(even)
3 bit STOP -> 0 Stop Bit(1 bit)
2 bit MP -> 0 Multi Processor(disable)
1 bit CKS1 -> 0 Clock Source ( φ )
0 bit CKS0 -> 0
*/
SCI1.SMR.BYTE = 0 ;
/* data transfer speed */
SCI1.BRR = x ;
/* wait 1 frame */
for (i = 0; i < 3000 ; i++) ;
/* enable Transmmit and Receive with receive interrupt */
SCI1.SCR.BYTE = 0x70 ;
}
/*+++++++++++++++++++++++++*/
/* SCI_1 receive interrupt */
/*+++++++++++++++++++++++++*/
void int_rxi1(void)
{
UBYTE ch,dummy ;
/* clear flag */
dummy = SCI1.SSR.BYTE ;
SCI1.SSR.BIT.RDRF = OFF ;
/* get a character */
ch = SCI1.RDR ;
/* store */
*(sbuf+sindex) = ch ;
sindex++ ;
/* check */
if ( ch == '\r' ) {
*(sbuf+sindex) = 0 ;
sindex = 0 ;
uflag = ON ;
}
}
/*+++++++++++++++*/
/* SCI_1 putchar */
/*+++++++++++++++*/
void rs1_putchar(UBYTE x)
{
/* wait data transfer */
while ( SCI1.SSR.BIT.TDRE == OFF ) ;
/* put */
SCI1.TDR = x ;
SCI1.SSR.BIT.TDRE = OFF ;
}
/*++++++++++++*/
/* SCI_1 puts */
/*++++++++++++*/
void rs1_puts(UBYTE *x)
{
while ( *x ) {
/* send 1 charactors */
rs1_putchar(*x);
x++ ;
}
}
/*++++++++++++*/
/* SCI_1 crlf */
/*++++++++++++*/
void rs1_crlf(void)
{
rs1_putchar('\r');
rs1_putchar('\n');
}
/*++++++++++++++++++++*/
/* SCI_1 command help */
/*++++++++++++++++++++*/
void show_help(void)
{
rs1_puts("? help") ; rs1_crlf();
rs1_puts("A change address") ; rs1_crlf();
rs1_puts(" 0->4 => A04{cr}") ; rs1_crlf();
rs1_puts("D distance") ; rs1_crlf();
rs1_puts(" address 2 => D2{cr}") ; rs1_crlf();
rs1_puts("M minimum distance") ; rs1_crlf();
rs1_puts(" address 4 => M4{cr}") ; rs1_crlf();
rs1_puts("V show version") ; rs1_crlf();
rs1_puts(" address 15 => VF{cr}") ; rs1_crlf();
rs1_puts("R show ring buffer") ; rs1_crlf();
rs1_puts("C clear ring buffer") ; rs1_crlf();
}
UBYTE get_hex(UBYTE x)
{
UBYTE result ;
/* default */
result = 0 ;
/* convert */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
void delay_ms(UWORD x)
{
ULONG target ;
/* calculate last value */
target = timcnt + x ;
/* wait */
while ( timcnt < target ) ;
}
/*
load data from ring buffer
*/
UBYTE get_ring(void)
{
UBYTE xresult ;
/* load */
xresult = *(ring+rdptr) ;
/* update */
rdptr++ ;
if ( rdptr == RINGMAX ) { rdptr = 0 ; }
return xresult ;
}
void show_ring(void)
{
UBYTE i ;
UBYTE tmp ;
for ( i = 0 ; i < RINGMAX ; i++ ) {
/* get 1 byte */
tmp = *(ring+i) ;
/* show */
rs1_puts("0x");
rs1_putchar( asc_hex[(tmp >> 4) & MASK0F] ) ;
rs1_putchar( asc_hex[tmp & MASK0F] ) ;
rs1_putchar(' ');
/* new line */
if ( (i & MASK0F) == MASK0F ) { rs1_crlf() ; }
}
}
void clear_ring(void)
{
UBYTE i ;
for ( i = 0 ; i < RINGMAX ; i++ ) {
*(ring+i) = 0 ;
}
wtptr = 0 ;
rdptr = 0 ;
}
void send_cmd(UBYTE xadr,UBYTE xcmd)
{
/* address */
rs0_putchar(xadr) ;
/* command */
rs0_putchar(xcmd) ;
}
void put_adr(UBYTE x,UBYTE y)
{
/* judge */
if ( x > 15 ) return ;
if ( y > 15 ) return ;
/* 1st command */
send_cmd(x,0xA0) ;
/* 2nd command */
send_cmd(x,0xAA) ;
/* 3rd command */
send_cmd(x,0xA5) ;
/* set address */
send_cmd(x,y) ;
}
void show_decimal(UBYTE xh,UBYTE xl)
{
UBYTE dix[5] ;
UWORD result ;
UWORD tmp ;
UBYTE loop ;
/* concatenate */
result = xh ;
result <<= 8 ;
result |= xl ;
tmp = result ;
/* separate */
*(dix+0) = result / 10000 ; result %= 10000 ;
*(dix+1) = result / 1000 ; result %= 1000 ;
*(dix+2) = result / 100 ; result %= 100 ;
*(dix+3) = result / 10 ;
*(dix+4) = result % 10 ;
/* conversion and show */
for ( loop = 0 ; loop < 5 ; loop++ ) {
*(dix+loop) = asc_hex[ *(dix+loop) ] ;
}
/* adjust */
if ( tmp < 100 ) {
*(dix+0) = ' ' ;
*(dix+1) = ' ' ;
*(dix+2) = ' ' ;
} else {
if ( tmp < 1000 ) {
*(dix+0) = ' ' ;
*(dix+1) = ' ' ;
} else {
if ( tmp < 10000 ) {
*(dix+0) = ' ' ;
}
}
}
/* show */
for ( loop = 0 ; loop < 5 ; loop++ ) {
rs1_putchar( *(dix+loop) ) ;
}
rs1_puts("cm");
/* new line */
rs1_crlf();
}
UBYTE is_correct_adr(UBYTE x)
{
if ( x < 16 ) return 1 ;
rs1_puts("illeagal address") ;
rs1_crlf();
return 0 ;
}
ハイパーターミナルを利用して、動作確認すると
次のようになりました。
?でヘルプの内容を表示してから、Version確認(Vコマンド)、
距離計測(Dコマンド)、キャリブレーション(Mコマンド)と
コマンドを与えてみました。
コマンド1文字に続いて、超音波センサーのアドレスを
入力します。
アドレス+コマンド+{enter}で、1レコード分をH8/3052Fに
転送します。
このセンサーは、往復距離を計測して
物体までの距離を出力します。
距離は、材質と距離を変えて計測しました。
すべての材質で、ほぼ同じ距離になりましたが
板に布をかけ測定すると、ありえない値を出力
することがありました。
実際のスタートゲートは、布はかけられていない
ので、PDSに置き換えられるセンサーになります。
目次
前
次