版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、精選優(yōu)質(zhì)文檔-傾情為你奉上操作系統(tǒng)實驗日志學(xué)號姓名甘昆祿專業(yè)年級班級智能1601實驗日期2018.11.07實驗項目第7天:FIFO與鼠標控制一、實驗主要內(nèi)容1. 獲取按鍵編碼實現(xiàn)功能:讓程序在按一個鍵后不結(jié)束,然后在屏幕上顯示出信息。這樣就可以切實完成中斷處理程序了。(顯示按鍵編碼,本來以為會顯示按鍵表示內(nèi)容,比如按A顯示A,還是太天真了哈哈,估計后面還要改)修改int.c程序中的inthandler21函數(shù):#define PORT_KEYDAT 0x0060void inthandler21(int *esp)/*來自PS/2鍵盤的中斷*/ struct BOOTINFO *binfo
2、= (struct BOOTINFO *) ADR_BOOTINFO; unsigned char data, s4; io_out8(PIC0_OCW2, 0x61); /*通知PIC*IRQ-01已經(jīng)受理完畢*/ data = io_in8(PORT_KEYDAT); sprintf(s, %02X, data); boxfill8(binfo-vram, binfo-scrnx, COL8_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); return;io_out8(PIC0
3、_OCW2, 0x61); 這句話用來通知PIC“已經(jīng)知道發(fā)生了IRQ1中斷。如果是IRQ3,則寫成0x63.也就是說,將”0x60+IRQ號碼”輸出給OCW2就可以。執(zhí)行這句話之后,PIC繼續(xù)時刻監(jiān)視IRQ1中斷是否發(fā)生。反過來,如果忘記了執(zhí)行這句話,PIC就不在監(jiān)視IRQ1中斷,不管下次由鍵盤輸入什么信息,系統(tǒng)都感知不到了。但事實上,我發(fā)現(xiàn)按字母鍵和其他健還是有些區(qū)別的。按其他健后再按另外的健會有反應(yīng)。但假若你一開始按字母鍵再按另外的健就沒有反應(yīng)了。2、加快中斷處理中斷處理是打斷CPU本來的工作,加塞要求進行處理。在處理進行期間不再接受別的中斷。若中斷處理速度太慢會影響CPU的的工作。將處
4、理字符顯示內(nèi)容的功能從中斷處理中提出來,將按鍵編碼接收下來保存到變量中,然后由HariMain偶爾去查看這個變量。發(fā)現(xiàn)有數(shù)據(jù)就顯示出來。struct KEYBUF unsigned char data, flag;#define PORT_KEYDAT 0x0060struct KEYBUF keybuf;void inthandler21(int *esp)/*來自PS/2鍵盤的中斷*/ unsigned char data; io_out8(PIC0_OCW2, 0x61); /*通知PIC*IRQ-01已經(jīng)受理完畢*/ data = io_in8(PORT_KEYDAT); if (ke
5、ybuf.flag = 0) keybuf.data = data; keybuf.flag = 1; return;在函數(shù)中用到了兩個變量:data和flag,所以可以建一個結(jié)構(gòu)體把兩個變量集中起來。將bootpack.c中MariMain函數(shù)中的io_halt()函數(shù)更改如下:for(;) io_cli(); if (keybuf.flag = 0) io_stihlt(); else i = keybuf.data; keybuf.flag = 0; io_sti(); sprintf(s, %02X, i); boxfill8(binfo-vram, binfo-scrnx, COL8
6、_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); 即將最初的inthandler21()函數(shù)拆解成了inthandler21()和for循環(huán)函數(shù)。開始先用io_cli指令屏蔽中斷(是為了防止被另外的指令中斷),然后去看一看keybuf.flag的值是什么。如果flag是0說明鍵還沒有按下,就去執(zhí)行io_hlt指令。但是由于已經(jīng)執(zhí)行io_cli屏蔽了中斷,所以就這樣去之心HLT指令的話,即使有鍵按下,程序也不會有任何反應(yīng)。所以STI和HLT兩個指令都要執(zhí)行,而執(zhí)行這兩個指令的函數(shù)就是
7、io_stihlt。執(zhí)行HLT指令后,如果收到PIC的通知,CPU就會被喚醒。這樣,CPU首先回去執(zhí)行中斷程序。中斷處理程序執(zhí)行完之后又回到for語句的開頭,再執(zhí)行io_cli函數(shù)。若執(zhí)行到else語句,說明在keybuf.data里存入了按鍵編碼。先將這個鍵碼(keybuf.data)值保存到變量i中,然后將flag置為0表示把鍵碼值清為空,再通過io_sti語句開放中斷。這樣一來,在屏蔽中斷期間所做的處理非常少,且會加快操作系統(tǒng)的中斷處理過程。最后莫忘了在bootpack中添加這一句:extern struct KEYBUF keybuf;以及早for循環(huán)中使用的i的聲明,還需要將stru
8、ct KEYBUF unsigned char data, flag;添加到.h文件中。右ctrl鍵的鍵碼值比較特殊,按下會產(chǎn)生兩個字節(jié)的鍵碼值”E0 1D”,而松開這個鍵之后會產(chǎn)生兩個字節(jié)的鍵碼值”E0 9D”。在一次產(chǎn)生兩個字節(jié)鍵碼值的情況下,因為鍵盤內(nèi)部電路一次只能發(fā)送一個字節(jié),所以一次按鍵就會產(chǎn)生兩次中斷,第一次中斷時發(fā)送E0,第二次中斷時發(fā)送1D。3、制作、整理緩沖區(qū)上一步在按右ctrl鍵時存入?yún)?shù)應(yīng)該有兩個字節(jié),但只顯示了一個字節(jié)舍棄了最開始那個。所以設(shè)計一個能夠存儲多字節(jié)的緩沖區(qū),就不會馬上存滿并舍棄較早存入的字節(jié)了。在結(jié)構(gòu)體KEYBUF里增加變量,可以定義一個數(shù)組:struct
9、 KEYBUF unsigned char data4;數(shù)組data4就是存入字節(jié)的緩沖區(qū),這里可以使用先前講到的FIFO、FILO這種棧,這里需要的是FIFO型,也就是先接收到的字節(jié)先顯示出來。于是代碼可以修改成這樣:struct KEYBUF unsigned char data32; int next;這一段代碼還是放在.h文件中,然后在int.c中修改代碼如下:void inthandler21(int *esp)/*來自PS/2鍵盤的中斷*/ unsigned char data; io_out8(PIC0_OCW2, 0x61); /*通知PIC*IRQ-01已經(jīng)受理完畢*/ da
10、ta = io_in8(PORT_KEYDAT); if (keybuf.flag 32) keybuf.datakeybuf.next = data; keybuf.next+; return;keybuf的起始點是“0”,所以最初存儲的數(shù)據(jù)是keybuf.data0。下一個數(shù)據(jù)是keybuf.data1,接著是2,一次類推,一共是32個存儲位置。下一個存儲位置用變量next來管理,這樣就能記住32個數(shù)據(jù)而不會溢出。修改HariMain中代碼:for (;) io_cli(); if (keybuf.next = 0) io_stihlt(); else i = keybuf.data0;
11、keybuf.next-; for (j = 0; j vram, binfo-scrnx, COL8_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); 注意里面用到的j還是要先聲明。如果next不是0,則說明至少有一個數(shù)據(jù)。最開始的一個數(shù)據(jù)肯定是放在data0中的,將這個數(shù)存入到變量i中去。這樣,數(shù)就減少了一個,所以講next減去1。如圖:然后遇到的問題就是上面的緩沖區(qū)處理需要數(shù)據(jù)移送,而且還是在中斷期間,花時還容易出錯。,這時候就需要改善了。主要看代碼就可以理解這個緩沖區(qū),相當(dāng)于
12、定義了兩個指針,一個指向下一個要讀的地方,一個指向下一個要存的地方。數(shù)據(jù)讀出位置追著數(shù)據(jù)寫入位置,且可以在寫入位置到達盡頭即緩沖區(qū)為空時重新回到0的位置,循環(huán)使用緩沖區(qū)空間。Bootpack.h的結(jié)構(gòu)體修改:struct KEYBUF unsigned char data32; int next_r, next_w, len;Int.c中inthandler21函數(shù)修改如下:void inthandler21(int *esp)/*來自PS/2鍵盤的中斷*/ unsigned char data; io_out8(PIC0_OCW2, 0x61); /*通知PIC*IRQ-01已經(jīng)受理完畢*/
13、 data = io_in8(PORT_KEYDAT); if (keybuf.next vram, binfo-scrnx, COL8_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); 這樣修改之后沒有任何數(shù)據(jù)移送操作,這個緩沖區(qū)可以記錄大量數(shù)據(jù),執(zhí)行速度又快。緩沖區(qū)固定為32字節(jié)以后改起來就不方便,所以把它定義成可變的。所以采用了指針的方法*buf(data32),將緩沖區(qū)的總字節(jié)保存在變量size(len)中。變量free用于保存緩沖區(qū)里沒有數(shù)據(jù)的字節(jié)數(shù)。緩沖區(qū)的地址保存在變量
14、buf里。p代表下一個數(shù)據(jù)寫入地址next_w,q代表寫一個數(shù)據(jù)讀出地址next_r。結(jié)構(gòu)體修改之后如下:struct KEYBUF unsigned char *buf; int p, q, size , free, flags;為了初始化緩沖區(qū)以及實現(xiàn)對緩沖區(qū)的相關(guān)操作,新建了一個fifo.c的文件。/* FIFO */#include bootpack.h#define FLAGS_OVERRUN 0x0001/fifo_init是結(jié)構(gòu)的初始化函數(shù),用來設(shè)定各種初始值,也就是設(shè)定FIFO8結(jié)構(gòu)的地址以及與結(jié)構(gòu)有關(guān)void fifo8_init(struct FIFO8 *fifo, in
15、t size, unsigned char *buf)/*初始化FIFO緩沖區(qū)*/ fifo-size = size; fifo-buf = buf; fifo-free = size; /*緩沖區(qū)的大小*/ fifo-flags = 0; fifo-p = 0; /*下一個數(shù)據(jù)寫入位置*/ fifo-q = 0; /*下一個數(shù)據(jù)讀出位置*/ return;/fifo8_put是往FIFO緩沖區(qū)存儲1字節(jié)信息的函數(shù)。如果一出返回-1,沒有溢出就返回0int fifo8_put(struct FIFO8 *fifo, unsigned char data)/*想FIFO傳遞數(shù)據(jù)并保存*/ if
16、(fifo-free = 0) /*空余沒有了,溢出了*/ fifo-flags |= FLAGS_OVERRUN; return -1; fifo-buffifo-p = data; fifo-p+; if (fifo-p = fifo-size) fifo-p = 0; fifo-free-; return 0;/fifo8_get函數(shù)是從FIFO緩沖區(qū)取出1字節(jié)的函數(shù)int fifo8_get(struct FIFO8 *fifo)/*從FIFO取得一個數(shù)據(jù)*/ int data; if (fifo-free = fifo-size) /如果緩沖區(qū)為空,則返回-1 return -1;
17、data = fifo-buf(fifo-q); fifo-q+; if (fifo-q = fifo-size) fifo-q = 0; fifo-free+; return data;/報告一下到底積攢了多少數(shù)據(jù)int fifo8_status(struct FIFO8 *fifo) return fifo-size - fifo-free;然后根據(jù)fifo.c中的函數(shù)在int.c中修改 inthandler21函數(shù)如下struct FIFO8 keyfifo;void inthandler21(int *esp)/*來自PS/2鍵盤的中斷*/ unsigned char data; io
18、_out8(PIC0_OCW2, 0x61); /*通知PIC*IRQ-01已經(jīng)受理完畢*/ data = io_in8(PORT_KEYDAT); fifo8_put(&keyfifo, data); return;該函數(shù)中的&是取地址運算符,用它可以取得結(jié)構(gòu)或變量的地址值。Fifo8_put接受的第一個參數(shù)是內(nèi)存地址,與之匹配,這里調(diào)用時傳遞的第一個參數(shù)也要是內(nèi)存地址。HariMain函數(shù)內(nèi)容如下: char s40, mcursor256, keybuf32; for (;) io_cli(); if (fifo8_status(&keyfifo) = 0) io_stihlt(); e
19、lse i = fifo8_get(&keyfifo); io_sti(); sprintf(s, %02X, i); boxfill8(binfo-vram, binfo-scrnx, COL8_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); 4、鼠標中斷分配給鼠標的中斷號碼是IRQ12,與鍵盤的IRQ1比起來差了好多代。要讓鼠標信號得到處理,要讓下面兩個裝置有效,一個是鼠標控制電路,一個是鼠標本身。關(guān)于控制電路的設(shè)定:鼠標控制電路包含在鍵盤控制電路里,如果鍵盤控制電路的初始化正
20、常完成,鼠標電路控制器的激活也就完成了。在bootpack.c后添加如下代碼:#define PORT_KEYDAT 0x0060#define PORT_KEYSTA 0x0064#define PORT_KEYCMD 0x0064#define KEYSTA_SEND_NOTREADY 0x02#define KEYCMD_WRITE_MODE 0x60#define KBC_MODE 0x47/讓鍵盤控制電路(KBC)做好準備動作,等待控制指令的到來。void wait_KBC_sendready(void) /等待鍵盤控制電路準備完畢 for (;) if (io_in8(PORT_K
21、EYSTA) & KEYSTA_SEND_NOTREADY) = 0) break; /*break語句是從for循環(huán)中強制退出*/ return;void init_keyboard(void) /初始化鍵盤控制電路,然后在HariMain函數(shù)調(diào)用init_keyboard函數(shù),鼠標控制電路的準備就完成了 wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, KBC_MODE); return;/然后開始發(fā)送激活鼠標的指令。歸根結(jié)底還是
22、要向鍵盤控制器發(fā)送指令#define KEYCMD_SENDTO_MOUSE 0xd4#define MOUSECMD_ENABLE 0xf4/這個函數(shù)與init_keyboard函數(shù)非常相似,不同點在于寫入的數(shù)據(jù)不同。如果往鍵盤控制電路發(fā)送指令0xd4,下一個數(shù)據(jù)就會自動發(fā)送給鼠標void enable_mouse(void) /*激活鼠標*/ wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
23、 return; /*順利的話,鍵盤控制器會返送回ACK(0xfa)*/鼠標中斷現(xiàn)在已經(jīng)有了,接下來是取出中斷數(shù)據(jù),int.c中添加代碼:struct FIFO8 mousefifo;void inthandler2c(int *esp)/* 來自PS/2鼠標的中斷 */ unsigned char data; io_out8(PIC1_OCW2, 0x64); /*通知PIC1 IRQ-12的受理已經(jīng)完成*/ io_out8(PIC0_OCW2, 0x62); /*通知PIC0 IRQ-02的受理已經(jīng)完成*/ data = io_out8(PORT_KEYDAT); fifo8_put(&m
24、ousefifo, data); return;鼠標和鍵盤的原理幾乎相同,所以程序也就非常相似。不同之處只有送給PIC的中斷受理通知。IRQ-12時從PIC的第4號(從PIC相當(dāng)于IRQ-08IRQ-15),首先要通知IRQ-12受理已完成,然后再通知主PIC。這是因為主/從PIC的協(xié)調(diào)不能夠自動完成,如果程序不交給主PIC該怎么做,它就會忽視從PIC的下一個中斷請求。鼠標數(shù)據(jù)取得方法如下:ifo8_init(&mousefifo, 128, mousebuf);for (;) io_cli(); if (fifo8_status(&keyfifo) + fifo8_status(&mouse
25、fifo) = 0) io_stihlt(); else if (fifo8_status(&keyfifo) != 0) i = fifo8_get(&keyfifo); io_sti(); sprintf(s, %02X, i); boxfill8(binfo-vram, binfo-scrnx, COL8_, 0, 16, 15, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 0, 16, COL8_FFFFFF, s); else if (fifo8_status(&mousefifo) != 0) i = fifo8_get(&mousefi
26、fo); io_sti(); sprintf(s, %02X, i); boxfill8(binfo-vram, binfo-scrnx, COL8_, 32, 16, 47, 31); putfonts8_asc(binfo-vram, binfo-scrnx, 32, 16, COL8_FFFFFF, s); 因為鼠標往往會比鍵盤更快地送出大量數(shù)據(jù),所以我們將它的FIFO緩沖區(qū)增加到了128字節(jié),避免溢出。取得數(shù)據(jù)的程序中,如果鍵盤和鼠標的FIFO緩沖區(qū)都為空了,就執(zhí)行HLT。如果不是兩個都空,就先檢查keyinfo,如果有數(shù)據(jù)就取出一個顯示出來。如果keyinfo是空,就再去檢查mouseinfo,如果有數(shù)據(jù),就取出一個顯示出來。二、遇到的問題及解決方法1、弄了很久還是對鍵盤的中斷有很多問題,第一個就是作者說的按一下鍵有兩個字節(jié)信息,即會產(chǎn)生兩個中斷,這兩個中斷究竟怎么處理的。因為就算到了今天的第四個工程,作者說要搞個聰明的緩沖區(qū),但還是覺得怪怪的,按鍵的前面那個字節(jié)編碼一直就沒有顯示出來,這樣做的緩沖區(qū)真的聰明嗎,還是說真的只要這兩個字節(jié)編碼的后面那個就夠了。在網(wǎng)上查詢的資料
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年生物樣本庫建設(shè)與運營合同
- 小班語言教案
- 半導(dǎo)體照明光源項目可行性研究報告申請報告
- 美術(shù)組教學(xué)工作計劃
- 寫給媽媽的感謝信模板集合5篇
- 護理學(xué)生自我鑒定大專(9篇)
- 關(guān)于堅持高二記敘文作文
- 小學(xué)三年級安全教育工作計劃
- 網(wǎng)絡(luò)實習(xí)報告范文合集六篇
- 云南省昭通市昭陽區(qū)2024-2025學(xué)年八年級上學(xué)期1月期末考試歷史試卷(無答案)
- 2023-2024學(xué)年廣東省深圳市光明區(qū)高二(上)期末地理試卷
- 【8地RJ期末】安徽省蕪湖市弋江區(qū)2023-2024學(xué)年八年級上學(xué)期期末考試地理試卷(含解析)
- 2025年春季幼兒園后勤工作計劃
- SCI論文寫作課件
- 濕法脫硫用水水質(zhì)要求
- 城管局個人工作總結(jié)
- 鉑銠合金漏板.
- (完整版)建筑力學(xué)(習(xí)題答案)
- 少年宮籃球活動教案
- 國有建設(shè)企業(yè)《大宗材料及設(shè)備采購招標管理辦法》
- 民間秘術(shù)絕招大全
評論
0/150
提交評論