一、准备工作
(一)硬件设置
计算机中鼠标的中断硬件组成,在前面的章节已经做了介绍:
从图中可以明显看到,鼠标是接在从片的4号端口上的,而从片又是接在主片的2号端口上的,因此我们第一步就是需要打开这两个端口的中断:
io_out8(PIC0_IMR, 0xf9); /* 开启键盘和鼠标中断主芯片设置:(11111001) */
io_out8(PIC1_IMR, 0xef); /* 从芯片设置:(11101111) */
之前,我们对键盘和鼠标中断号已经做了定义,分别是0X21和0X2C。那我们鼠标驱动的主要任务其实就是编写0X2C号中断的中断服务程序。另外,我们需要将中断号0X2C的中断服务程序注册到IDT表中,这个方法和键盘中断没有差异。
鼠标电路硬件上其实是从属于键盘电路的,因此我们还需要从硬件上做两个事情:
1.启用鼠标电路,程序中用init_keyboard()函数实现。
2.启动鼠标设备,程序中用 enable_mouse(&mdec)函数实现。
(二)鼠标数据接收
鼠标与CPU数据交互上和键盘不相同,因为鼠标的数据量远远大于键盘,键盘无非就是一个按键和释放,而鼠标有5种数据:点击左键、点击右键、滑动中间键、X坐标位移和Y坐标位移。所以鼠标和CPU是采用一种异步通信的方式:一次鼠标操作分3次握手完成传递,每次传递一个字节,第1个字节表示的是鼠标点击数据、第2个字节和第3个字节表示的是X坐标位移和Y坐标位移。那么第1个字节就很关键,它的定义是最低3位分别表示点击左中右键。我们需要在中断服务程序里用逻辑来区分这3个阶段,以保证能收到的数据不乱序。方法一般是:首先判断鼠标送来的数据知否在正常范围内来判断是否是第一个字节,因为超出合理范围就肯定不是第一字节。具体方法这个可以看书上的教程:
二、运行效果
三、程序代码
1.Main.c
void Main(void)
{
sysinit(); /*操作系统运行准备*/
intservice(); /*外设中断服务准备(键盘鼠标)*/
desktop(); /*桌面显示*/
while(1)
{
;
}
}
2.Desktop.c
关键点:
(1)struct BOOTINFO *binfo:这个数据结构是整个操作系统的基础信息,其作用就是从内存固定物理地址0x7000处开始读出分辨率、键盘按键状态、显卡内存地址等在前面汇编程序部分写进去的基础信息。
#define BOOTBASE 0x7000
struct BOOTINFO {
char cyls, leds, vmode, reserve;
short scrnx, scrny;
char *vram;
int asmlen;
};
(2)extern struct FIFO8 keyfifo; extern struct FIFO8 mousefifo; keyfifo和mousefifo分别为32字节的键盘数据输入缓冲区和128字节的鼠标数据输入缓冲区。必须用关键词extern来定义变量,是因为这两个缓冲区是在Keryboard.c和Mouse.c中定义的,那么这里引用的作用显然是只管从缓冲区读出数据!FIFO8实际上只是一个缓冲区的信息描述符,它用来指向真正的数据缓冲区并做读写控制,真正的数据缓冲区是存放在char keybuf[32],mousebuf[128]这两个数组里面的。
(3)专门定义了一个数据结构struct MOUSE_DEC mdec,用来解析和存储鼠标每次送来的3个字节数据。
#include "Jiangos.h"
#include <stdio.h>
void desktop(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) BOOTBASE;
init_palette();
init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
static char c=7;
/*---显示字符串---*/
putfont_Jiang(binfo->vram,binfo->scrnx, 10,10, COL8_FFFFFF);
putfonts8_asc(binfo->vram, binfo->scrnx,10,40, COL8_FFFFFF, "Jiang OS 13572468");
line(binfo->vram,binfo->scrnx,60,c);
/*---显示变量---*/
char s[40];
sprintf(s, "VRAMX=%d", binfo->scrnx);
putfonts8_asc(binfo->vram, binfo->scrnx, 16, 64, COL8_FFFFFF, s);
sprintf(s, "VRAMY=%d", binfo->scrny);
putfonts8_asc(binfo->vram, binfo->scrnx, 100, 64, COL8_FFFFFF, s);
sprintf(s, "VRAMAddr=0X %X", binfo->vram);
putfonts8_asc(binfo->vram, binfo->scrnx, 184, 64, COL