目次

UART処理

 UART動作の確認に、次のような
 システムを考えました。



 送受信処理が出来たのかを、LEDの点灯による
 モニタ信号で確認します。



 大まかな仕様を、次のように考えました。

 通信が関係するので、プロトコルを決めます。

 コマンドは、?、A、Iの3種。

 システム概要を決めたので、詳細な仕様を
 記述していきます。

 システムクロック周波数

  システムクロックは、41.78MHzとする。

  システムクロックを決めたので、ボーレートを
  決めるレジスタの設定値は、以下となる。
     COMDIV0 = 0x44 ;
     COMDIV1 = 0x00 ;

  タイマー割込みによるLED点滅には、タイマー0
  を利用。周期割込みを使えるように初期化。
  41.78MHzを256分周し、更に10Hz程度になるように
  設定。また、周期割込みのパラメータ設定。
  まとめると、次のコードに。
      T0LD  = 16320 ;
      T0CON = 0xc8 ;

 割込み

  タイマー0の周期割込み、UARTの受信割込みを扱う
  ため、割込みイネーブルレジスタIRQENにパラメータ
  を設定します。
    IRQEN = RTOS_TIMER_BIT | UART_BIT ;

  割込みハンドラでは、割込みが発生したときに
  フラグをセットして通知します。。
    volatile UBYTE ch ;
    /* judge UART receive interruption */
    if ( (IRQSTA & UART_BIT) == UART_BIT ) {
      /* judge */
      if ( COMSTA0 & 1 ) {
        /* clear flag */
        ch = COMRX ;
        *(sbuf+sindex) = ch ;
        sindex++ ;      
        if ( ch == '\r' ) {
          sindex = 0 ;
          uflag  = ON ;
        }
      }
    }
    /* judge timer0 interruption (10us) */
    if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) {
      /* clear timer1 interrupt flag */
      T0CLRI = 0xff ;
      /* increment */
      tflag = ON ;
    }

  受信割込みでは、バッファに文字を入れます。
  1レコード分が溜まった時点で、フラグをセットします。
  タイマー0周期割込みでは、単にフラグをセットします。

 UART動作

  仕様に相当するパラメータを設定します。
   データ長8ビット、ストップビット1、パリティなし、
   フロー制御なし。
     COMCON0 = 0x03 ;

  受信割込みを使うとして、レジスタCOMIEN0の相当
  ビットをセットします。
     COMIEN0 = 0x01 ;

 動作表示

  ADuC7026基板上のLED点滅で、動作を表示する。
  タイマー0の周期割込で、LEDを点滅するので
  割込みハンドラから通知されるトリガーフラグ
  を使い、フラグ通知されるたびに、P4.7出力値
  を反転します。



 システム動作変更

  フラットケーブルで接続したLEDの点滅制御。
  タイマー0の周期割込で、P3.0に接続のLEDを点滅。
  ただし、PCから設定したフラグで、消灯と点滅を
  切り換えます。



 コマンドインタプリタ

  割込みハンドラからの通知フラグを
  とらえて、バッファからコマンドと
  パラメータを引き出します。



  コマンドは、バッファ中の最初の文字で
  判断してから、該当する関数を呼出して
  対応します。

 GPIO操作

  GP1には、UARTの通信に利用するので、UARTを
  選択して、GP1.0を入力、GP1.1を出力に指定。
     /* use UART */
     GP1CON = 0x00000011 ;
     /* input output */
     GP1DAT = 0xFE000000 ;

  GP3、GP4を出力で使い、出力値を確定しておきます。
     GP3DAT = 0xffff0000 ;
     GP4DAT = 0xff000000 ;

 UART送信

  COMTXに1文字を設定するには、COMSTA0の
  該当ビットを見て、空きがあることを判断
  しています。
    /* ? transmmit buffer empty */
    while( (COMSTA0 & 0x40) == 0 ) ;
    /* set value */
    COMTX = x ;

 まとめると、以下。

#include <ADuC7026.h>

#define OFF 0
#define ON  OFF+1

/* data definitions */
typedef unsigned char  UBYTE ;
typedef   signed char  SBYTE ;
typedef unsigned short UWORD ;
typedef   signed short SWORD ;
typedef unsigned long  ULONG ;
typedef   signed long  SLONG ;

void  IRQ_Handler(void) __irq;
void  init_usr(void);

#define MASKFF 0xFF
#define MASK0F 0x0F
#define MASK80 0x80
#define MASK40 0x40
#define MASK20 0x20
#define MASK10 0x10
#define MASK08 0x08
#define MASK04 0x04
#define MASK02 0x02
#define MASK01 0x01

#define MASKF0 0xF0

UBYTE timcnt ;

void  rs_putchar(UBYTE x);
void  crlf(void);
void  rs_puts(UBYTE *x);
void  show_help(void);

/* global variables */
volatile UBYTE uflag ;
volatile UBYTE tflag ;
volatile UBYTE gflag ;
volatile UBYTE sbuf[8] ;
volatile UBYTE sindex ;
volatile UBYTE cmd ;

int main(void)
{
  /* initialize user */
  init_usr();
  /* show message */
  rs_puts("Hello , World\n");
  /* endless loop */
  while(ON)
  {
    /* command interrpreter */
    if ( uflag == ON ) {
      /* clear flag */
      uflag = OFF ;
      /* judge */
      cmd = *(sbuf+0) ;
      /* help */
      if ( cmd == '?' ) { show_help(); }
      /* active */
      if ( cmd == 'A' ) {
        gflag = ON ;
        rs_puts("Enable\n"); 
      }
      /* inactive */
      if ( cmd == 'I' ) {
        gflag = OFF ; 
        rs_puts("Disable\n");
      }
    }
    /* debug */
    if ( tflag == ON ) {
      tflag = OFF ;
      GP4DAT ^= (1 << 23) ;
      timcnt++ ;
      if ( timcnt == 5 ) {
        timcnt = 0 ;
        /* judge */
        if ( gflag == OFF ) {
          GP3DAT |= (1 << 16) ;
        }  else {
          GP3DAT ^= (1 << 16) ;
        }
      }
    }
  }
  /* dummy return */
  return (0);
}

void IRQ_Handler(void) __irq
{
  volatile UBYTE ch ;
  /* judge UART receive interruption */
  if ( (IRQSTA & UART_BIT) == UART_BIT ) {
    /* judge */
    if ( COMSTA0 & 1 ) {
      /* clear flag */
      ch = COMRX ;
      *(sbuf+sindex) = ch ;
      sindex++ ;      
      if ( ch == '\r' ) {
        sindex = 0 ;
        uflag  = ON ;
      }
    }
  }
  /* judge timer0 interruption (10us) */
  if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) {
    /* clear timer1 interrupt flag */
    T0CLRI = 0xff ;
    /* increment */
    tflag = ON ;
  }
}

void init_usr(void)
{
  /* select clock 41.78MHz 
       initialized in start up routine
  */
  PLLKEY1 = 0xaa ;
  PLLCON  = 0x01 ;
  PLLKEY2 = 0x55 ;
  /* power control
       initialized in start up routine 
  */
  /* clear flag */
  uflag = OFF ;
  tflag = OFF ;
  gflag = ON  ; 
  /* clear counter */
  timcnt = 0 ;
  sindex = 0 ;
  /* initialize UART */
  {
    /* set baud rate 19200 bps CD = 0 DL = 0x11 */
    COMCON0 = 0x80 ; /* select COMDIV1 and COMDIV0 */
    COMDIV0 = 0x44 ;
    COMDIV1 = 0x00 ;
    /* set conditions */
    COMCON0 = 0x03 ; /* select COMRX and COMTX , 8bit data , 1 stop bit , no parity */
    /* enable interrupt */
    COMIEN0 = 0x01 ; /* ERBFI */
  }
  /* P1 */
  {
    /* use UART */
    GP1CON = 0x00000011 ;
    /* */
    GP1DAT = 0xFE000000 ;
  }
  /* P3 */
  {
    GP3DAT = 0xffff0000 ;
  }
  /* P4 */
  {
    GP4DAT = 0xff000000 ;
  }
  /* initialize timer 0 */
  {
    T0LD  = 16320 ; /* (41.78MHz / 256) / 16320 <10Hz> */
    T0CON = 0xc8 ; /* enable , cyclic , 1/256 */ 
  }
  /* enable timer 0 interrupt and UART interrupt */
  IRQEN = RTOS_TIMER_BIT | UART_BIT ;
}

/* UART putchar */
void  rs_putchar(UBYTE x)
{
  /* turn on LED */
  GP3DAT ^= ~(1 << 23) ;
  /* ? transmmit buffer empty */
  while( (COMSTA0 & 0x40) == 0 ) ;
  /* set value */
  COMTX = x ;
  /* turn off LED */
  GP3DAT |= (1 << 23) ;
}

/* carriage return and line feed */
void  crlf(void)
{
  rs_putchar('\r');
  rs_putchar('\n');
}

/* UART puts */
void  rs_puts(UBYTE *x)
{
  while ( *x != '\0' ) {
    rs_putchar( *x ) ;
    x++ ;
  }
}

/* show help */
void  show_help(void)
{
  rs_puts("? help\n");
  rs_puts("A active\n");
  rs_puts("I inactive\n");
}


目次

inserted by FC2 system