ochalog

RubyとMediaWikiとIRCが好き。

2015-06-10 の日記

今日は午後から、マイコン(授業で使っている AKI-H8/3069F ボード)に RS-232C 接続のバーコードリーダー経由で情報を取り込む実験を行った。取り込んだ情報は最終的にモデルに流し込み、LCD に表示することとなる。インターフェース技術の授業で習ったとはいえ、実際に回路を組むのは初めてなので分からないことばかりだった。

# 機材を取りに校内を行ったり来たりしていたときになおやさん(@naoya_24)と出会った。校長先生も一緒だったけれど、どんなご用事だったのだろう。

最終目的がバーコードリーダーを使うことだとしても、それ以前にシリアル通信で情報を取り込めなければ話にならないので、まずはそこから。授業で、TeraTerm を起動しキーボードで打った 1 文字を読み込む実習は行ったが、文字を貯め込むのはやったことがなかった。ただループで回すと同じ文字が大量に入力されることになったので、同じ文字が打たれている間は無視するようにしなければならない。大まかな流れは以下の形。

/*
 * シリアル通信で文字を取り込む
 */

#include "reg3067.h"

// シリアル通信関連のビット
#define SSR_RDR_FULL  0x40

// SCI1 を使って 1 文字受信する
unsigned char SCI1_getchar(void);

int main(void) {
  unsigned char ch;             // 読み込んだ文字
  unsigned char last_ch = '\0'; // 最後に読み込んだ文字

  // シリアル通信の設定
  SMR1 = 0x00;
  BRR1 = 10;   // 20 MHz, 57600 bps
  SCR1 = 0x30; // RE on, TE on

  while (1) {
    ch = SCI1_getchar();

    if (ch != last_ch) {
      // 同じ文字が入力された際の初回のみ

      // 文字を貯め込んで LCD 等に表示する
    }

    last_ch = ch;
  }

  return 0;
}

unsigned char SCI1_getchar(void) {
  // SCI1 受信:キー入力待ち
  SSR1 = 0x00;
  while (!(SSR1 & SSR_RDR_FULL));
  return RDR1; // 読み出し
}

バーコードは形式によって桁数が異なるが、今回は 8 桁程度あれば大丈夫そうなので、簡単な 8 桁分のリングバッファに貯めることにした。メモリを動的に確保しなくても使える。

/*
 * 8 文字分のリングバッファ
 */

// 8 文字分のリングバッファの構造体
typedef struct ring_buffer8 {
  unsigned int length;        // 貯めこまれている文字列の長さ
  unsigned int current_index; // 現在の位置
  char chars[9]; // printf デバッグをしやすいように 1 つ大きくした
} ring_buffer8_t;

// リングバッファを初期化する
void ring_buffer8_init(ring_buffer8_t* buffer) {
  unsigned int i;

  buffer->length = 0;
  buffer->current_index = 0;

  for (i = 0; i < 9; ++i) {
    buffer->chars[i] = '\0';
  }
}

// リングバッファに 1 文字追加する
void ring_buffer8_push(ring_buffer8_t* buffer, unsigned char ch) {
  buffer->chars[buffer->current_index] = ch;

  if (buffer->length < 8) {
    ++buffer->length;
  }

  buffer->current_index = (buffer->current_index + 1) % 8;
}

// リングバッファの内容を文字列として取り出す
void ring_buffer8_to_string(ring_buffer8_t* buffer, char* dest) {
  unsigned int i;

  if (length < 8) {
    for (i = 0; i < buffer->length; ++i) {
      dest[i] = buffer->chars[i];
    }

  } else {
    unsigned int j;

    // 折り返し前:現在の位置から最後まで
    for (i = 0, j = buffer->current_index; j < 8; ++i, ++j) {
      dest[i] = buffer->chars[j];
    }

    // 折り返し後:最初から現在の位置の手前まで
    for (j = 0; j < buffer->current_index; ++i, ++j) {
      dest[i] = buffer->chars[j];
    }
  }

  dest[buffer->length] = '\0';
}

ここまでやって TeraTerm 上でキーボードを打つことで情報を入力できるようになったが、今日はバーコードリーダーへの移行は完了しなかった。TeraTerm では通信設定さえ合わせれば、きちんとバーコードを読み取って数字が表示された。オシロスコープで見ると、バーコードリーダーで読み取った情報は RxD 端子(D-Sub 9 ピンコネクタ 2 番)から流れてくるようだった。マニュアルを見ると JP1 と SCI0 がつながっていて、また電圧レベル変換 IC の ADM3202AN にも接続されているので、コネクタと JP1 の対応する端子同士を線材+はんだ付けで接続すれば良さそう。次回はそんな感じで進めたい。