[トップページへ戻る]

AVR-CDCにLCD/EEPROM操作機能を組み込む

2011年5月
AVR-CDCを活用しています。PCに接続した自作機器を簡単なソフトで自由にコントロールできるのは魅力的です。AVR-CDCをより便利に使うため、機能を拡張してみました。

関連リンク
AVR-CDC開発サイト Recursion Co., Ltd.(サイト内 AVR-CDCのページ


AVR-CDCの機能を拡張する
LCDモジュール SC162シリーズ」の記事ではAVR-CDCを使い、PCからLCDモジュールを制御しました。このときLCDの内蔵コマンドを実行するシーケンスは全てPCから送信しました。ビット操作をする度に通信するので、1文字表示するだけでも時間がかかりました。LCDの反応は全体的にもっさりしていました。

決まった手順の処理内容であれば、あらかじめAVR-CDC内に関数を持っておき、ネイティブで(AVR内部で)処理すれば高速に実行できます。PCからは実行指示を出すだけです。今回はそのような改造をしてみました。

AVR-CDCのATmega48版は3.6KBです。ATmega88[8KB]に書き込んで利用するとき、フラッシュメモリは約4KB余ります。余った容量はPC側から活用できるわけではなく、まるまる空きっぱなしです。この分を有効に活用する意味でも、AVR-CDCの拡張(内部に関数を作り込んでおく)は有意義ではないでしょうか。

ATmega48版のAVR-CDCを改造します。改造後のファームのサイズは5.5KBになります。
ATmega48[4KB]ではフラッシュ容量が足りなくなります。改造後のファームはATmega88/168が書き込み対象です。
ATtiny4x版の改造は試していませんが、同様に行えるはずなので記事を参考にしてください。フラッシュメモリの容量の関係からATtiny85/861が対象になると思います。
もともと容量いっぱいで、機能を削っているほどのATtiny2313版は改造の対象外です。

【改造にあたっての注意】
AVR-CDCが正常に使用できる環境であること。既にドライバのインストールが済み、動作確認ができていること。
使用するLCDモジュールはSC1602/SD1602などHD44780互換コントローラのものが前提です。

AVR-CDC 改造手順
【ファイルを配置する】
mega48フォルダ AVR Studio


AVR-CDCを拡張するファイル
ダウンロード avrcdc48extsrc.zip

上記zipファイルの中身
eeprlib_cdc.c
eeprlib_cdc.h
lcdlib_cdc.c
lcdlib_cdc.h
lcdlib_def.h


Recursion Co., Ltd.サイト内、AVR-CDCのページからダウンロードした「cdcio.2009-07-15.zip」(ファイル名は例)を解凍し、「mega48」フォルダを開きます。
「avrcdc48extsrc.zip」を解凍して得たファイルを「mega48」フォルダに置きます。
そのフォルダにある「cdcio.aps」をダブルクリックしてAVR Studioを起動します(関連付けしてある場合)。
lcdlib, eeprlibのソースファイルとヘッダファイルをプロジェクトに追加します。

【main.cを編集する】
下記テキストボックス内の記述(断片的なソース)を、main.cの該当箇所にコピー&ペーストしてください。
1.
先頭付近にlcdlib, eeprlibのヘッダファイルをincludeします。
2.
「@」「?」「=」などコマンドを解釈している部分に、LCD操作のコマンド「#」とEEPROM操作のコマンド「:」の解釈と処理内容を追加します。
1.ヘッダをインクルードする 2.コマンド解釈を追加する
[main.c]

#include "usbdrv.h"
#include "oddebug.h"

#include "lcdlib_cdc.h"
#include "eeprlib_cdc.h"

#define INTERRUPT_REPORT 1


[main.c]

switch( rbuf[0] ) {
case '#': // LCD operation
  lcdAction((uint8_t)tos, (uint8_t)val, (uint8_t)val2);
  break;
case ':': // EEPROM operation
  eepromAction((uint8_t)tos, (uint8_t)val, (uint8_t)val2);
  if (eepromResult(ERS_EXIST_HI)) {
   x = eepromResult(ERS_GET_HI);
   out_char( u2h(x>>4) );
   out_char( u2h(x&0x0f) );
  }
  if (eepromResult(ERS_EXIST_LO)) {
   x = eepromResult(ERS_GET_LO);
   out_char( u2h(x>>4) );
   out_char( u2h(x&0x0f) );
  }
  break;
case '@': // who
  ptr = PSTR( CMD_WHO );
  while( (c=pgm_read_byte(ptr++))!=0 ) {
  out_char(c);
  }
  break;



【リビルドする】
プロジェクトのOptionダイアログを開きます。
「Use External Makefile」のチェックを外し、
「Device:」を「atmega88」など目的のデバイスに変更します。
メニューバーの Build → Rebuild All でリビルドします。


【ファームを書き込む】
作成されたhexファイルを目的のデバイスに書き込んで完成です。

PC側からの呼び出し方
改造といってもAVR-CDCのコマンドを追加しただけなので、PC側からの使い方は従来と同様です。
データとして2つの値を送信することが多いので、'$'コマンド(set2()関数)と同じ書式になります。
LCDを操作するコマンドが'#'、EEPROMを操作するコマンドが':'です。それぞれにサブコマンドがあります。

AVR-CDC側は通常通りコマンド('#' ':' '@' '?' '=' など)で処理を振り分けます。コマンドがLCD操作('#')、EEPROM操作(':')だった場合はサブコマンドを解釈し、それに割り当てられた具体的な処理を実行します。

AVR-CDCが1回に受信できるデータは8byteまでです。[値][空白][値][空白][値][空白][コマンド]で7byte。一度に4個以上の値を受信することができません。そのため今回の改造ではAVR-CDC内に16byte分のバッファを持たせました。
※16byteの理由はLCDの1行を16桁と想定しているからです。1行分の文字列をまとめて処理できるように。正確にはヌル文字の分を入れて17byteで定義しています。

例えば10文字の文字列"アイウエオカキクケコ"を表示したい場合、次のようにします。
LCMD_BUF_READYでバッファ準備→LCMD_BUF_SETで2文字ずつ5回送信→LCMD_STRINGで表示開始。
AVR-CDC側はLCMD_STRINGを受信すると、バッファ内の値を対象として文字列表示の処理を実行します。
1文字転送→1文字表示→1文字転送→1文字表示→…を10回繰り返すよりも処理が速いです。

EEPROM操作では書き込み処理でアドレス/データとも16bitの場合があり、4byte分のデータを送信することになります。そのため、サブコマンドでアドレス指定とデータ指定の処理に分け、2byteずつ2回送信します。



LCD操作
PCからAVR-CDCへ送信する内容 「data2 data1 cmd '#'」 ※dataの並び順に注意
'#' LCD操作を表すコマンド。
cmd サブコマンド。
data1,data2 8bitデータ。または上位byte,下位byteに分割した16bitデータ。

LCD操作のサブコマンド
LCMD_BUF_READY AVR-CDC内バッファへの転送準備。
data1=0, data2=0
LCMD_BUF_SET AVR-CDC内バッファへ値をセットする。
data1=任意の1byte, data2=任意の1byte
LCMD_DATA_PORT データ線を配線したポート。レジスタ名を指定する。
data1=PORTx, data2=DDRx
LCMD_DATA_BIT データ線4bitの指定。
data1=連続する4bitを含む値。例:0x3C (0b00111100)
data2=ビットリバースする(1)/しない(0) ※配線の都合上、データ線の並びを逆順にしたい場合
LCMD_CTRL_PORT 制御線を配線したポート。レジスタ名を指定する。
data1=PORTx, data2=DDRx
LCMD_CTRL_BIT 制御線の指定。 ※R/W線は使用せず、配線はGND固定であるとする
data1=E線。例:0x02 (0b00000010)
data2=RS線。例:0x01 (0b00000001)
LCMD_INIT LCD初期化。ポートを設定した後に実行する。
data1=0, data2=0
LCMD_CMD LCDモジュールの内蔵コマンドを発行する。
data1=内蔵コマンドを表す8bitの値, data2=0
LCMD_CHAR 1文字表示する。
data1=char型1文字, data2=0
LCMD_STRING 16文字以下の文字列を表示する。LCMD_BUF_XXXと組み合わせて使う。
data1=0, data2=0
LCMD_UINT 符号なし整数を表示する。8bit整数は16bit整数にキャストしてdataにセットする。
data1=上位byte, data2=下位byte
LCMD_DEFCHAR 外字定義を確定する。LCMD_BUF_XXXと組み合わせて使う。
data1=0, data2=0



EEPROM操作
PCからAVR-CDCへ送信する内容 「data2 data1 cmd ':'」 ※dataの並び順に注意
':' EEPROM操作を表すコマンド。
cmd サブコマンド。
data1,data2 8bitデータ。または上位byte,下位byteに分割した16bitデータ。

EEPROM操作のサブコマンド
ERCMD_READ_BYTE 8bitデータを読み出す。
dataにアドレスを指定する。アドレスが8bit値の場合は16bit値にキャストする。
data1に上位byte、data2に下位byteをセットする。
戻り値は、1byte分の16進文字列+改行コード。
ERCMD_READ_WORD 16bitデータを読み出す。
dataにアドレスを指定する。アドレスが8bit値の場合は16bit値にキャストする。
data1に上位byte、data2に下位byteをセットする。
戻り値は、上位byte分の16進文字列+下位byte分の16進文字列+改行コード。
ERCMD_WRITE_ADDR データを書き込むアドレスを指定する。
アドレスが8bit値の場合は16bit値にキャストする。
data1に上位byte、data2に下位byteをセットする。
ERCMD_WRITE_BYTE 8bitデータを書き込む。
data1=8bit値, data2=0
ERCMD_WRITE_WORD 16bitデータを書き込む。
data1に上位byte、data2に下位byteをセットする。
※AVR-CDC内では<avr/eeprom.h>で定義されたeeprom_read/write_byte/word()を実行している。

作例:リソースモニタ
改造版AVR-CDCの利用例としてリソースモニタを作りました。
LCD操作方法、EEPROM操作方法のサンプルとしてソースファイルを公開します。
ダウンロード sample_resmon.zip
ダウンロード resmon_vs2008proj.zip
sample_resmon.zip 解凍→ ConsoleApplication1.exe …リソースモニタ
resmon_vs2008proj.zip …Visual Studio 2008 C# のプロジェクト丸ごと
※Visual Studio 2008 C# で開発。WindowsXPで動作確認。

主なソースファイルの説明
ATmega48.cs
AVR-CDCのサンプルプロジェクト内のatmega48.cs(レジスタ名の定義ファイル)にビット名の定義を追加しました。
CdcIO.cs
AVR-CDCのサンプルプロジェクト内のcdcio.cs(SerialPortの派生クラス)を補強し、LCD操作、EEPROM操作の関数を追加しました。
CmdDefine.cs
LCD操作、EEPROM操作のサブコマンドの定義です。AVR Studioで追加したlcdlib_cdc.c, eeprlib_cdc.c内にも同じ定義があり、サブコマンドが指す意味と値が一致している必要があります。
Program.cs
リソースモニタのプログラム本体です。COMポートのオープン/クローズ、LCDの初期化、LCDの外字登録、LCDの文字列表示、EEPROMの読み書き、のやり方が分かります。

【実行手順】
改造版AVR-CDCをPCに接続します。
デバイスマネージャからCOMポート番号を確認します。番号はPC環境により異なります。


コマンドプロンプトを開き、次のように入力してリソースモニタを起動します。COMポート名を引数にします。
Z:\>ConsoleApplication1.exe COM6

起動すると、このように表示されます。※初回起動時は日時が正しく表示されません。


【動作中の様子】
1秒周期でCPU負荷と空きメモリ容量をLCDに表示します。
CPU負荷が50%以上になると右上に「!!」マークが出ます。
[K]キーを押すごとに「FreeMem」←→「空きメモリ」の表示が切り替わります。


※5x8ドットにも関わらず「空」と読めてしまう。
回路図



◆ ◆ ◆
AVR-CDCを改造しました。サブコマンドを定義したことがポイントです。
ターゲットの容量が許す限りAVR-CDCの機能をいろいろ拡張することができます。
拡張した機能はPCからの通信による制御ではなくAVR内部で自立的に実行されるので、AVR-CDCに接続した機器を高速に扱えることになります。
PC側で処理手順を記述する必要が無くなり、ソフトの開発が楽になります。


2011/06 追記

AVR-CDC/IO(ATmega88使用)を基板に仕上げました。
今後の実験のため、クリスタルを取り替えられるようにしてあります。
通常は12MHzで使いますが、16MHzで動作することも確認済みです。
もちろんその場合は16MHz用のファームに差し替えます。



(C) 『昼夜逆転』工作室 [トップページへ戻る]
inserted by FC2 system