0x07_自制操作系统My-OS实现键盘输出字符到屏幕

接上一课class04,这是他的运行结果

 

收到了键盘的中断,现在想的当然是怎么把输入的文字显示到屏幕上,做成一个最简单的IO

 

这是class04的目录结构,现在我们把他换成class05

我们现在要读取键盘的数据,然后显示在屏幕上面

interrupt.c

#include "include/head.h"


void inthandler21(int *esp)
/* 来自PS/2键盘的中断 */
{
    unsigned char data,s[256];
    io_set8(PIC0_OCW2, 0x61); /* 通知PIC,说IRQ-01的受理已经完成 */
    data = io_get8(PORT_KEYDAT);
    struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;

    boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
    sprintf(s, "key = %d", data);
    putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);

    return;
}

直接修改中断函数里面的代码即可,主要就是获取data然后输出

head.h

/*interrupt.c*/
#define PORT_KEYDAT 0x0060

这个是数据的地址,你要修改一下head.h,刚刚的那个函数要用的

 运行:

cd class05
..\z_tools\make.exe run

如果你发现你的键盘按一下就没用了可能是现在的键盘有点新,你可以把大写锁定打开,如果你不想这么麻烦,你可以自己买老键盘,最好2010之前的也可以买罗技k120这个型号的我就是这个试着没问题

还有我把main.c的输出那几句删了避免显示重叠

 

今天还没完呢,我还得讲一下fifo,first in first out,这个东西是用来缓存数据的,我刚刚给你们的键盘输入是不是还行,但是这个有个问题就是你按键盘的时候pic完全为键盘+屏幕输出服务,比如你用pic搞计时器,计时器会受影响,屏幕输出要花时间的pic等不起,或许你看不出来但是这对pic影响很大,所以我们要先把数据保存下来然后慢慢的输出,这时候pic就只负责保存数据到内存,不要显示。

fifo.c

#include "include/head.h"

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf){
    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)
{
    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){
    int data;
    if (fifo->free == fifo->size) {
        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;
}

代码给你们直接用就是,我解释也解释不清,我乃cv工程师不需要知道原理

/*fifo.c*/
struct FIFO8 {
    unsigned char *buf;
    int p, q, size, free, flags;
};
#define FLAGS_OVERRUN    0x0001
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);

这个添加到head.h里面去都是fifo要用的

/*naskfunc.asm*/
void io_stihlt();
void io_hlt(void);
void io_cli(void);
void io_sti(void);
int io_get8(int port);
void io_set8(int port, int data);
void write_mem8(int addr, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);

void asm_inthandler21(void);

/* asmhead.nas */
struct BOOTINFO { /* 0x0ff0-0x0fff */
    char cyls; /* 启动区读磁盘读到此为止 */
    char leds; /* 启动时键盘的LED的状态 */
    char vmode; /* 显卡模式为多少位彩色 */
    char reserve;
    short scrnx, scrny; /* 画面分辨率 */
    char *vram;
};
#define ADR_BOOTINFO 0x00000ff0

/*graphic.c*/
void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);

/*font*/
extern char font[4096];

/* dsctbl.c */
struct SEGMENT_DESCRIPTOR {
    short limit_low, base_low;
    char base_mid, access_right;
    char limit_high, base_high;
};
struct GATE_DESCRIPTOR {
    short offset_low, selector;
    char dw_count, access_right;
    short offset_high;
};
void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
#define ADR_IDT            0x0026f800
#define LIMIT_IDT        0x000007ff
#define ADR_GDT            0x00270000
#define LIMIT_GDT        0x0000ffff
#define ADR_BOTPAK        0x00280000
#define LIMIT_BOTPAK    0x0007ffff
#define AR_DATA32_RW    0x4092
#define AR_CODE32_ER    0x409a
#define AR_INTGATE32    0x008e

/* pic.c */
void init_pic(void);
#define PIC0_ICW1        0x0020
#define PIC0_OCW2        0x0020
#define PIC0_IMR        0x0021
#define PIC0_ICW2        0x0021
#define PIC0_ICW3        0x0021
#define PIC0_ICW4        0x0021
#define PIC1_ICW1        0x00a0
#define PIC1_OCW2        0x00a0
#define PIC1_IMR        0x00a1
#define PIC1_ICW2        0x00a1
#define PIC1_ICW3        0x00a1
#define PIC1_ICW4        0x00a1

/*interrupt.c*/
#define PORT_KEYDAT 0x0060

void inthandler21(int *esp);

/*fifo.c*/
struct FIFO8 {
    unsigned char *buf;
    int p, q, size, free, flags;
};
#define FLAGS_OVERRUN    0x0001
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);

加粗你懂吧,都是新加的,上面单独这句也要,之前说了,是键盘接收数据的地址

修改interrupt.c

#include "include/head.h"

struct FIFO8 keyfifo;

void inthandler21(int *esp)
/* 来自PS/2键盘的中断 */
{
    unsigned char data;
    io_set8(PIC0_OCW2, 0x61); /* 通知PIC,说IRQ-01的受理已经完成 */
    data = io_get8(PORT_KEYDAT);
    fifo8_put(&keyfifo, data);
    return;
}

就是保存数据了,fifo还要初始化,我们在main里面初始化,在main的死循环里面读取

main.c

#include "include/head.h"
#include <string.h>

struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
extern struct FIFO8 keyfifo;

void Main(void){
    int i;char s[256];
    char keybuf[256];

    init_gdtidt();
    init_pic();
    io_sti();
    fifo8_init(&keyfifo, 32, keybuf);

    init_palette();
    io_set8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */

    for (;;) {
        io_hlt();
        if (fifo8_status(&keyfifo)== 0) {
            io_stihlt();
        } else {
            int i = fifo8_get(&keyfifo);
            io_sti();    
            if(i<129)
            {
                boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
                sprintf(s, "key = %d", i);
                putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);
            }else{
                boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
                sprintf(s, "key = -");
                putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);
            }
            
        }
    }
}

加粗懂我意思吧,最后修改Makefile就可以编译运行了

 运行:

cd class05
..\z_tools\make.exe run

 

 

 
自制操作系统合集
原文地址:https://www.cnblogs.com/Frank-dev-blog/category/2249116.html
项目github地址rick521/My-OS (github.com)给我点颗star

 

posted @ 2023-02-27 20:39  Z_Chan  阅读(108)  评论(0编辑  收藏  举报