关于C/C++中使用中断(转载)

原文链接地址http://newkedison.blog.163.com/blog/static/369822582007917119442/

 

什么是中断

---------------------------------------------

中断是CPU处理外部突发事件的一个重要技术。它能使CPU在运行过程中对外部事件发出的中断请求及时地进行处理,处理完成后又立即返回断点,继续进行CPU原来的工作。引起中断的原因或者说发出中断请求的来源叫做中断源。 根据中断源的不同,可以把中断分为硬件中断和软件中断两大类,而硬件中断又可以分为外部中断和内部中断两类。

CPU为了处理并发的中断请求,规定了中断的优先权。中断优先权由高到低的顺序是:

  1. 除法错、溢出中断、软件中断
  2. 不可屏蔽中断
  3. 可屏蔽中断
  4. 单步中断。

---------------------------------------------

我个人理解就是象函数调用一样,CPU运行运行着,突然调用了一个函数,这个函数处理完之后,由返回下面的程序继续执行,至于为什么会突然调用了一个程序,那就是中断的原因了。而调用的这个函数,就就叫中断函数。

然后来看几个C语言控制中断函数的函数

void interrupt (*getvect(int interruptno))();

这个函数的结构我可是研究了半天才研究出来的

1、这是个函数,名字叫getvect,输入参数是interruptno,输出参数是一个中断函数指针

2、interruptno是个中断地址(比如时钟中断地址是0x1c)

3、每个中断都会调用一个中断函数(不然叫什么中断)

4、这个函数的作用就是把指定的中断调用的函数的指针作为返回值返回,这样就可以保存这个函数,以便以后恢复。
void setvect(int interruptno, void interrupt (*isr) (...);

理解了上面的那个函数,这个就简单了

1、函数名setvect,输入参数,一个中断地址,一个中断函数指针,输出参数,无

2、这个函数的功能是把指定中断的中断函数设置为第二个输入参数指定的函数,也就是更改这个中断调用的中断函数。

3、函数的用处有两个,一个是把原来默认的中断函数改成我们自己写的函数,另一个是恢复默认的中断函数(为什么能恢复呢?因为每次更改中断函数的时候,都必须先用那个getvect把原来的中断函数保存下来,只要把保存下来的函数恢复回去就行)

搞定了这两个函数,中断函数就不再神秘了,下面看个实例

目标是调用时间中断,每秒输出一个数,10秒后结束

/*	
	下面这段英文不大明白是什么意思
	This is an interrupt service routine. You can NOT compile this
	program with Test Stack Overflow turned on and get an executable
	file which will operate correctly. 
*/

/*	
	这个程序每隔1秒钟输出一个整数,10秒钟后结束程序。
	按escape键提前退出程序 。
*/

#include <stdio.h>
#include <dos.h>
#include <conio.h>

/* ESC的按键码 */
#define VK_ESC 0x11b 

#define TIMER 0x1c		// 时钟中断的中断号,也就是上面说的中断地址

/* 	
	中断处理函数在C和C++中的表示略有不同。
	如果定义了_cplusplus则表示在C++环境下,否则是在C环境下。
	可能是因为C++的函数必须加三个点,所以要这么干,至于为什么要加三个点就不大清楚了 
*/

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

int TimerCounter=0;	// 计时变量,每秒钟增加18。解释一下,其实是平均每秒发生18.2次时钟中断,所以累计到18次也就大概是1秒了

// 指向原来时钟中断处理过程入口的中断处理函数指针(句柄)
void interrupt ( *oldhandler)(__CPPARGS);

/*
	1、这是个变量,名字叫oldhandler,类型是一个指向中断函数的指针
	2、只要知道这是个函数指针,就好理解了,后面括号里面的是参数,如果是c,就留空,如果是C++,就写三个点,目前还不知道原因。
	3、这个变量的作用就是用来保存原来的中断函数地址,以便后来的恢复
*/

// 新的时钟中断处理函数
void interrupt newhandler(__CPPARGS)
{
	// increase the global counter
	TimerCounter++;	//累计看多少次进入了这个中断函数

	/* 	
		call the old routine 调用原来的中断函数,因为原来的中断函数也是要完成一些事情的,
		如果因为我们改变了中断函数的位置而导致原来的中断函数无法执行,那系统可能就出问题了,
		就这个程序来说,就是会导致计时错误。
	*/
	oldhandler();
}

// 设置新的时钟中断处理过程
void SetTimer(void interrupt (*IntProc)(__CPPARGS))	//输入参数就是一个中断函数的指针
{
	oldhandler=getvect(TIMER);	//获得原来时钟中断所调用的中断函数,赋值给oldhandler,这样原来的中断函数地址就保存下来了
	disable(); 		// 设置新的时钟中断处理过程时,禁止所有中断
	setvect(TIMER,IntProc);	//设置时间中断的中断函数为我们自己设置的函数
	enable(); 		// 开启中断
}

// 恢复原有的时钟中断处理过程
void KillTimer()
{
	disable();
	/*	
		把保存在oldhandler里面的原来中断函数的地址恢复,这个步骤绝对不能少,不然等我们程序运行完了,
		上面我们自己定义的函数就不见了,那时钟中断就找不到地方可以执行中断函数了,会出什么问题我不敢试,但是肯定会出问题
	*/
	setvect(TIMER,oldhandler);
	enable();
}


void main(void)
{
	int key,time=0;
	SetTimer(newhandler);	// 修改时钟中断

	for (;;)
	{
		if (bioskey(1))		// 这个表示按了键盘上的某个键,因为与本文无关,具体用法请自行百度之
		{
			key=bioskey(0);	// 取得按键码
			if (key==VK_ESC)	// 按escape键提前退出程序
			{
				printf("User cancel!\n");
				break;
			}
		}
		if (TimerCounter>18)	// 1秒钟处理一次
		{
			// 恢复计时变量
			TimerCounter=0;
			time++;
			printf("%d\n",time);
			if (time==10)	// 10秒钟后结束程序
			{
				printf("Program terminated normally!\n";
				break;
			}
		}
	}
	KillTimer();	// 恢复时钟中断
}
 

 程序结束。

通过这个实例,可以很清楚的表示使用中断函数所必须的几个步骤

1、用一个变量保存原来的中断函数

2、设置一个新的中断函数,这个中断函数要调用默认的中断函数

3、更改中断的中断函数,改为我们自己写的中断函数

4、程序结束后,记得恢复中断函数为默认的中断函数

我记得以前还看过说,我们自己定义的中断函数不要有太多太复杂的操作,我觉得也是应该这样的,不然出了问题就麻烦大了。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在虚拟机配置VSCode的C/C++环境可以让你在虚拟机进行C/C++的开发工作。以下是配置步骤: 1. 安装VSCode:首先,在虚拟机下载并安装Visual Studio Code。你可以从VSCode官方网站上下载适用于你的操作系统的安装包。 2. 安装C/C++扩展:打开VSCode,点击左侧的扩展图标(或按下Ctrl+Shift+X),在搜索框输入"C/C++",找到并安装Microsoft的C/C++扩展。 3. 安装编译器:在虚拟机,你需要安装一个C/C++编译器。常用的编译器有GCC和Clang。你可以使用包管理器(如apt-get、yum等)来安装编译器。 4. 配置编译器路径:打开VSCode,点击左下角的设置图标(或按下Ctrl+,),在搜索框输入"C/C++",找到"C/C++: Edit Configurations (UI)"选项,点击进入编辑配置界面。在"Compiler path"字段填入你安装的编译器的路径。 5. 创建C/C++项目:在VSCode,点击左侧的资源管理器图标(或按下Ctrl+Shift+E),右键点击一个文件夹,选择"New Folder"来创建一个新的文件夹作为你的项目目录。然后,点击左侧的源代码管理图标(或按下Ctrl+Shift+G),选择"Initialize Repository"来初始化一个Git仓库。 6. 编写C/C++代码:在项目目录创建一个新的C/C++源文件(如hello.c),在文件编写你的C/C++代码。 7. 编译和运行代码:在VSCode,点击左侧的调试图标(或按下Ctrl+Shift+D),点击顶部的绿色箭头按钮来编译和运行你的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值