30天自制操作系统-第7天笔记

来源:互联网 发布:石家庄软件学院 编辑:程序博客网 时间:2024/06/12 10:49

1.获取按键编码

#define PORT_KEYDAT   0x0060void inthandler21(int *esp)/* 键盘中断 */{    struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;    unsigned char data ,s[4];    io_out8(PIC0_OCW2,0x61); //通知PICIRQ-01”已经受理完毕    data = io_in8(PORT_KEYDAT);    sprintf(s,"%02X",data);    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);//向屏幕输出s    for (;;) {        io_hlt();    }}

分析:
io_out8(PIC0_OCW2,0x61); 这句话告诉IPC“已经知道发生了IRQ1中断”。如果是IRQ3中断,则写成0x63.也就是说,将“0x60+IRQ号码”输出给OCW2就可以了。执行这句话之后,PIC继续监视IRQ1中断是否发生。反过来,如果忘记执行,PIC将不再监视。
下面:从编号为0x60的设备输入的8位信息是按键编码,0x60的设备就是键盘。
执行结果:图片1
图片1

2. 加快中断处理

1.添加缓冲标志,在bootpack.h 中加入:
/* int.c */

struct KEYBUF {    unsigned char data, flag;};

2.在int.c中处理中断:

#define PORT_KEYDAT   0x0060struct KEYBUF keybuf;void inthandler21(int *esp)/* 中断 */{    unsigned char data ;    io_out8(PIC0_OCW2,0x61); //通知PIC“IRQ-01”已经受理完毕    data = io_in8(PORT_KEYDAT);    if(keybuf.flag == 0){ //如果flag==0,说明之前的数据已经被打印,接下来把刚刚键盘输入的字符缓存        keybuf.data = data;        keybuf.flag = 1; //设置标志位1,    }    return;}

3.在主函数中处理中断(主函数中的for循环修改如下):

for (;;) {        //io_hlt();        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_008484, 0, 16, 15, 31);            putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);//向屏幕打印s        }    }

实现结果:缓冲区只能存储一个字节,出现问题:
结果与图1类似

3.制作缓冲区

  1. 修改缓存结构体:
struct KEYBUF {    unsigned char data[32];    int next;};

2 修改中断处理,提高缓存数据量

void inthandler21(int *esp)/* 中断 */{    unsigned char data ;    io_out8(PIC0_OCW2,0x61); //通知PICIRQ-01”已经受理完毕    data = io_in8(PORT_KEYDAT);    if(keybuf.next < 32){ //可以缓存32个字符        keybuf.data[keybuf.next] = data;        keybuf.next ++; //缓存数+1    }    return;}

3.修改输出:

for (;;) {        //io_hlt();        io_cli();        if(keybuf.next == 0){            io_stihlt();        }else{            i = keybuf.data[0];            keybuf.next--;            //向前移一位            for(j = 0; j < keybuf.next; j++){                keybuf.data[j] = keybuf.data[j+1];              }            io_sti();            sprintf(s,"%02X",i);            boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);            putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);//向屏幕打印s        }    }

结果与图1类似

4、5 改善和整理缓冲区

  1. 增加一个结构体 FIFO8
/* fifo.c */struct FIFO8 {    unsigned char *buf;    int p, q, size, free, flags;};

其中 :
p: 下一个写入的数据的位置
q : 下一个读出的数据的位置
size : 缓冲区总字节数
free: 保存缓冲区没有数据的字节数
2. 增加一个文件fifo.c,具体功能查看注释:

/* FIFO */#include "bootpack.h"#define FLAGS_OVERRUN       0x0001void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)/* FIFO初始化 */{    fifo->size = size;    fifo->buf = buf;    fifo->free = size; /* 空闲的大小 */    fifo->flags = 0;    fifo->p = 0; /* 下一个数据写入的位置 */    fifo->q = 0; /* 下一个数据读入的位置 */    return;}int fifo8_put(struct FIFO8 *fifo, unsigned char data)/* 向FIFO传送数据并保存 */{    if (fifo->free == 0) {        /* 空余没有了,溢出 */        fifo->flags |= FLAGS_OVERRUN;        return -1;    }    fifo->buf[fifo->p] = data;    fifo->p++;    if (fifo->p == fifo->size) {        fifo->p = 0;    }    fifo->free--;    return 0;}int fifo8_get(struct FIFO8 *fifo)/* FIFO获取一个数据 */{    int data;    if (fifo->free == fifo->size) {        /* 如果缓冲区为空,则返回-1 */        return -1;    }    data = fifo->buf[fifo->q];    fifo->q++;    if (fifo->q == fifo->size) {        fifo->q = 0;    }    fifo->free++;    return data;}int fifo8_status(struct FIFO8 *fifo)/*报告一下积攒了多少数据 */{    return fifo->size - fifo->free;}

3 修改中断函数:

struct FIFO8 keyfifo;void inthandler21(int *esp)/* 中断 */{    unsigned char data ;    io_out8(PIC0_OCW2,0x61); //通知PICIRQ-01”已经受理完毕    data = io_in8(PORT_KEYDAT);    fifo8_put(&keyfifo, data);    return;}

4 修改主函数:

fifo8_init(&keyfifo, 32, keybuf); //初始化keybuffor (;;) {        //io_hlt();        io_cli();        if(fifo8_status(&keyfifo) == 0){            io_stihlt();        }else{            i = fifo8_get(&keyfifo);            io_sti();            sprintf(s,"%02X",i);            boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);            putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);//向屏幕打印s        }    }

5 修改Make file文件:增加fifo.obj

6 make run
结果与图1类似

6、7.从鼠标接收数据

  1. 在bootpack.c 中添加3个函数:
#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                0x47void wait_KBC_sendready(void){    /* 等待键盘控制电路准备完毕 */    for (;;) {        if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {            break;        }    }    return;}void init_keyboard(void){    /* 初始化键盘控制电路 */    wait_KBC_sendready();    io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);    wait_KBC_sendready();    io_out8(PORT_KEYDAT, KBC_MODE);    return;}#define KEYCMD_SENDTO_MOUSE     0xd4#define MOUSECMD_ENABLE         0xf4void enable_mouse(void){    /* 激活鼠标 */    wait_KBC_sendready();    io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);    wait_KBC_sendready();    io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);    return; /* 顺利的话,键盘控制其会返送回ACK(0xfa) */}

2 设置鼠标中断

void inthandler2c(int *esp) /* 鼠标中断 */{    unsigned char data ;    io_out8(PIC1_OCW2,0x64); //通知PIC1IRQ-12”已经受理完毕    io_out8(PIC0_OCW2,0x62); //通知PIC0IRQ-02”已经受理完毕    data = io_in8(PORT_KEYDAT);    fifo8_put(&mousefifo, data);    return;}

3 修改主函数的显示

for (;;) {        //io_hlt();        io_cli();        if(fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 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_008484,  0, 16, 15, 31);                putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);            } else if (fifo8_status(&mousefifo) != 0) {                i = fifo8_get(&mousefifo);                io_sti();                sprintf(s, "%02X", i);                boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31);                putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);            }        }    }

4.结果显示:
这里写图片描述

阅读全文
0 0
原创粉丝点击