IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 《30天自制操作系统》笔记 ---Day7 -> 正文阅读

[嵌入式]《30天自制操作系统》笔记 ---Day7

1.获取按键编码

鼠标与键盘在代码实现上相差不大,所以我们只要完成其中一个就可以仿制出另一个。
因为之前按一个键后,其余什么也做不了。
修改init.c中inthandler21函数

#define PORT_KEYDAT 0x0060//该设备号由IBM规定,具体可以参考http://community.osdev.info/?(AT)keyboard
void inthandler21(int *esp)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	unsigned char data, s[4];
	io_out8(PIC0_OCW2, 0x61); /* 通知PIC"IRQ-01已经受理完毕" 如果是IRQ3,则写成0x63。
也就是说,将“0x60+IRQ号码”输出给OCW2就可以执行这句话之后,PIC继续时刻监视IRQ1中断是否发生*/
	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);
	return;
}

2.加快中断处理

上文程序的缺点是字符显示的内容被放在中断处理程序中。如果处理键盘的中断速度太慢,就会出现鼠标的运动不连贯,不能从网上接受数据等。所以我们可以先将按键编码保存到变量,然后由main函数偶尔去检查这个变量,有就显示。
所以修改之前的函数如下:

struct KEYBUF {
	unsigned char data, flag;/*flag变量来表示缓冲区是否为空*/
};
#define PORT_KEYDAT 0x0060
struct 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) {
	keybuf.data = data;
	keybuf.flag = 1;
}
return;
}

对于main函数:

for (;;) {
	io_cli();//先屏蔽中断
	if (keybuf.flag == 0) {
	io_stihlt();//执行STI和HLT,不能分开写io_sti();io_hlt();克服俩条指令间的中断
} 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);
}
}

3.制作FIFO缓冲区

前者写出的程序只能存储一个字节,下面准备做一个存储多字节的缓冲区,这样不会马上存满。
最简单的就是在KEYBUF结构体里增加data变量(后果是程序变得冗长)

//法一:
struct KEYBUF {
unsigned char data1, data2, data3, data4, ...
};
//法二:
struct KEYBUF {
unsigned char data[4];
};
//制作FIFO缓冲区改进后:
struct KEYBUF {
unsigned char data[32];
int next;
};
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01已经受理完毕 */
data = io_in8(PORT_KEYDAT);
if (keybuf.next < 32) {
keybuf.data[keybuf.next] = data;
keybuf.next++;
}
return;
}

4.改善FIFO缓冲区

此节的目标是开发一个不需要数据移送操作的FIFO型缓冲区。大致流程就是一边读一边写,当读出与写入一致,说明缓冲区为空,当到数据末尾,则置零,重头开始。

//修改KEYBUF
struct KEYBUF {
	unsigned char data[32];
	int next_r, next_w, len;
};
void inthandler21(int *esp)
{
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61); /* 通知 IRQ-01已经受理完毕 */
	data = io_in8(PORT_KEYDAT);
	if (keybuf.len < 32) {
		keybuf.data[keybuf.next_w] = data;
		keybuf.len++;
		keybuf.next_w++;
		if (keybuf.next_w == 32) {
			keybuf.next_w = 0;
			}
	}
	return;
}
//取数据
for (;;) {
io_cli();
if (keybuf.len == 0) {
io_stihlt();
} else {
i = keybuf.data[keybuf.next_r];
keybuf.len--;
keybuf.next_r++;
if (keybuf.next_r == 32) {
keybuf.next_r = 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);
}
}

5.整理FIFO缓冲区

由于鼠标每次移动会连续发送3个字节数据。现在将缓冲区定义成(字节数)可变的。

struct FIFO8 {
	unsigned char *buf;//存放缓冲区地址
	int p, q, size, free, flags;
	//p:下一个数据写入地址(next_w)
	//q:下一个数据读出地址(next+r)
	//size:保存总字数大小
	//free:保存缓冲区没有数据的字节数
};
/*************FIFO*********************/
/*******初始化FIFO缓冲区***************/
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;
}
/**向FIFO缓冲区存储1字节信息函数*******/
#define FLAGS_OVERRUN 0x0001
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;//没有溢出
}
/**向FIFO缓冲区取得1字节信息函数*******/
int fifo8_get(struct FIFO8 *fifo)
{
	int data;
	if (fifo->free == fifo->size) {
		return -1;/* 如果缓冲区为空,则返回 -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;
}

6.总算讲到鼠标了

鼠标中断号:IRQ12
要让鼠标中断有效需要实现下面俩个装置有效:
①鼠标控制电路有效
②鼠标本身有效

#define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE 0xf4
void 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)*/
}

7.从鼠标接收数据

中断做好,下面就从中断中取出数据。(可以类比键盘)

struct FIFO8 mousefifo;
void inthandler2c(int *esp)
/* 来自PS/2鼠标的中断 */
{
	unsigned char data;
	io_out8(PIC1_OCW2, 0x64); /* (从)通知PIC1 IRQ-12的受理已经完成 */
	io_out8(PIC0_OCW2, 0x62); /* (主)通知PIC0 IRQ-02的受理已经完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&mousefifo, data);
	return;
}
/************************/
fifo8_init(&mousefifo, 128, mousebuf);
for (;;) {
	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);
		}
	}
}

ok,今天就完成了键盘与鼠标的终端操作,明天继续呼呼。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:05:27  更:2022-01-30 19:05:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:30:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码