處理器:intel celeron® dual-core cpu 2.10ghz
作業系統:windows7 專業版 x86
工具:../toolset/
鍵盤輸入處理的流程似滑鼠輸入處理流程,需要提前配置好gdt和idt,並初始化好pic。
int keydata0;
struct fifo32 *keyfifo;
void wait_kbc_sendready(void)
} return;
}/* 初始化鍵盤控制電路
* fifo為管理緩衝區的結構體
* 鍵盤緩衝區加上data0的值後再寫入緩衝區,跟其它資料得以區分
*/void init_keyboard(struct fifo32 *fifo, int data0)
初始化鍵盤控制電路,讓鍵盤控制電路接收鍵盤按下時向它傳送的資料。
鍵盤中斷訊號為為pic上的irq1,所以需要開啟pic對irq1中斷的監聽。
io_out8(pic0_imr, 0xf8);// 主pic埠0x0021,11111000:irq0-2中斷允許
允許監聽某irq0-2後,如果picirq0-2有中斷來臨,則pic向cpu匯報這些中斷。
在初始化pic時,設定int0x20 ~ 0x2f接收中斷訊號irq0~ 15。形象的將鍵盤中斷函式名稱為inthander21。
void inthandler21(int *esp)
鍵盤資料儲存埠60h中,需要程式自動讀取。
中斷程式的返回需要使用iretd指令,c語句無與iretd對應的語句,需要用編寫匯程式設計序asm_inthandler21()來呼叫inthandler21()的方式來達到讀取60h中的鍵盤資訊,在idt中註冊鍵盤中斷函式註冊asm_inthandler21()即可。
1. global _asm_inthandler21
2. extern _inthandler21
3. _asm_inthandler21:
4. push es
5. push ds
6. pushad
7. mov eax,esp
8. push eax
9. mov ax,ss
10. mov ds,ax
11. mov es,ax
12. call _inthandler21
13. pop eax
14. popad
15. pop ds
16. pop es
17. iretd
//設定gdt和idt
void init_gdtidt(void)
當鍵盤被按下或者鬆開時,鍵盤向鍵盤控制電路的60h埠傳送鍵盤資料,此時pic向cpu匯報irq1的中斷資訊。cpu接收到pic的這個匯報後,(執行完當前指令後)根據中斷資訊的中斷號(irq1的中斷號為21h)轉去執行idt+ 21h(位址)中asm_inthandler21位址處的**。(經iretd指令後,cpu又返回到原程式中執行後續指令)。
在鍵盤上按下乙個鍵時,鍵盤向埠60h傳送這個按鍵的掃瞄碼(通碼);當鬆開這個按鍵時,鍵盤向埠60h傳送這個按鍵的斷碼(通碼+ 80h)。「書」14.4章節有鍵盤各個按鍵的通碼表,其中』a』按鍵的通碼值為1eh。
在主函式harimain()中包含處理鍵盤輸入的各步驟。
……
void harimain(void)
else
}…………}}
開啟「書」中的「!cons_nt.bat」,整個程式通過編譯後,執行「makerun」命令在qemu中執行程式。
鍵盤上有很多個需要顯示的字元,將它們組織在乙個資料結構裡面供鍵盤顯示。
按照鍵盤上每個字元編碼的規律,用乙個陣列來儲存鍵盤的各按鍵字元。
static char keytable[0x54] = ;
keytable[0x1e]對應字元』a』,』a』的通碼剛好為1eh。
最好是能根據鍵盤輸入就能夠對應鍵盤輸入按鍵在資料結構的對應的字元。
i = fifo32_get(&fifo);
io_sti();
if (256 <= i && i <= 511) }}
按照keytable陣列中編排按鍵字元以及往緩衝區寫入鍵盤資料的方式,鍵盤通碼減去256剛好是鍵盤字元在keytable陣列中的下標。
文字的輸入背景就是用繪製矩形的函式繪製一些矩形。
/* 製作文字輸入的背景
* sht為文字輸入所在的圖層,
* x0,y0為文字輸入背景的起始位置,
* sx,sy為在文字輸入背景在x,y方向上的長度
* c為文字輸入背景邊框的顏色
*/void make_textbox8(struct sheet *sht, int x0, int y0, int sx, int sy, int c)
字元輸入圖示根據鍵盤輸入的變化而變化,將游標的座標變換寫到harimain()主函式中。
int cursor_x, cursor_c;
……make_textbox8(sht_win, 8, 28, 144, 16, col8_ffffff);
cursor_x = 8;
cursor_c = col8_ffffff;
……for (;;) else
}if (i == 256 + 0x0e && cursor_x > 8)
//顯示游標
boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
} else if (512 <= i && i <= 767) else if (i == 10) else if (i == 3) else if (i <= 1) else
timer_settime(timer3, 50);
boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);}}}
程式通過編譯後,在真機中執行。
figure1.接收鍵盤輸入 及 鍵盤輸入的背景顯示
在harimain()程式中實現視窗的移動。
for (;;) else else if (512 <= i && i <= 767)
}} else if (i == 10) else if (i == 3) else if (i <= 1) else
timer_settime(timer3, 50);
boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);}}}
整個程式編譯通過後,在真機中執行。
figure2. 視窗的移動
初始化外部中斷硬體模組到呼叫中斷程式的過程。
圖示的移動。
[x86os] note over.
[2015.04.17]