AVR313 AVR313 : PC ATキーホ ート のインターフェース 法 要 点 標 準 PC ATキーホ ート のインターフェース 2つの 入 出 力 ヒ ンだけが 必 要 (それらの1つは 外 部 割 り 込 みヒ ンでなければなりません ) 外 部 ハート ウェア 必 要 なし キーホ ート シリアル 変 換 器 を 実 装 するC 言 語 での 完 全 な 例 序 説 殆 どのマイクロ コントローラはいくつかの 種 類 の 対 人 インターフェースを 必 要 とします この 応 用 記 述 は 標 準 PC ATキーホ ート を 使 用 してこれを 行 う1つの 方 法 を 記 述 します 物 理 インターフェース キーホ ート とホスト 間 の 物 理 インターフェースが 図 1.で 示 されます クロックとテ ータの2つの 信 号 線 が 使 用 さ れます 信 号 線 はキーホ ート 内 に 配 置 されたフ ルアッフ 抵 抗 を 持 つオーフ ン コレクタです これはホスト またはキーホ ート のどちらでもLowレヘ ルの 強 制 を 可 能 にします "5D" 型 式 の5ヒ ンDINコネクタとより 小 さな6ヒ ンのミニDINの2つのコネクタが 利 用 可 能 です ヒ ン 割 り 当 ては 表 1.で 示 されます 図 1. インターフェース VCC AVR +5V キーホ ート VCC 8ヒ ット マイクロ コントローラ 応 用 記 述 (またはINTn) INT0 Clock Pxn GND Data GND 表 1. ATキーホ ート コネクタ ヒ ン 割 り 当 て 2 4 5 ATコンヒ ュータ 1 3 信 号 DIN41524(PC 側 メス)5ヒ ンDIN 180 6 5 4 3 2 1 PS2 形 式 6ヒ ン ミニDIN(PC 側 メス) Clock 1 5 Data 2 1 N.C. 3 2,6 GND 4 3 +5V 5 4 遮 蔽 外 殻 外 殻 本 書 は 一 般 の 方 々の 便 宜 のた め 有 志 により 作 成 されたもので ATMEL 社 とは 無 関 係 であること を 御 承 知 ください しおりのはじ めにでの 内 容 にご 注 意 ください Rev. 1235B-05/02, 1235BJ1-12/13 1
タイミンク キーホ ート からホストへのテ ータ 転 送 は 図 2.で 示 されます 規 約 は1 開 始 ヒ ット( 常 に0) 8テ ータ ヒ ット 奇 数 ハ リティ ヒ ット 1 停 止 ヒ ット( 常 に1)で す テ ータはクロック ハ ルスのLow 区 間 の 間 で 有 効 です キーホ ート がクロック 信 号 を 生 成 し クロック ハ ルスは 代 表 的 に30~50μsのLowと30~50 μsのhighです ホスト システムはクロック 線 をLowに 強 制 することによってキーホ ート へ 命 令 を 送 ることができます そしてテ ータ 線 をLowに 引 き 込 みます( 開 始 ヒ ット) 直 ぐにクロック 線 は(キーホ ート に 於 いて) 開 放 されなければなりません キーホ ート は10 個 のクロック ハ ルスを 数 えます テ ータ 線 はクロック ハ ルスの 後 行 端 の 前 にホストによって 正 しいレヘ ルに 設 定 されなければなりません 第 10ヒ ット 後 キーホ ート はテ ータ 線 上 のHighレヘ ル( 停 止 ヒ ット)を 調 べ それがHighなら テ ータ 線 をLowに 強 制 します これはキーホ ート によってテ ータが 受 信 されたことをホストに 知 らせます この 設 計 記 述 に 於 けるソフトウェアはキーホ ート へどんな 命 令 も 送 りません 走 査 符 号 ATキーホ ート は 各 キーに 関 連 する 走 査 符 号 を 持 ちます キーが 押 されると この 符 号 が 送 信 されます キーが 一 定 の 間 押 さえ 付 けられる と 繰 り 返 しを 始 めます 繰 り 返 し 速 度 は 代 表 的 に1 秒 間 に10 回 です キーが 開 放 されると キー 走 査 符 号 が 後 続 する"break" 符 号 ($F0) が 送 信 されます キーの 殆 どに 関 して 走 査 符 号 は1ハ イトです Home,Insert,Delete キーのようないくつかのキーは2~5ハ イトの 拡 張 走 査 符 号 を 持 ちます (これらの) 先 頭 ハ イトは 常 に$E0です これは"break" 手 順 ( 例 えば$E0,$F0,$xx,...)についても 変 わりません ATキーホ ート は3 組 の 走 査 符 号 を 扱 う 能 力 があり そして 第 2 組 が 既 定 です 本 例 は 第 2 組 だけを 使 用 します 方 法 キーホ ート 受 信 はINT0_interrupt 割 り 込 み 関 数 によって 処 理 されます 受 信 は 残 りのフ ロク ラムと 無 関 係 に 動 作 します 方 法 は 全 く 単 純 で クロック ハ ルスの 先 行 端 でテ ータ 線 の 値 を 格 納 します これはクロック 線 がINT0またはINTnヒ ンに 接 続 されている 場 合 容 易 に 扱 われます 割 り 込 み 関 数 はクロック 周 期 のエッシ 毎 に 実 行 され テ ータは 下 降 端 で 格 納 されます 全 てのヒ ットが 受 信 された 後 テ ータを 復 号 することができます これはdecode 関 数 を 呼 び 出 すことによって 行 われます 文 字 キーに 関 してこの 関 数 はASCII 文 字 を 緩 衝 部 内 に 格 納 します キーが 押 された 時 にシフト キーが 押 さえ 付 けられている 場 合 を 考 慮 します 機 能 キー 誘 導 キー( 矢 印 キー Page Up/Downキーなど)ような 他 のキーとCtrlやAltのような 変 更 キーは 無 視 されます 走 査 符 号 からASCII 文 字 への 割 り 当 てはシフトされた 文 字 に 対 する1つの 表 とシフトされないものに 対 する1つの 参 照 表 で 処 理 されます 変 更 と 改 良 ホストがキーホ ート との 同 期 を 外 した 場 合 後 続 する 全 ての 受 信 テ ータが 不 正 になります これを 解 決 する1つの 方 法 は 時 間 超 過 を 用 いる ことです 1.5ms 以 内 に11ヒ ットが 受 信 されない 場 合 何 らかの 異 常 が 起 きています ヒ ット 計 数 器 がリセットされ 誤 ったテ ータは 破 棄 され るべきです 自 動 繰 り 返 し(typematic)の 速 度 と 遅 延 のようなキーホ ート のハ ラメータが 設 定 される 場 合 テ ータがキーホ ート へ 送 られなければなりません これは 前 で 記 述 されるように 行 うことができます 命 令 についてはキーホ ート 製 造 業 者 の 仕 様 をご 覧 ください 図 2. キーホ ート からホストへの 転 送 タイミンク Clock Data 開 始 ヒ ット0 ヒ ット1 ヒ ット2 ヒ ット3 ヒ ット4 ヒ ット5 ヒ ット6 ヒ ット7 ハ リティ 停 止 2 AVR313
AVR313 Main.c #include <pgmspace.h> #include <stdio.h> #include <stdlib.h> #include "io8515.h" #include "serial.h" #include "gpr.h" #include "kb.h" void main(void) unsigned char key; init_uart(); init_kb(); while(1) key=getchar(); putchar(key); delay(100); // UART 送 信 緩 衝 部 初 期 化 // キーホ ート 受 信 初 期 化 // キーホ ート からの 受 信 文 字 取 得 // 受 信 文 字 をUART 送 信 Low_level_init.c #include <ina90.h> #include <io8515.h> int low_level_init(void) UBRR = 12; // 19200bps/4 MHz UCR = 0x08; // UART 送 信 許 可 GIMSK= 0x40; // INT0 割 り 込 み 許 可 _SEI(); return 1; // 全 体 割 り 込 み 許 可 3
Serial.c #include <stdio.h> #include <pgmspace.h> #include <io8515.h> /* I/Oレシ スタ 宣 言 */ #include "serial.h" #define ESC 0x1b #define BUFF_SIZE 64 flash char CLR[] = ESC, '[','H', ESC, '[', '2', 'J',0; unsigned char UART_buffer[BUFF_SIZE]; unsigned char *inptr, *outptr; unsigned char buff_cnt; void init_uart(void) inptr = UART_buffer; outptr = UART_buffer; buff_cnt = 0; void clr(void) puts_p(clr); // VT100 端 末 へ ' 画 面 消 去 'を 送 信 int putchar(int c) if (buff_cnt<buff_size) // 緩 衝 部 内 空 き 有 りで *inptr = c; // 緩 衝 部 内 に 文 字 設 定 inptr++; // 緩 衝 部 書 き 込 み 位 置 指 示 子 進 行 buff_cnt++; // 緩 衝 部 内 文 字 ハ イト 数 増 加 if (inptr >= UART_buffer + BUFF_SIZE) // 緩 衝 部 書 き 込 み 位 置 指 示 子 上 限 丸 め inptr = UART_buffer; UCR = (1<<UDRIE) (1<<TXEN); // UARTテ ータ レシ スタ 空 割 り 込 み 許 可 return 1; // 成 功 符 号 で 復 帰 else // 緩 衝 部 内 空 きなしで return 0; // 緩 衝 部 満 杯 符 号 で 復 帰 /* 割 り 込 み 駆 動 UART 送 信 */ interrupt [UART_UDRE_vect] void UART_UDRE_interrupt(void) UDR = *outptr; // 緩 衝 部 から1ハ イト 送 信 開 始 outptr++; // 緩 衝 部 読 み 込 み 位 置 指 示 子 進 行 if (outptr >= UART_buffer + BUFF_SIZE) outptr = UART_buffer; if (--buff_cnt == 0) UCR = UCR && (1<<UDRIE); // 緩 衝 部 読 み 込 み 位 置 指 示 子 上 限 丸 め // 緩 衝 部 内 文 字 ハ イト 数 減 少 緩 衝 部 が 空 らで // UARTテ ータ レシ スタ 空 割 り 込 み 禁 止 4 AVR313
AVR313 Kb.c #include <pgmspace.h> #include "kb.h" #include "serial.h" #include "gpr.h" #include "scancodes.h" #define BUFF_SIZE 64 unsigned char edge, bitcount; // 0= 下 降 端, 1= 上 昇 端 unsigned char kb_buffer[buff_size]; unsigned char *inpt, *outpt; unsigned char buffcnt; void init_kb(void) inpt = kb_buffer; outpt = kb_buffer; buffcnt = 0; // 緩 衝 部 初 期 化 MCUCR = 2; // INT0 割 り 込 みを 下 降 端 に 設 定 edge = 0; // 下 降 端 フラク 設 定 (0= 下 降 端,1= 上 昇 端 ) bitcount = 11; // 受 信 ヒ ット 計 数 器 初 期 化 interrupt [INT0_vect] void INT0_interrupt(void) static unsigned char data; // 受 信 した 走 査 符 号 ハ イト if (!edge) // 下 降 端 割 り 込 みで 開 始 if(bitcount < 11 && bitcount > 2) // 10~3がテ ータ 開 始 /ハ リティ/ 停 止 ヒ ットは 無 視 data = (data >> 1); // 現 受 信 テ ータを1ヒ ット 下 位 側 へ 移 動 (MSB=0) if(pind & 8) // Data 線 =High(1)で data = data 0x80; // 現 受 信 テ ータのMSBを1に 設 定 MCUCR = 3; // INT0 割 り 込 みを 上 昇 端 に 設 定 edge = 1; // 上 昇 端 フラク 設 定 (0= 下 降 端,1= 上 昇 端 ) else // 上 昇 端 での 割 り 込 みで MCUCR = 2; // INT0 割 り 込 みを 下 降 端 に 設 定 edge = 0; // 下 降 端 フラク 設 定 (0= 下 降 端,1= 上 昇 端 ) if(--bitcount == 0) // 受 信 ヒ ット 計 数 器 減 数 受 信 完 了 で decode(data); // 受 信 走 査 符 号 をASCII 符 号 に 変 換 bitcount = 11; // 受 信 ヒ ット 計 数 器 初 期 化 5
void decode(unsigned char sc) static unsigned char is_up=0, shift = 0, mode = 0; unsigned char i; if (!is_up) // 直 前 がキー 開 放 (break) 符 号 でなければ switch (sc) case 0xF0 : is_up = 1; // キー 開 放 (break) 符 号 なら // キー 開 放 (break) 符 号 フラク 設 定 case 0x12 : shift = 1; case 0x59 : shift = 1; // 左 側 Shiftキーなら // シフト フラク 設 定 // 右 側 Shiftキーなら // シフト フラク 設 定 case 0x05 : // F1キーで if(mode == 0) mode = 1; if(mode == 2) mode = 3; // ASCII 動 作 開 放 状 態 ならば 走 査 符 号 動 作 に 変 更 // 走 査 符 号 動 作 開 放 状 態 ならばASCII 動 作 に 変 更 default: if(mode == 0 mode == 3) // ASCII 動 作 なら if(!shift) // シフトなしで for(i = 0; unshifted[i][0]!=sc && unshifted[i][0]; i++); // 対 応 表 検 索 if (unshifted[i][0] == sc) // 有 効 符 号 なら 対 応 文 字 をキー 緩 衝 部 へ 格 納 put_kbbuff(unshifted[i][1]); else // シフト 有 りで for(i = 0; shifted[i][0]!=sc && shifted[i][0]; i++); // 対 応 表 検 索 if (shifted[i][0] == sc) // 有 効 符 号 なら 対 応 文 字 をキー 緩 衝 部 へ 格 納 put_kbbuff(shifted[i][1]); else // 走 査 符 号 動 作 なら print_hexbyte(sc); // 走 査 符 号 を16 進 文 字 で 直 接 出 力 put_kbbuff(' '); // 緩 衝 部 に 空 白 文 字 を 設 定 put_kbbuff(' '); else // 直 前 がキー 開 放 (break) 符 号 で is_up = 0; // キー 開 放 (break) 符 号 フラク 解 除 ($F0 連 続 は 禁 止 ) switch (sc) case 0x12 : // 左 側 Shiftキーなら shift = 0; // シフト フラク 解 除 case 0x59 : shift = 0; // 右 側 Shiftキーなら // シフト フラク 解 除 case 0x05 : // F1キーで if(mode == 1) mode = 2; if(mode == 3) mode = 0; // 走 査 符 号 動 作 ならば 走 査 符 号 動 作 開 放 状 態 に 変 更 // ASCII 動 作 ならばASCII 動 作 開 放 状 態 に 変 更 case 0x06 : clr(); // F2キーで // 画 面 消 去 符 号 列 送 信 6 AVR313
AVR313 void put_kbbuff(unsigned char c) if (buffcnt<buff_size) // キー 緩 衝 部 空 き 有 りで *inpt = c; // キー 緩 衝 部 内 に 文 字 ハ イト 設 定 inpt++; // キー 緩 衝 部 書 き 込 み 位 置 指 示 子 進 行 buffcnt++; // キー 緩 衝 部 内 文 字 ハ イト 数 計 数 値 増 加 if (inpt >= kb_buffer + BUFF_SIZE) inpt = kb_buffer; // キー 緩 衝 部 書 き 込 み 位 置 指 示 子 丸 め int getchar(void) int byte; while(buffcnt == 0); byte = *outpt; outpt++; // キー 緩 衝 部 文 字 有 りまで 待 機 // キー 緩 衝 部 から 文 字 ハ イト 取 得 // キー 緩 衝 部 読 み 込 み 位 置 指 示 子 進 行 if (outpt >= kb_buffer + BUFF_SIZE) // キー 緩 衝 部 読 み 込 み 位 置 指 示 子 丸 め outpt = kb_buffer; buffcnt--; // キー 緩 衝 部 内 文 字 ハ イト 数 計 数 値 減 少 return byte; Gpr.c #include "gpr.h" void print_hexbyte(unsigned char i) unsigned char h, l; h = i & 0xF0; h = h>>4; h = h + '0'; if (h > '9') h = h + 7; l = (i & 0x0F)+'0'; if (l > '9') l = l + 7; putchar(h); putchar(l); // 上 位 ニフ ル 抽 出 // 上 位 ニフ ルを 下 位 ニフ ル 位 置 へ 移 動 // 16 進 文 字 符 号 変 換 // '9' 越 えで 'A'からに 変 更 // 下 位 ニフ ル16 進 文 字 符 号 変 換 // '9' 越 えで 'A'からに 変 更 // 上 位 ニフ ル16 進 文 字 直 接 出 力 // 下 位 ニフ ル16 進 文 字 直 接 出 力 void delay(char d) char i,j,k; for(i=0; i<d; i++) for(j=0; j<40; j++) for(k=0; k<176; k++); Pindefs.h //********************* // ヒ ン 定 義 ファイル //********************* // キーホ ート 接 続 #define PIN_KB PIND #define PORT_KB PORTD #define CLOCK 2 #define DATAPIN 3 7
Scancodes.h // シフトなし 符 号 - 文 字 対 応 表 flash unsigned char unshifted[][2] = 0x0d,9, 0x0e,' ', 0x15,'q', 0x16,'1', 0x1a,'z', 0x1b,'s', 0x1c,'a', 0x1d,'w', 0x1e,'2', 0x21,'c', 0x22,'x', 0x23,'d', 0x24,'e', 0x25,'4', 0x26,'3', 0x29,' ', 0x2a,'v', 0x2b,'f', 0x2c,'t', 0x2d,'r', 0x2e,'5', 0x31,'n', 0x32,'b', 0x33,'h', 0x34,'g', 0x35,'y', 0x36,'6', 0x39,',', 0x3a,'m', 0x3b,'j', 0x3c,'u', 0x3d,'7', 0x3e,'8', 0x41,',', 0x42,'k', 0x43,'i', 0x44,'o', 0x45,'0', 0x46,'9', 0x49,'.', 0x4a,'-', 0x4b,'l', 0x4c,'o', 0x4d,'p', 0x4e,'+', 0x52,'a', 0x54,'a', 0x55,'\\', 0x5a,13, 0x5b,' ', 0x5d,'\'', 0x61,'<', 0x66,8, 0x69,'1', 0x6b,'4', 0x6c,'7', 0x70,'0', 0x71,',', 0x72,'2', 0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+', 0x7a,'3', 0x7b,'-', 0x7c,'*', 0x7d,'9', 0,0 ; // シフト 有 り 符 号 - 文 字 対 応 表 flash unsigned char shifted[][2] = 0x0d,9, 0x0e,' ', 0x15,'Q', 0x16,'!', 0x1a,'Z', 0x1b,'S', 0x1c,'A', 0x1d,'W', 0x1e,'"', 0x21,'C', 0x22,'X', 0x23,'D', 0x24,'E', 0x25,'.', 0x26,'#', 0x29,' ', 0x2a,'V', 0x2b,'F', 0x2c,'T', 0x2d,'R', 0x2e,'%', 0x31,'N', 0x32,'B', 0x33,'H', 0x34,'G', 0x35,'Y', 0x36,'&', 0x39,'L', 0x3a,'M', 0x3b,'J', 0x3c,'U', 0x3d,'/', 0x3e,'(', 0x41,';', 0x42,'K', 0x43,'I', 0x44,'O', 0x45,'=', 0x46,')', 0x49,':', 0x4a,'_', 0x4b,'L', 0x4c,'O', 0x4d,'P', 0x4e,'?', 0x52,'A', 0x54,'A', 0x55,'`', 0x5a,13, 0x5b,'^', 0x5d,'*', 0x61,'>', 0x66,8, 0x69,'1', 0x6b,'4', 0x6c,'7', 0x70,'0', 0x71,',', 0x72,'2', 0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+', 0x7a,'3', 0x7b,'-', 0x7c,'*', 0x7d,'9', 0,0 ; 8 AVR313
本 社 Atmel Corporation 2325 Orchard Parkway San Jose, CA 95131, USA TEL 1(408) 441-0311 FAX 1(408) 487-2600 国 外 営 業 拠 点 Atmel Asia Unit 1-5 & 16, 19/F BEA Tower, Millennium City 5 418 Kwun Tong Road Kwun Tong, Kowloon Hong Kong TEL (852) 2245-6100 FAX (852) 2722-1369 Atmel Europe Le Krebs 8, Rue Jean-Pierre Timbaud BP 309 78054 Saint-Quentin-en-Yvelines Cedex France TEL (33) 1-30-60-70-00 FAX (33) 1-30-60-71-11 Atmel Japan 104-0033 東 京 都 中 央 区 新 川 1-24-8 東 熱 新 川 ヒ ル 9F アトメル シ ャハ ン 株 式 会 社 TEL (81) 03-3523-3551 FAX (81) 03-3523-7581 製 造 拠 点 Memory 2325 Orchard Parkway San Jose, CA 95131, USA TEL 1(408) 441-0311 FAX 1(408) 436-4314 Microcontrollers 2325 Orchard Parkway San Jose, CA 95131, USA TEL 1(408) 441-0311 FAX 1(408) 436-4314 La Chantrerie BP 70602 44306 Nantes Cedex 3 France TEL (33) 2-40-18-18-18 FAX (33) 2-40-18-19-60 ASIC/ASSP/Smart Cards Zone Industrielle 13106 Rousset Cedex France TEL (33) 4-42-53-60-00 FAX (33) 4-42-53-60-01 1150 East Cheyenne Mtn. Blvd. Colorado Springs, CO 80906, USA TEL 1(719) 576-3300 FAX 1(719) 540-1759 Scottish Enterprise Technology Park Maxwell Building East Kilbride G75 0QR Scotland TEL (44) 1355-803-000 FAX (44) 1355-242-743 RF/Automotive Theresienstrasse 2 Postfach 3535 74025 Heilbronn Germany TEL (49) 71-31-67-0 FAX (49) 71-31-67-2340 1150 East Cheyenne Mtn. Blvd. Colorado Springs, CO 80906, USA TEL 1(719) 576-3300 FAX 1(719) 540-1759 Biometrics Avenue de Rochepleine BP 123 38521 Saint-Egreve Cedex France TEL (33) 4-76-58-47-50 FAX (33) 4-76-58-47-60 文 献 請 求 www.atmel.com/literature Atmel Corporation 2002. ATMEL 製 品 は ウェフ サイト 上 にあるATMELの 定 義 条 件 による 標 準 保 証 で 明 示 された 内 容 以 外 の 保 証 はありません 本 製 品 は 改 良 のため 予 告 なく 変 更 される 場 合 があります いかなる 場 合 も 特 許 や 知 的 技 術 のライセンスを 与 えるものではありません ATMEL 製 品 は 生 命 維 持 装 置 の 重 要 部 品 などのような 使 用 を 認 めておりません 本 書 中 の はATMELの 登 録 商 標 商 標 です 本 書 中 の 製 品 名 などは 一 般 的 に 商 標 です HERO 2013. 本 応 用 記 述 はATMELのAVR313 応 用 記 述 (doc1235.pdf Rev.1235B-05/02)の 翻 訳 日 本 語 版 です 日 本 語 では 不 自 然 となる 重 複 す る 形 容 表 現 は 省 略 されている 場 合 があります 日 本 語 では 難 解 となる 表 現 は 大 幅 に 意 訳 されている 部 分 もあります 必 要 に 応 じて 一 部 加 筆 されています 頁 割 の 変 更 により 原 本 より 頁 数 が 少 なくなっています 必 要 と 思 われる 部 分 には( ) 内 に 英 語 表 記 や 略 称 などを 残 す 形 で 表 記 しています 青 字 の 部 分 はリンクとなっています 一 般 的 に 赤 字 の0,1は 論 理 0,1を 表 します その 他 の 赤 字 は 重 要 な 部 分 を 表 します