目次

スタートゲートセンサー

 SHARPのPDSは、スタートゲートセンサーとして
 よく利用されているようですが、人と同じもの
 は使いたくないと思い、秋月電子で販売されて
 いる、超音波センサーが使えるかテストです。



 5ピンのLタイプピンを半田付けし、5ピンケーブル
 で、相手のマイクロコンピュータに接続します。



 LEDがある側に、+5V。その下にRxD、TxD、
 MODE、GNDとピンが配置されています。



 秋月電子のサイトから、リンクをたどり、次の
 仕様がわかりました。

 シリアルインタフェースで、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種
 を実装することに。

 シリアルインタフェースで、コマンドを与える
 には、センサー番号を先に与える仕様です。

 センサー番号(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');
}

 通信に関連する関数を作成したので、コマンドインタプリタ
 を定義していきます。

 ?、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に置き換えられるセンサーになります。


目次

inserted by FC2 system