目次

LED点滅スケッチ

 Arduino基板には、D13にLEDが接続されています。

 D13に接続されているLEDの点滅周期を変更し
 タイマー割込みが正しく動いていることを
 確認します。



 タイマー割込みにはMsTimer2を利用し、200msごとに
 イベントフラグをセットします。

void  update_trigger(void)
{
  eflag = ON ;
}

 loopの中では、イベントフラグを受取り、カウンタを
 インクリメントして、カウンタ値に応じてLEDの点灯
 消灯を確定します。

  if ( eflag == ON ) {
    /* clear flag */
    eflag = OFF ;
    /* update */
    xcnt++ ;
    xmode = mode ;
    /* generate code */
    m0 = xcnt & ON ;
    m1 = (xcnt >> 1) & ON ;
    m2 = (xcnt >> 2) & ON ;
    /* judge */
    i = m0 ;
    switch ( xmode ) {
      case  1 : i = m1 ; break ;
      case  2 : i = m2 ; break ;
      default : i = m0 ; break ;
    }
    /* impress */
    send_led( i ) ;
  }

 変数modeを利用し、どのモードになっているかで
 カウンタのビット0、1、2の値を取出し、その
 値をLEDに出力します。

 モード値は、シリアル通信で変更できるとして
 LEDの点灯、消灯を決めるときに、参照します。

 シリアル通信でモード値を設定し、イベントフラグを
 受取ったときに更新して、カウンタのビット値を取り
 出します。

 LEDの状態は、専用関数を定義して処理します。

void  send_led(byte x)
{
  if ( x ) { PORTB |=  (1 << LED_BIT); }
  else     { PORTB &= ~(1 << LED_BIT); }
}

 digitalWriteでは、更新時間がかかるので
 ポート値を直接更新します。

 通信関係で1文字出力、文字列出力に関係する
 関数を定義します。

void  rs_putchar(char x)
{
  Serial.write(x);
}

void  rs_puts(char *x)
{
  while ( *x ) {
    rs_putchar(*x);
    x++ ;
  }
}

void  crlf(void)
{
  rs_putchar('\r');
  rs_putchar('\n');
}

 文字列出力関数を作成すれば、コマンドインタプリタで
 使う関数を定義できます。

void  show_help(void)
{
  rs_puts("? help");      crlf();
  rs_puts("M set mode "); crlf();
}

 コマンドインタプリタは、loopの中に以下のコードを
 展開して実現します。

  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* new line */
    crlf();
    /* get command */
    cmd = *(sbuf+0) ;
    /* judge */
    if ( cmd == '?' ) { show_help(); }
    /* execute */
    if ( cmd == 'M' ) {
      mode = 0 ;
      if ( *(sbuf+1) == '1' ) { mode = 1 ; }
      if ( *(sbuf+1) == '2' ) { mode = 2 ; }
    }
  }

 コマンドを受信割込みで取り込めばよいので
 イベントハンドラを考えます。

void serialEvent()
{
  char ch ;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

 コマンドが入ったならば、イベントフラグで通知します。

 TeraTermでArduinoと通信すると、次のようになります。

 ヘルプコマンド



 モード設定



 スケッチは以下。

#include <MsTimer2.h>

#define OFF 0
#define ON  OFF+1

#define LED_BIT 5

/* function prototype */
void rs_putchar(char x);
void rs_puts(char *x);
void crlf(void);
void show_help(void);
void send_led(byte x);

/* global variables */
byte xcnt ;
byte eflag ;
byte uflag ;
byte sindex ;
byte sbuf[4] ;
byte cmd ;
byte mode ;

void setup()
{
  /* initialize serial port */
  Serial.begin(9600);
  /* set initial state */
  PORTB = 0x00 ;
  PORTC = 0x00 ;
  PORTD = 0x01 ;
  /* set pin directions */
  DDRB = 0xff ;
  DDRC = 0xfe ;
  DDRD = 0xfe ;
  /* clear flags */
  eflag = OFF ;
  uflag = OFF ;
  /* command interpreter buffer */
  sindex = 0 ;
  /* initialize */
  xcnt = 0 ;
  mode = 0 ;
  /* 200ms period */
  MsTimer2::set(200,update_trigger);
  /* enable */ 
  MsTimer2::start();
}

void loop()
{
  byte i ;
  byte m0 ;
  byte m1 ;
  byte m2 ;
  byte xmode ;
  /* LED handling */
  if ( eflag == ON ) {
    /* clear flag */
    eflag = OFF ;
    /* update */
    xcnt++ ;
    xmode = mode ;
    /* generate code */
    m0 = xcnt & ON ;
    m1 = (xcnt >> 1) & ON ;
    m2 = (xcnt >> 2) & ON ;
    /* judge */
    i = m0 ;
    switch ( xmode ) {
      case  1 : i = m1 ; break ;
      case  2 : i = m2 ; break ;
      default : i = m0 ; break ;
    }
    /* impress */
    send_led( i ) ;
  }
  /* serial handling */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* new line */
    crlf();
    /* get command */
    cmd = *(sbuf+0) ;
    /* judge */
    if ( cmd == '?' ) { show_help(); }
    /* execute */
    if ( cmd == 'M' ) {
      mode = 0 ;
      if ( *(sbuf+1) == '1' ) { mode = 1 ; }
      if ( *(sbuf+1) == '2' ) { mode = 2 ; }
    }
  }
}

void  rs_putchar(char x)
{
  Serial.write(x);
}

void  rs_puts(char *x)
{
  while ( *x ) {
    rs_putchar(*x);
    x++ ;
  }
}

void  crlf(void)
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void  show_help(void)
{
  rs_puts("? help");      crlf();
  rs_puts("M set mode "); crlf();
}

void  send_led(byte x)
{
  if ( x ) { PORTB |=  (1 << LED_BIT); }
  else     { PORTB &= ~(1 << LED_BIT); }
}

void  update_trigger(void)
{
  eflag = ON ;
}

/* receive interrupt */
void serialEvent()
{
  char ch ;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}


目次

inserted by FC2 system