简介

上节实现了时钟定时器功能,但是系统的时钟定时器只有一个,电脑中有多处需要用到定时器的功能,但是硬件只有一个。要实现多个定时器的功能我们需要使用软件模拟硬件的功能。

目标

使用软件模拟多个时钟定时器的功能,让硬件定时器每隔一小段时间中断一次,在终端处理函数中依次判断添加的定时器实现多定时器功能。

1.timer.h

#ifndef  TIMER_H
#define TIMER_H#include "global_def.h"#define MAX_TIMER  512//定义定时器状态
#define TIMER_FALG_FREE  0  //定时器未使用
#define TIMER_FALG_ALLOC 1  //定时器被分配
#define TIMER_FALG_USING 2  //定时器使用中typedef struct _TIMER {unsigned int timeout, flag;FIFO8 *fifo;unsigned char data;
}TIMER;//定义时钟管理器
typedef struct _TIMERCTL {unsigned int count;       //记录中断次数int size;               //能容纳的定时器总个数TIMER timers[MAX_TIMER];
}TIMERCTL;//初始化始终控制器
void init_timerCtl(TIMERCTL *timctl);TIMER* timer_alloc(TIMERCTL *timctl);void timer_free(TIMER *timer);void timer_init(TIMER *timer,FIFO8 *fifo, unsigned char data);void timer_setTimeout(TIMER *timer, unsigned int timeout);#endif

2.timer.c

#include "timer.h"
#include "io.h"#define PIT_CTRL   0x43
#define PIT_CNT0   0x40//向8259A芯片的对应端口发送指定数据,首先需要向端口0x43发送一个数值0x34,
//紧接着向端口0x40发送两个数据0x9c,0x2d, 这样时钟中断就能在1秒内发生100次了
void init_timerCtl(TIMERCTL *timctl){io_out8(PIT_CTRL, 0x34);io_out8(PIT_CNT0, 0x9c);io_out8(PIT_CNT0, 0x2e);timctl->count = 0;timctl->size = MAX_TIMER;for(int i=0;i<MAX_TIMER;i++){timctl->timers[i].flag = TIMER_FALG_FREE;}
}TIMER* timer_alloc(TIMERCTL *timctl){TIMER *tim = (TIMER *)0;for(int i=0;i<MAX_TIMER;i++){if(timctl->timers[i].flag == TIMER_FALG_FREE){timctl->timers[i].flag = TIMER_FALG_ALLOC;tim = &timctl->timers[i];return tim;}}return tim;
}void timer_free(TIMER *timer){timer->flag = TIMER_FALG_FREE;}void timer_init(TIMER *timer,FIFO8 *fifo, unsigned char data){timer->fifo = fifo;timer->data = data;}void timer_setTimeout(TIMER *timer, unsigned int timeout){timer->timeout = timeout;timer->flag = TIMER_FALG_USING;
}

3.os.c
init_main 函数关于时钟中断修改为

//初始化时钟中断,初始化后每隔10毫秒发送一次中断,中断超时后将把一个数据送入时钟FIFO8队列中init_timerCtl(&_timctl);

int_timer函数模拟多时钟中断

//定时器中断
void int_timer(){io_out8(0x20, 0x60);_timctl.count++;for(int i=0;i<_timctl.size;i++){if(_timctl.timers[i].flag == TIMER_FALG_USING){_timctl.timers[i].timeout -= 10;if(_timctl.timers[i].timeout <= 0){_timctl.timers[i].flag = TIMER_FALG_ALLOC;fifo8_put(_timctl.timers[i].fifo,_timctl.timers[i].data);}}}
}

runloop 函数实现2个定时器输出

static void runloop(){AddrRangeDes *memDes = (AddrRangeDes *)mem_block_buf();int memCount = mem_block_count();int memId = -1;int index = 0;//如果变量是没有用static 修饰,变量分配在栈上则定时器不会正常工作;//原因估计是因为段寄存器中ss 和 ds 不一样static FIFO8 fifo1;static char buf1[8];fifo8_init(&fifo1,8,buf1);TIMER *t1 = timer_alloc(&_timctl);timer_init(t1,&fifo1,1);timer_setTimeout(t1,2000);static FIFO8 fifo2;static char buf2[8];fifo8_init(&fifo2,8,buf2);TIMER *t2 = timer_alloc(&_timctl);timer_init(t2,&fifo2,0x12);timer_setTimeout(t2,3000);for(; ;){if(_keybufInfo.len>0){io_cli();int len = _keybufInfo.len;for(int t=0;t<len;t++){char data = fifo8_get(&_keybufInfo);if(data == 0x1c){memId++;if(memId==memCount){memId=0;}showMemInfo(memDes+memId,memId);}}io_sti();}else if(_mousebufInfo.len>0){io_cli();int len = _mousebufInfo.len;mouseCursorMoved(&_mouseDes,COLOR_INVISIBLE);io_sti();}else if(fifo1.len>0){int data = fifo8_get(&fifo1);int len = 0;_tempArr[len++] = '0';_tempArr[len++] = 'x';for(int j=0;j<4;j++){int temp = char2HexStr(((char *)&data)[3-j]);_tempArr[len++] = ((char *)&temp)[0];_tempArr[len++] = ((char *)&temp)[1];}_tempArr[len] = 0;showString(_shtctl,_shtMsg,10,44,COL8_FFFFFF,COL8_C6C6C6,_tempArr);}else if(fifo2.len>0){int data = fifo8_get(&fifo2);int len = 0;_tempArr[len++] = '0';_tempArr[len++] = 'x';for(int j=0;j<4;j++){int temp = char2HexStr(((char *)&data)[3-j]);_tempArr[len++] = ((char *)&temp)[0];_tempArr[len++] = ((char *)&temp)[1];}_tempArr[len] = 0;showString(_shtctl,_shtMsg,10,60,COL8_FFFFFF,COL8_C6C6C6,_tempArr);}}
}

4.修改boot.s 加载更多的内核代码

cmp ch,2

5.修改main.c 写入更多数据

#include<stdio.h>
#include<stdlib.h>
#include<string.h>#include "floppy.h"int main(int argc,char **argv){FILE *fp = initFloppy("floppy.img");if(fp == NULL) {printf("初始化磁盘失败");exit(0);}FILE *src = fopen("boot.bat", "r");if(src == NULL) {printf("文件打开失败:%s\n","boot.bat");exit(0);}char buf[512];memset(buf, 0, 512);fread(buf, 512, 1, src);buf[510] = 0x55;buf[511] = 0xaa;writeFloppy(0, 0, 1, fp, buf);fclose(src);src = fopen("kernel.bat", "r");if(src == NULL) {printf("文件打开失败:%s\n","kernel.bat");exit(0);}//可正确处理18个扇区的数据内容int c = 1,h = 0,s = 1;int count = 0;int size = 18*2*2;for(int i=0;!feof(src) && i < size;i++){memset(buf, 0, 512);fread(buf, 512, 1, src);writeFloppy(c, h,s, fp, buf);count += 1;s++;if(s==19){h++;s = 1;}if(h==2){h = 0;c++;}   }fseek(src,0,SEEK_END);long len = ftell(src);if(len > size*512){printf("kernel.bat 文件长度%ldB,超过写入界限!!!\n",len);}else{printf("读取了%dx512=%dB,floppy.img软盘文件制作成功\n",count,count*512);}fclose(src);fclose(fp);return 1;
}

6.虚拟机加载floppy.img 文件,在消息框中先显示出一个字符串后将过一小段时间后再显示另一个字符串,最终效果如下图:

总结

计算机中受硬件的限制通常是不能实现对硬件资源的独占,需要使用软件的方式模拟多个硬件的功能,计算机的速度非常的快,在使用软件模拟硬件功能时可以非常方便的对计算机资源的管理!

24.模拟多时钟定时器相关推荐

  1. 数码管在c语言中显示时间,如何利用单片机数码管程序模拟是时钟显示时间?...

    数码管是一种半导体发光器件,其基本单元是发光二极管.数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元,也就是多一个小数点(DP)这个小数点可以更精确的表示数码管想要 ...

  2. jquery模拟LCD 时钟

    查看效果网址:http://keleyi.com/keleyi/phtml/jqtexiao/24.htm 以下是HTML文件源代码: 1 <!DOCTYPE html PUBLIC " ...

  3. 模拟数字时钟走字60次

    任务描述 本关任务:本题中已给出一个时钟类的定义,请模拟数字时钟走字过程. 相关知识 为了完成本关任务,你需要掌握:1.类和对象. 编程要求 根据提示,在右侧编辑器补充代码,模拟数字时钟走字,只需输出 ...

  4. Unity时钟定时器插件

    Unity时钟定时器插件 http://dsqiu.iteye.com/blog/2020603 https://github.com/joserocha3/KillerCircles/blob/67 ...

  5. 【笔记】STM32F4xx 时钟定时器

    第五部分 时钟定时器 一.时钟 1. 时钟是什么? T: 时钟周期,最小重复的信号单元的时间长度. f: 频率Hz 单位时间内(电平)完成周期性变化的次数 2. 为什么需要时钟呢? 同步信号:大部分时 ...

  6. 模拟数字时钟,python代码

    这是一个使用 Python 创建模拟数字时钟的示例代码: importtime import oswhile True:# 获取当前时间current_time = time.strftime(&qu ...

  7. 硬核!用Arduino打造纯机械装置模拟数字时钟

    本文转载自程序员极客实验室 本项目是一个真正意义上的「机械时钟」,由 3D 打印部件.25 个 Arduino Nano 和 48 个步进电机构建.每个时钟面都是用 Eagle 设计的 PCB. 时钟 ...

  8. Arduino提高篇24—摇杆调节时钟时间

    对于电子时钟而言,虽然我们可以在程序中对RTC芯片写入初始时间数据,但按键调时功能也是必不可少的,它可以让我们更加灵活的进行时间调节校准.本篇我们使用摇杆按键来调节时间数据,采用多级菜单的思路进行设计 ...

  9. 使用硬件定时器软模拟多个定时器(8.15改进版)

    在嵌入式平台中,界面有许多的数据需要定时刷新,而硬件资源不可能提供大量的定时器. 在没有上系统的情况下,使用该方法模拟定时器是不错的方法.如果非裸奔大可不必如此麻烦. 该方法可单独使用也可以结合GUI ...

最新文章

  1. C语言截取指定长度子字符串方法
  2. Hadoop HA 机制学习:HA是怎么运作,QJM又是怎么发挥功效的
  3. SD-WAN如何简化企业网络并节省资金
  4. 解决h5py\_init_.py:26:FutureWarning: Conversion of the second argument of issubdtype from `float`^……
  5. elementUI响应式布局@media:基于断点的隐藏类
  6. Python中的@property Decorator:其用例,优点和语法
  7. 【架构师】【数据库基础】【笔记 01】快速了解数据库系统的重要概念01
  8. oracle 表(下)
  9. WeixinJSBridge API使用实例
  10. 邮件服务器突然很慢,原因探究与处理
  11. 应聘的16个经典面试问题回答思路
  12. PowerDesigner显示Comment注释
  13. QQ能上网,浏览器打不开网页,怎么办?
  14. sqlitedeveloper数据库管理(SQLite Developer) v4.0.0.528 中文破解版
  15. (一)SDN基本架构
  16. Flutter 启动外部浏览器
  17. 泰拉瑞亚手机版html,泰拉瑞亚提基套装怎么得 提基套装属性详解
  18. 微信小程序接口调用渲染
  19. python的函数式编程实例_函数式编程例子
  20. 路由器接口及连接(1)

热门文章

  1. 软考成绩一般几天出来?快速了解出成绩时间!
  2. linux挂载华为存储设备,Centos 6.5挂载华为赛门铁克存储(Oceanspace S6800E存储系统)...
  3. 基于功能安全的车载计算平台开发:硬件层面
  4. WEB前端浏览器兼容问题处理
  5. 解决浏览器页面缩放前端页面大小自适应改变的问题
  6. らぶデス海茶3去码补丁.
  7. 磁盘与文件系统管理之四:挂载文件系统
  8. 已解决[notice] A new release of pip available: 22.2 -> 22.2.2
  9. 基于FPGA Uart串口通信实验
  10. 华章培训 Android实战就业