单片机中断服务函数写法

合集下载

几种单片机的中断函数写法

几种单片机的中断函数写法

几种单片机的中断函数写法写单片机程序,中断是免不了的。

我比较喜欢用C写单片机程序,简单而且可读性高,当然程序效率没有汇编的高。

目前写过51单片机跟AVR单片机的C程序,最近在看MSP430的书。

用C写不同的单片机程序其实都是大同小异,因此能对不熟悉的单片机也能很快上手写程序。

不过中断函数的写法,各个编译器往往都会有些差别。

最早写的C程序是51单片机的,用的编译器自然是大名鼎鼎的keil c了。

Keil的功能还是非常强劲的,不仅能编译,还有软件仿真调试与硬件调试的功能。

由于条件简陋,没用过什么仿真器,一直都是靠软件仿真调试程序的。

Keil 中的中断函数一般格式如下:void 函数名() interrupt n using n{…….}其中函数名可以任意取,关键字interrupt用来指明这是一个中断服务函数,后面的n 表示中断号,关键字using加后面的n表示使用哪一组寄存器。

后然接触到AVR的单片机,该单片机开发环境一般用ICC或者是GCC。

由于ICC是商用软件,而GCC是免费的,因此我一般用GCC来写AVR的C程序。

现在版本的GCC for AVR有了一些改进,对于中断函数支持两种关键字ISR与SIGNAL,其格式如下:ISR(vect){………}与SIGNAL(vect){……..}其中的vect就是中断向量名,根据不同的型号的AVR单片机的不同的中断源都会有相对应的中断向量名,比如外部中断0对于ISR格式的中断向量名为INT0_vect,对SIGNAL则为SIG_INTERRUPT0。

最近在看TI的MSP430系列单片机的资料,看到该单片机采用C430写的中断服务函数有点像前两种的综合,其格式如下:interrupt [vect] void 函数名(void){…….}其中vect也是中断向量名,函数名可以任取。

比较这几种中断函数写法,本人更倾向于AVR的GCC的写法。

首先对于中断函数来说即不能有输入参数又没有返回值,没必要再给它加个“void 函数名(void)”的形式的函数。

C语言的中断服务函数

C语言的中断服务函数

C语言的中断服务函数中断服务函数是一种特殊的函数,用于处理系统或外设发生的中断事件。

在C语言中,中断服务函数常用于嵌入式系统的开发中,用于实现硬件的响应和处理。

下面是关于C语言中断服务函数的详细介绍,包括定义、注册、实现和应用等方面。

一、中断服务函数的定义中断服务函数(Interrupt Service Routine,ISR)是一段特殊的代码,用于响应和处理中断事件。

它与普通的函数不同,不是由程序主动调用的,而是由系统或硬件触发的。

中断事件一般包括硬件的输入、定时器的溢出、软件触发等。

在C语言中,中断服务函数的定义方式与普通的函数类似,但需要使用特殊的关键字和参数。

如下是一个C语言中断服务函数的定义示例:```void interrupt_service_functio//中断处理代码```在上述示例中,`void`表示中断服务函数不返回值,`interrupt_service_function`是函数的名称。

根据不同的开发平台和编译器,中断服务函数的定义可能有所不同。

二、中断服务函数的注册要使用一个中断服务函数,需要将其注册到相应的中断源中。

中断源可以是系统的中断控制器,也可以是外设的中断引脚。

注册中断服务函数的目的是告诉系统,在相应中断事件发生时调用该函数。

以8051单片机为例,注册中断服务函数的方式如下所示:```void mairegister_interrupt_service_function(interrupt_service_functi on);//其他代码```在上述示例中,`register_interrupt_service_function`是用于将中断服务函数`interrupt_service_function`注册到系统中断控制器的函数。

在实际开发中,不同平台和配置会有不同的注册方式。

三、中断服务函数的实现中断服务函数的实现主要包括对中断事件的处理和相应操作。

中断服务函数的实现需要了解特定硬件的中断机制和相关的寄存器操作。

中断函数的使用

中断函数的使用

中断函数的使用:《单片机C语言编程与实例》中断函数通过使用interrupt关键字和中断编号0-4来实现。

使用该扩展属性的函数声明语法如下:返回值函数名interrupt nN对应中断源的编号中断编号告诉编译器中断程序的入口地址,它对应者IE寄存器中的使能位,即IE寄存器中的0位对应着的外部中断0,相应的外部中断0的中断编号是0。

当正在执行一个特定任务是,可能有更紧急的事情需要CPU处理,这就涉及到终端优先级,搞优先级的中断可以中断正在处理的底有限级中断程序,因而最好给每种优先级分配不同的寄存器组。

在c51中可以使用using制定的寄存器组,using后的变量为0-3的长整数,分别表示51单片机内的四个寄存器组。

中断函数的完整语法及实例如下:返回值函数名(【参数】)【模式】【重入】interrupt n [using n] Unsigned int interruptent;Unsigned char second;V oid time0(void)interrupt 1 using 2{if(++interruptent==4000) %计数到4000{second++; % 另一个计数器Interruptent=0; %计数器清零}}要是摸个中断源的申请得到相应,必须保证EA=1和相应的允许位为1定义中断服务函数的一般形式为::函数类型函数名(形式参数表)[interrupt n][using n]Interrupt 后面的n是中断号,n的取值范围为0-31,编译器从8n+3处产生中断向量。

11.111111外部中断例题:通过P1.7口电量发光二极管,然后外部输入一脉冲串,则发光二极管亮、暗交替#include <REGX51.H>Sbit P1_7=P1^7;V oid tnterrupt0()interrupt 0 using 2//定义定时器0{ P1_7=!P1^7;}V oid main(){EA=1;//开启总中断IT0=1;//外部中断0低电平触发EX0=1; //外部中断0P1_7=0;Do()while(1);}2222相套中断外部中断INT1触发后,启动计数器0,计数达到10次后停止计数,启动定时器1,由定时器1控制定时,由P1.7输出周期为200ms的方波性能好,接受2次中断后关闭方波发生器,P1.7置低。

stm32中断函数和回调函数

stm32中断函数和回调函数

STM32的中断函数和回调函数是两种不同的函数类型,它们在嵌入式系统中有着广泛的应用。

1. 中断函数:
中断函数通常用于处理实时事件或外部信号。

当某个事件发生时,中断控制器会打断正在执行的程序,跳转到中断处理函数中执行相应的操作。

在STM32中,中断处理函数通常被定义为ISR (Interrupt Service Routine)。

ISR应该尽可能地简短快速,避免在中断处理函数中进行复杂的计算或逻辑处理。

中断函数的定义通常如下:
```c
void ISR() interrupt 1 // 1表示中断号
{
// 中断处理代码
}
```
其中,`interrupt`后面的数字表示中断号,用于区分不同的中断。

2. 回调函数:
回调函数是一种通用的事件处理机制。

它通常用于将某个函数作为参数传递给另一个函数,当事件发生时,调用传递的函数进行相应的处理。

回调函数通常被定义为一个指针类型,指向一个具有特定参数和返回值的函数。

回调函数的定义通常如下:
```c
typedef void (*Callback)(int event); // 定义回调函数类型
void function(Callback callback) // 传递回调函数作为参数{
// 执行一些操作
// 当事件发生时,调用callback函数进行处理
callback(event);
}
```
其中,`Callback`是一个指向函数的指针类型,`event`是传递给回调函数的参数。

在`function`函数中,可以调用传递的回调函数进行事件处理。

单片机C语言函数中断函数(中断服务程序)

单片机C语言函数中断函数(中断服务程序)

单片机_C‎语言函数_‎中断函数(中断服务程‎序)在开始写中‎断函数之前‎,我们来一起‎回顾一下,单片机的中‎断系统。

中断的意思‎(学习过微机‎原理与接口‎技术的同学‎,没学过单片‎机,也应该知道‎),我们在这里‎就不讲了,首先来回忆‎下中断系统‎涉及到哪些‎问题。

(1)中断源:中断请求信‎号的来源。

(8051有‎3个内部中‎断源T0,T1,串行口,2个外部中‎断源INT‎0,INT1(这两个低电‎平有效,上面的那个‎横杠不知道‎怎么加上去‎))(2)中断响应与‎返回:CPU采集‎到中断请求‎信号,怎样转向特‎定的中断服‎务子程序,并在执行完‎之后返回被‎中断程序继‎续执行。

期间涉及到‎C PU响应‎中断的条件‎,现场保护,现场恢复。

(3)优先级控制‎:中断优先级‎的控制就形‎成了中断嵌‎套(8051允‎许有两级的‎中断嵌套,优先权顺序‎为INT0‎,T0,INT1,T1,串行口),同一个优先‎级的中断,还存在优先‎权的高低。

优先级是可‎以编程的,而优先权是‎固定的。

80C51‎的原则是①同优先级,先响应高优‎先权②低优先级能‎被高优先级‎中断③正在进行的‎中断不能被‎同一级的中‎断请求或低‎优先级的中‎断请求中断‎。

80C51‎的中断系统‎涉及到的中‎断控制有中‎断请求,中断允许,中断优先级‎控制(1)3个内部中‎断源T0,T1,串行口,2个外部中‎断源INT‎0,INT1(2)中断控制寄‎存器:定时和外中‎断控制寄存‎器TCON‎(包括T0、T1,INT0、INT1),串行控制寄‎存器SCO‎N,中断允许寄‎存器IE,中断优先级‎寄存器IP‎具体的是什‎么,包括哪些标‎志位,在这里不讲‎了,所有书上面‎都会讲。

在这里我们‎讲下注意的‎事项(1)CPU响应‎中断后,TF0(T0中断标‎志位)和TF1由‎硬件自动清‎0。

(2)CPU响应‎中断后,在边沿触发‎方式下,IE0(外部中断I‎N T0请求‎标志位)和IE1由‎硬件自动清‎零;在电平触发‎方式下,不能自动清‎楚IE0和‎I E1。

c51中断函数的介绍

c51中断函数的介绍

c51中断函数的介绍C51编译器允许用c51创建中断服务程序,大家仅仅需要关心中断号和寄存器组的选择就可以了。

编译器自动产生中断向量和程序的入栈及出栈代码。

在函数声明时包括interrupt,将把所声明的函数定义为一个中断服务程序。

另外,可以用using定义此中断服务程序所使用的寄存器组。

一、中断函数的定义1、中断函数定义的格式为:函数类型函数名interrupt n using n其中:Interrupt后面的n是中断号。

关键字using后面的n是所选择的寄存器组,取值范围是0-3.定义中断函数时,using是一个选项,可以省略不用。

如果不用则由编译器选择一个寄存器组作为绝对寄存器组。

2、8051的中断过程通过使用interrupt关键字和中断号来实现,中断号告诉编译器中断程序的入口地址。

中断号对应着IE寄存器中的使能位,换句话说,IE 寄存器中的0位对应着外部中断0,相应的外部中断0的中断号是0.IE寄存器中的使能位与外部中断对应关系:中断号中断源0 外部中断01 定时器02 外部中断13 定时器1中断4 串行口中断5 定时器2中断二、使用中断函数时要注意的问题:1. 在设计中断时,要注意的是哪些功能应该放在中断程序中,哪些功能应该放在主程序中。

一般来说中断服务程序应该做最少量的工作,这样做有很多好处。

首先系统对中断的反应面更宽了,有些系统如果丢失中断或对中断反应太慢将产生十分严重的后果,这时有充足的时间等待中断是十分重要的。

其次它可使中断服务程序的结构简单,不容易出错。

中断程序中放入的东西越多,他们之间越容易起冲突。

简化中断服务程序意味着软件中将有更多的代码段,但可把这些都放入主程序中。

中断服务程序的设计对系统的成败有至关重要的作用,要仔细考虑各中断之间的关系和每个中断执行的时间,特别要注意那些对同一个数据进行操作的ISR.2. 中断函数不能传递参数。

3. 中断函数没有返回值。

4. 中断函数调用其他函数,则要保证使用相同的寄存器组,否则出错。

c2000中断程序代码

c2000中断程序代码

c2000中断程序代码C2000系列微控制器是德州仪器(TI)推出的一款高性能的32位微控制器,其中断服务程序是用来处理硬件中断的。

在C2000系列微控制器中,中断服务程序的编写一般包括以下几个步骤:1. 中断向量表设置,首先需要在程序的起始处设置中断向量表,将各个中断源对应的中断服务程序入口地址填入中断向量表中。

2. 中断服务程序编写,针对特定的中断源,编写相应的中断服务程序。

在C2000系列微控制器中,中断服务程序需要使用特定的关键字来声明,以确保编译器正确识别。

3. 中断使能,在初始化阶段,需要将特定的中断源使能,以确保当中断事件发生时,CPU能够响应并跳转到相应的中断服务程序执行。

4. 中断处理,在中断服务程序中,需要根据具体的中断源进行相应的处理,可能涉及到清除中断标志、读取相关寄存器状态、执行特定的操作等。

下面是一个简单的C2000中断服务程序的伪代码示例: c.#pragma CODE_SECTION(ISR, "ramfuncs");interrupt void ISR(void)。

{。

// 中断服务程序的具体内容。

// ...// 清除中断标志。

PieCtrlRegs.PIEACK.bit.ACK1 = 1;}。

void main(void)。

{。

// 初始化。

// ...// 使能中断。

PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // 使能中断源INT7。

// 启用全局中断。

EINT;// 主循环。

while(1)。

{。

// 主循环内容。

// ...}。

}。

在这个示例中,我们定义了一个名为ISR的中断服务程序,并使用#pragma CODE_SECTION将其放置在RAM中,以提高执行速度。

在main函数中,我们将INT7中断源使能,并在主循环中等待中断事件的发生。

需要注意的是,实际的中断服务程序的编写可能涉及到更多的细节,比如中断优先级设置、中断嵌套处理、中断向量表的具体设置等。

单片机编程中的常用函数

单片机编程中的常用函数

单片机编程中的常用函数在单片机编程中,常用函数是我们编写程序时经常使用到的函数。

这些函数不仅能够减少我们的工作量,还能提高程序的效率和可读性。

下面将介绍单片机编程中常用的几种函数。

一、延时函数延时函数是单片机编程中非常常用的函数之一,它可以在程序中引入适当的延时,以确保程序能够按照我们的期望进行运行。

延时函数通常使用定时器或者循环来实现。

下面是一个简单的延时函数示例:```cvoid delay(unsigned int ms){unsigned int i, j;for(i = 0; i < ms; i++)for(j = 0; j < 114; j++);}```在这个延时函数中,我们使用两个循环来进行延时操作。

内层循环是一个简单的计数器,当计数器达到一定值时,延时一毫秒。

外层循环控制延时的总时长。

通过调整内层循环的计数器初值,可以实现不同的延时时长。

二、IO口控制函数在单片机编程中,我们经常需要对IO口进行控制操作,例如点亮LED灯、控制继电器等。

为了简化这些操作,可以使用IO口控制函数。

下面是一个简单的IO口控制函数示例:```cvoid GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal){if(BitVal)GPIOx->ODR |= GPIO_Pin;elseGPIOx->ODR &= ~GPIO_Pin;}```这个函数接收三个参数,分别为GPIO端口、GPIO引脚和操作位的值。

通过判断操作位的值,可以实现对相应的GPIO引脚进行设置或清零操作,从而实现对IO口的控制。

三、定时器中断函数定时器中断函数是单片机编程中非常重要的函数之一,它可以在定时器溢出时触发相应的中断服务程序(ISR),从而实现定时任务。

下面是一个简单的定时器中断函数示例:```cvoid TIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){// 定时器中断处理代码TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清除中断标志位}}```在这个定时器中断函数中,我们首先判断定时器是否发生了溢出事件。

stm32 freertos 中断写法

stm32 freertos 中断写法

在STM32微控制器上使用FreeRTOS实时操作系统时,中断服务例程(ISR)的写法需要遵循一定的规范,以确保中断处理能够在不同的任务之间正确地进行。

以下是一些基本步骤和注意事项,用于在FreeRTOS中实现中断服务例程:1. **中断向量表初始化**:在系统启动时,需要初始化中断向量表,将中断处理函数的地址映射到相应的中断号上。

2. **中断优先级设置**:在FreeRTOS中,可以通过NVIC(嵌套向量中断控制器)设置中断的优先级。

在中断服务例程中,可以使用`HAL_NVIC_SetPriority`函数设置优先级。

3. **中断使能**:在中断服务例程编写完成后,需要使用`HAL_NVIC_EnableIRQ`或`HAL_NVIC_Enable`函数使能中断。

4. **中断服务例程的原型**:中断服务例程应该有一个原型,其中包含了中断号和中断服务例程的函数指针。

5. **在中断服务例程中保护现场**:在进入中断服务例程之前,应该保存CPU的状态,包括程序计数器和其他必要的寄存器,以防止中断服务例程被其他中断打断。

6. **中断服务例程的退出**:在中断服务例程结束时,应该恢复之前保存的状态,并使用`HAL_NVIC_DisableIRQ`或`HAL_NVIC_Disable`函数禁用中断。

7. **使用FreeRTOS的API**:如果需要在中断服务例程中使用FreeRTOS的API,比如创建任务、等待消息等,应该确保这些操作不会导致中断被禁止的时间过长,以免影响系统的响应性。

以下是一个简单的STM32中断服务例程的示例代码:```cvoid EXTI0_IRQHandler(void) {// 保存状态HAL_NVIC_DisableIRQ(EXTI0_IRQn); // 禁用中断// 中断处理逻辑// ...// 恢复状态HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 使能中断} ```。

t0中断服务函数的书写方法

t0中断服务函数的书写方法

t0中断服务函数的书写方法在嵌入式系统中,中断是一种非常重要的机制,它可以让CPU在执行程序的同时,及时响应外部事件的发生。

而t0中断是一种定时器中断,它可以周期性地触发中断服务函数的执行。

在本文中,我们将介绍t0中断服务函数的书写方法。

1. 中断服务函数的定义中断服务函数是一种特殊的函数,它的执行是由中断触发的。

在t0中断中,中断服务函数的名称通常为“t0_isr”,它的定义如下:void t0_isr(void) interrupt 1{// 中断服务函数的代码}其中,void表示该函数没有返回值,interrupt 1表示该函数是由中断1触发的。

在8051单片机中,t0中断的中断号为1。

2. 中断服务函数的功能t0中断服务函数的主要功能是处理定时器中断。

在t0中断中,定时器的计数器会溢出,当计数器溢出时,就会触发中断。

中断服务函数需要在中断发生时,及时处理定时器中断,并清除中断标志位,以便下一次中断的触发。

下面是一个简单的t0中断服务函数的例子:void t0_isr(void) interrupt 1{// 处理定时器中断// 清除中断标志位TF0 = 0;}在这个例子中,我们只是简单地清除了中断标志位。

实际上,中断服务函数的功能可能会更加复杂,例如读取传感器数据、控制外设等。

3. 中断服务函数的注意事项在编写t0中断服务函数时,需要注意以下几点:(1)中断服务函数需要尽可能地短小精悍,以便尽快地完成中断处理,并返回到主程序中。

(2)中断服务函数中不应该使用延时函数或者阻塞函数,因为这些函数会占用CPU的时间,导致系统响应变慢。

(3)中断服务函数中不应该使用浮点运算,因为浮点运算需要较长的时间,会影响系统的响应速度。

(4)中断服务函数中不应该使用全局变量,因为全局变量可能会被主程序和中断服务函数同时访问,导致数据不一致。

(5)中断服务函数中可以使用局部变量,但是需要注意变量的生命周期,以免出现变量被销毁的情况。

51单片机串行口中断服务程序

51单片机串行口中断服务程序

51单片机串行口中断服务程序单片机串行口中断服务程序是指在单片机进行串行通信时,当接收到数据时会触发中断,然后执行相应的中断服务程序。

下面是一个示例的单片机串行口中断服务程序,共计1200字以上。

#include <reg51.h> // 引入reg51.h头文件//定义串行口中断标志sbit RI_FLAG = P3^0; // 数据接收中断标志sbit TI_FLAG = P3^1; // 数据发送中断标志//定义串行口接收数据缓冲区unsigned char receiveBuffer[10];unsigned char receiveCount = 0;//定义串行口发送数据缓冲区unsigned char sendBuffer[10];unsigned char sendCount = 0;//串行口中断服务函数void serialInterrupt( interrupt 4if(RI_FLAG) // 判断是否是数据接收中断receiveBuffer[receiveCount] = SBUF; // 读取串行口接收数据receiveCount++; // 接收计数加1RI_FLAG=0;//清除中断标志位}if(TI_FLAG) // 判断是否是数据发送中断if(sendCount < 10) // 判断是否还有数据需要发送SBUF = sendBuffer[sendCount]; // 发送串行口数据sendCount++; // 发送计数加1}elsesendCount = 0; // 重置发送计数TI_FLAG=0;//清除中断标志位}}//主函数void mainES=1;//允许串行口中断TMOD=0x20;//设置定时器1为模式2,串行口使用定时器1 TH1=0xFD;//设置波特率为9600,定时器初值为0xFDTL1=0xFD;//定时器初值为0xFDSCON=0x50;//设置串行口工作在方式1,允许接收TR1=1;//启动定时器1while(1)//主程序逻辑//将数据存入发送缓冲区sendBuffer[0] = 'H';sendBuffer[1] = 'e';sendBuffer[2] = 'l';sendBuffer[3] = 'l';sendBuffer[4] = 'o';sendBuffer[5] = '\r'; // 发送回车符sendBuffer[6] = '\n'; // 发送换行符while(sendCount != 0) //等待数据发送完毕//主程序逻辑}}。

单片机定时器中断程序实例

单片机定时器中断程序实例

单片机定时器中断程序实例在单片机编程中,定时器是一种非常重要的功能模块。

它可以用来产生精确的时间延迟,实现定时触发事件等功能。

而定时器中断则是利用定时器来实现中断功能的一种方式。

下面是一个单片机定时器中断程序实例,供大家参考。

首先,我们需要初始化定时器。

以51单片机为例,定时器的初始化函数如下所示:void Init_Timer0(void){TMOD |= 0x01; //设置为模式1TH0 = (65536 - 50000) / 256; //设置初值TL0 = (65536 - 50000) % 256;EA = 1; //打开总中断ET0 = 1; //打开定时器0中断TR0 = 1; //启动定时器0}其中,TMOD寄存器用于设置定时器的工作模式。

这里设置为模式1,即16位定时器模式。

TH0和TL0寄存器则是定时器的计数器。

我们需要通过初值来设置定时时间。

在这个例子中,我们设置的定时时间为50ms。

接下来,我们需要编写定时器中断服务程序。

定时器中断服务程序是由中断向量表中的相应位置调用的,用于响应定时器中断。

在这个例子中,我们将定时器中断服务程序命名为Timer0_isr,定义如下:void Timer0_isr(void) interrupt 1{TH0 = (65536 - 50000) / 256;TL0 = (65536 - 50000) % 256;//定时器中断处理代码}在定时器中断服务程序中,我们需要重新设置计数器的初值,以实现定时器的循环工作。

同时,在这个例子中,我们需要在定时器中断处理代码中实现某些功能,例如周期性的输出一个信号、更新某个计数值等等。

最后,在主程序中,我们只需要调用Init_Timer0函数即可开始定时器的工作。

当定时器中断发生时,定时器中断服务程序会被自动调用。

这样,我们就实现了一个简单的单片机定时器中断程序。

51单片机串口中断的两种写法

51单片机串口中断的两种写法

单片机串口通信在嵌入式系统中具有非常重要的作用,而其中串口中断的编写方式更是至关重要。

今天我们来讨论一下51单片机串口中断的两种写法。

1. 外部中断写法在51单片机中,串口通信一般使用串口中断来实现。

外部中断写法是一种常见的串口中断编写方式。

其具体步骤如下:1)需要设置串口工作参数,包括波特率、数据位、停止位和校验位等。

2)在主程序中使能串口中断,并设置中断优先级。

3)在中断服务函数中进行接收数据的处理,可以通过接收缓冲区、中断标志位等来判断接收数据的情况,并进行相应的处理。

2. 定时器中断写法除了外部中断写法,定时器中断也是一种常见的串口中断编写方式。

其具体步骤如下:1)同样需要设置串口工作参数,包括波特率、数据位、停止位和校验位等。

2)在主程序中初始化定时器,并使能定时器中断。

3)在定时器中断服务函数中进行接收数据的处理,同样可以通过接收缓冲区、中断标志位等来判断接收数据的情况,并进行相应的处理。

总结无论是外部中断写法还是定时器中断写法,都是实现51单片机串口通信的常见方式。

在选择具体的编写方式时,需要根据具体的应用场景和需求来进行选择。

在实际应用中,可以根据具体情况来灵活选择合适的串口中断编写方式,以便更好地满足系统的需求。

在实际编写中断服务函数时,需要注意以下几点:1)处理数据时需要考虑数据的完整性和准确性,可以通过校验位等手段来验证数据的正确性。

2)在中断服务函数中应尽量减少对全局变量的访问,以避免出现数据冲突和竞争的情况。

3)合理设置中断优先级,避免产生中断嵌套和冲突。

通过合理的中断编写方式和注意事项,可以更好地实现串口通信功能,提高系统的稳定性和可靠性,为嵌入式系统的应用提供良好的技术支持。

对于外部中断写法和定时器中断写法,两者各有优缺点。

外部中断写法在串口数据到达时能够即刻响应中断、处理数据。

但是,如果数据传输速率较快或需要高精度的数据处理,外部中断写法可能无法满足要求。

在这种情况下,定时器中断写法显得更加合适。

单片机中断函数常见用法

单片机中断函数常见用法

#if __VER__<200interrupt void Usart1_rxInt(void) //与电表/红外通讯接收记数#else#pragma vector=USART1RX_VECTOR__interrupt void Usart1_rxInt(void)#endif{uchar ch=RXBUF1 ;if(devState.doWriteIrDA)return;if(n645Counts==0){if(ch!=0x68)return;elsecommState.wireSta645= RXDOING645;}commCode_645[n645Counts++] = ch;if(n645Counts > 63)n645Counts = 0;rxOverTime645 = 8; //unit:16ms}#if __VER__<200interrupt void Usart1_txInt(void) //与电表通讯发送中断发送记数#else#pragma vector = USART1TX_VECTOR__interrupt void Usart1_txInt(void)#endif{TXBUF1 = commCode_645[n645Counts++];if(n645Counts < nFrame645Size)return ;if(devState.doWriteIrDA) //红外发送TxIrDAover = 0;else{commState.wireSta645 = WAITACK645 ;waitAckOverTime645 = 30; //unit:16ms}IE2 &= ~UTXIE1; //关发送中断n645Counts = 0; //发送完成,长度清零}#if __VER__<200interrupt void Usart0_rxInt(void) //与主站通讯接收记数#else#pragma vector=USCIAB0RX_VECTOR__interrupt void Usart0_rxInt(void)#endif{unsigned char c=UCA0RXBUF;BYTE* pCode = GPRS_mCode;if(devState.dolocalComm){ if(nCommCounts==0 ){if(c!=0x68)return;else commState.rxDoing=1;}commCode[nCommCounts++] = c;rxOverTime = 6; //unit:16ms //doLocalpro = 0;if(nCommCounts > COMCODELEN)nCommCounts = 0;}else{if(specialFlag.GPRSTxf==0){c=UCA0RXBUF;commState.rxDoing = 1;pCode[GPRS_Com.RTxLen++] = c;rxOverTime= 10;if(MC55_Call_process == 13||MC55_Call_process == 15)rxOverTime = 35;else if(MC55_Call_process == 14 || MC55_Call_process == 8)rxOverTime = 185;else if(MC55_Call_process == 3)rxOverTime = 65;else if(MC55_Call_process == 4)rxOverTime = 65;if(GPRS_Com.RTxLen > COMCODELEN + 64)GPRS_Com.RTxLen = 0;}}}#if __VER__<200interrupt void Usart0_txInt(void) //与主站通讯发送中断发送记数#else#pragma vector = USCIAB0TX_VECTOR__interrupt void Usart0_txInt(void)#endif{if(devState.dolocalComm){UCA0TXBUF = commCode[nCommCounts++];if( nCommCounts < nFrameSize) return ;IE2 &= ~UCA0TXIE; //关发送中断nCommCounts = 0; //发送完成,长度清零}else{UCA0TXBUF = GPRS_mCode[GPRS_Com.nPos++];if(GPRS_Com.nPos < GPRS_Com.RTxLen)return ;IE2 &= ~UCA0TXIE; //关发送中断memset(GPRS_mCode,0,GPRS_Com.RTxLen);if(devState.ConfirmSetGPRS){devState.ConfirmSetGPRS = 0;nConfirmGPRS = 3;}GPRS_Com.RTxLen = 0;specialFlag.GPRSTxf = 0;}if(devState.ReadyResetPower){devState.stop_cleardg = 1;devState.ReadyResetPower = 0;}}#if __VER__<200interrupt void WatchDog_Timer(void) //看门狗定时器中断,遥脉计数#else#pragma vector = WDT_VECTOR__interrupt void WatchDog_Timer(void)#endif{if(rxOverTime645) rxOverTime645--;if(waitAckOverTime645) waitAckOverTime645--;if(rxOverTime) rxOverTime--;/*if(P1IN&BIT0)PowerOff_Timer = 10;if(PowerOff_Timer)PowerOff_Timer--;*/if(devState.ResetMC55){if(devState.wirelessMode)MC55_Start();elseEM200_Start();}}#if __VER__<200interrupt void basic_timer(void) //基本定时器主要是产生时钟信号62.5ms #else#pragma vector=BASICTIMER_VECTOR //暂未用__interrupt void basic_timer(void)#endif{static int SysTimeCount=0;SysTimeCount++;devState.n62_5msFlag = 1;if(SysTimeCount >= 16){devState.SecondFlag = 1;SysTimeCount = 0;LEDFLASH;CalculateAddedPQ();if(TxGPRSOverTime){TxGPRSOverTime--;if(TxGPRSOverTime==0){GPRS_recallnum++;specialFlag.GPRScom_finish = 1;if(GPRS_recallnum >= 3){GPRS_recallnum = 0;WaitStateFlag = 1;InitModem();specialFlag.CalledNum++;}}}if(devState.doIrDA){doIrdapro++;if(doIrdapro >= 4)devState.doIrDAover = 1;}elsedoIrdapro = 0;}}void TimerAOut(){CCTL0&=~CCIE;TACTL&=~(MC0+MC1);CCTL0&=~CAP;P1SEL&=~BIT0;if(BD_data.Frequence >= 4500 && BD_data.Frequence <= 5500) CCR0 = (92160000L/BD_data.Frequence)>>6;elseCCR0=DEFAULTCCR0;Sam_Counter=0;TACCR1 = 100; // Trig for ADC12 sample & convertTACCTL1 = OUTMOD_3; // Set/resetTACTL |= TACLR+ MC0;//MC_1 ; // clear TAR, up modeADC12CTL0 |= ENC;}void TimerAStop(){CCTL0&=~CCIE;TACTL&=~(MC0+MC1);}#if __VER__<200interrupt void ADC(void)#else#pragma vector = ADC12_VECTOR__interrupt void ADC(void)#endif{ADC12CTL0 &= ~ENC;Ua_Data[Sam_Counter] = ADC12MEM0<<3;//将A/D值存入数组Ia_Data[Sam_Counter] = ADC12MEM1<<3;Ub_Data[Sam_Counter] = ADC12MEM2<<3;Ib_Data[Sam_Counter] = ADC12MEM3<<3;Uc_Data[Sam_Counter] = ADC12MEM4<<3;Ic_Data[Sam_Counter] = ADC12MEM5<<3;Sam_Counter++;if(Sam_Counter>=64){devState.SampleSta=SAMPLEFFT ;Sam_Counter=0;TimerAStop();}elseADC12CTL0 |= ENC;}#if __VER__<200interrupt void Port2(void)#else#pragma vector=PORT2_VECTOR__interrupt void Port2(void)#endif{if((P2IFG & BIT0)== BIT0){P2IFG &= ~BIT0;if(!devState.doIrDA){SXD_1;devState.doIrDA = 1;n645Counts = 0;SetComBTForIrDA();}}}Main(){初始化;While(1){处理;}}#if __VER__<200interrupt void USCIA0_Int(void) //与电表通讯接收/发送中断记数#else#pragma vector=USCI_A0_VECTOR //既能接收中断也能发送中断__interrupt void USCIA0_Int(void)#endif{unsigned char ch;switch(__even_in_range(UCA0IV,4)){case 0:break; // Vector 0 - no interruptcase 2: // Vector 2 - RXIFG 接收中断标志while (!(UCA0IFG&UCTXIFG)); // USCI_A3 TX buffer ready?ch=UCA0RXBUF ;if(devState.doWriteIrDA)return;if(commState.n645Counts==0){if(ch!=0x68)break;}commState.wireSta645= RXDOING645;commCode_645[commState.n645Counts++] = ch;if(commState.n645Counts > 63)commState.n645Counts = 0;rxOverTime645 = 10; //unit:16msbreak;case 4: //Vector 4 - TXIFG 发送中断标志//SpecialFlag.TxdIdleFlag=1;UCA0TXBUF = commCode_645[commState.n645Counts++];if(commState.n645Counts < commState.nFrame645Size)break;if(devState.doWriteIrDA) //红外发送TxIrDAover = 0;else{commState.wireSta645 = WAITACK645 ;waitAckOverTime645 = 20; //unit:16ms}UCA0IE &= ~UCTXIE; //关发送中断commState.n645Counts = 0; //发送完成,长度清零break;default:break;}}#if __VER__<200interrupt void USCIA1_Int(void) //与本地维护口通讯接收/发送中断记数#else#pragma vector=USCI_A1_VECTOR //既能接收中断也能发送中断__interrupt void USCIA1_Int(void)#endif{unsigned char c;switch(__even_in_range(UCA1IV,4)){case 0:break; // Vector 0 - no interruptcase 2: // Vector 2 - RXIFG 接收中断标志//while (!(UCA0IFG&UCTXIFG)); // USCI_A3 TX buffer ready?c=UCA1RXBUF;if(_1_nCommCounts==0){//if(c!=0x68)return;}_1_rxDoing=1;LocalComCode[_1_nCommCounts++] = c; //leon-10-3-18_1_rxOverTime = 6; //unit:16ms //if(_1_nCommCounts > COMCODELEN)_1_nCommCounts = 0;efrom_Com_1 = 1;break;case 4: //Vector 4 - TXIFG 发送中断标志UCA1TXBUF = LocalComCode[_1_nCommCounts++]; //leon-10-3-18if( _1_nCommCounts < commState.nFrameSize)return ;UCA1IE &= ~UCTXIE; //关发送中断efrom_Com_1 = 0;_1_nCommCounts = 0; //发送完成,长度清零if(devState.ReadyResetPower){devState.stop_cleardg = 1;devState.ReadyResetPower = 0;}break;default:break;}}#if __VER__<200interrupt void USCIA2_Int(void) //与载波模块通讯接收/发送中断记数#else#pragma vector=USCI_A2_VECTOR //既能接收中断也能发送中断__interrupt void USCIA2_Int(void)#endif{unsigned char c;// BYTE* pCode = GPRS_mCode;switch(__even_in_range(UCA2IV,4)){case 0:break; // Vector 0 - no interruptcase 2: // Vector 2 - RXIFG 接收中断标志c=UCA2RXBUF;CalCom[carrworkst.testPos++] = c;carrworkst.workstate = RXDOING645;carrworkst.rxOverTime = 30;break;case 4: //Vector 4 - TXIFG 发送中断标志UCA2TXBUF = CalCom[carrworkst.testPos++];if(carrworkst.testPos < carrworkst.Txlen)return;UCA2IE &= ~UCTXIE;carrworkst.testPos = 0;carrworkst.workstate = WAITACK645;break;default:break;}}#if __VER__<200interrupt void USCIA3_Int(void) // 串口3 与GPRS模块口通讯接收/发送中断记数#else#pragma vector=USCI_A3_VECTOR //既能接收中断也能发送中断__interrupt void USCIA3_Int(void)#endif{unsigned char c;BYTE* pCode = GPRS_mCode; // 指向指令区switch(__even_in_range(UCA3IV,4)) // UCA3IV 为几就执行case 几{case 0:break; // Vector 0 - no interrupt 无中断case 2: // Vector 2 - RXIFG 接收中断标志接收//while (!(UCA0IFG&UCTXIFG)); // USCI_A3 TX buffer ready? UCA0IFG=0 UCTXIFG=0 if(specialFlag.GPRSTxf==0){c=UCA3RXBUF; //接收到的数据全部放入缓存在放入变量C中(一个字节)_2_rxDoing = 1;pCode[GPRS_Com.RTxLen++] = c; //再放入命令区命令区长度加1_2_rxOverTime= 10;if(MC55_Call_process == 13||MC55_Call_process == 15)_2_rxOverTime = 35;if(MC55_Call_process == 15)_2_rxOverTime = 15;else if(MC55_Call_process == 14 || MC55_Call_process == 8)_2_rxOverTime = 200;else if(MC55_Call_process == 3)_2_rxOverTime = 65;else if(MC55_Call_process == 4)_2_rxOverTime = 65;if(GPRS_Com.RTxLen > COMCODELEN + 64)GPRS_Com.RTxLen = 0;}break;case 4: //Vector 4 - TXIFG 发送中断标志发送UCA3TXBUF = GPRS_mCode[GPRS_Com.nPos++]; //需要发送的数据放入缓存if(GPRS_Com.nPos < GPRS_Com.RTxLen) //发送未完成。

51单片机中断函数

51单片机中断函数

51单片机中断函数在51单片机中,中断函数是一种特殊的函数,它用于响应硬件中断信号。

当某个特定的硬件事件发生时,例如按下按键、定时器溢出等,会触发相应的中断。

中断函数被设计用于在中断发生时执行特定的操作,以便及时响应和处理。

1. 中断的基本概念中断是指计算机运行过程中突然打断正常程序执行的事件。

当一个中断事件发生时,CPU会立即停下当前正在执行的指令,转而去执行与中断相关的处理程序,也就是中断函数。

完成中断处理后,CPU会返回到被中断的指令继续执行。

2. 中断函数的编写编写中断函数需要遵循一定的规则,以确保正确的执行和处理中断事件。

下面是一些编写中断函数的基本要点:•中断函数的定义,需要使用特殊的语法来声明,例如:void interrupt 中断函数名(void)•中断函数不能有参数,因为中断发生时无法传递参数•中断函数内部的代码应尽量简短,避免耗时过长,以免影响正常程序的执行•在中断函数中,可以使用一些特殊的关键字和函数来操作中断相关的寄存器和标志位,例如EA(总中断使能)和EX0(外部中断0使能)3. 中断的优先级和嵌套在51单片机中,中断可以有不同的优先级。

具有较高优先级的中断可以打断正在执行的较低优先级中断。

这种中断嵌套的机制可以确保重要的中断事件能够及时得到响应。

在编写中断函数时,需要注意不同中断的优先级设置。

一般情况下,较高优先级的中断应该尽量快速地完成处理,以便让其他中断有机会执行。

4. 中断的开关与屏蔽为了灵活控制中断的响应和屏蔽,51单片机提供了相关的寄存器和函数。

通过设置中断控制寄存器,可以开关特定中断的使能。

通过设置标志位,可以屏蔽或允许中断的触发。

在编写中断函数时,需要注意合理地使用中断开关和屏蔽功能,以避免不必要的中断触发和冲突。

5. 中断函数的调用与返回中断函数的调用是由硬件自动完成的,无需程序员主动调用。

当中断事件发生时,CPU会自动跳转到相应中断函数的入口地址执行。

中断服务函数

中断服务函数

中断服务函数51中断:5个 ES串⼝,ET1定时器1,ET0定时器0,EX1外部中断1,EX0外部中断0⾸先要了解相关的与中断有关的寄存器:IE寄存器:中断控制的寄存器,要实现中断就要配置该寄存器。

EA为总开关,只有先打开EA才能对相应的寄存器进⾏操作TCON寄存器:⽤来控制中断的触发⽅式,是低电平触发还是下降沿触发,由图知道:⾸先相应触发⽅式,然后看是低电平还是下降沿触发(给0或1,1下降沿触发)然后对应的IE寄存器相当于开关的作⽤,然后是IP寄存器控制中断的优先级要是⽤中断 得记住:这个就是对应中断的对应触发⽅式的⼊⼝外部中断0:INT0 中断的优先级 0定时计数器中断0:TF0 1外部中断1:INT1 2定时器中断1:TF1 3串⼝中断:R1/T1 4中断函数写的时候,⾸先要初始化,就是打开相应的中断请求,如打开外部中断0⾸先定义⼀个初始化的函数INT0,然后打开触发⽅式IT0=1,然后打开总开关EA=1;然后打开定时器0的开关EX0=1;然后定义中断0的服务函数,中断号是0,如果打开外部中断1 那么定义⼀个初始化的函数INT1,然后打开触发⽅式IT1=1,然后打开总开关EA=1,打开中断的开关EX1=1;注意中断服务函数的⼊⼝是2也可以采⽤看图配置寄存器来使⽤,按照16进制看图来配置,如何让产⽣中断后进⾏相关操作,可以定义⼀个状态变量,当产⽣中断时,状态变量翻转,然后根据相关的状态来进⾏相关的操作总结:中断函数⾸先进⾏初始化的定义,看是使⽤外部中断(0,1)0的话先打开下降沿的触发信号IT0,然后再打开总开关EA=1,然后⼤开外部中断0(INT0)的开关EX0=1,然后定义相关的中断服务函数 中断号为0,中断服务函数中尽量少些程序,可以⽤状态值来调⽤中段函数,例如我可以先定义⼀个状态变量为0,进⼊中断函数后状态变量为1,然后在定义⼀个相关的函数进⾏操作,让状态变量函数成为判断条件,进⾏完相关的操作后,将状态变量的值该变为原来的状态 值得注意的是在定义相关开关的时候,可以直接对寄存器进⾏相关的操作,就是直接给0或者1让其打开相关的寄存器,然后写成16进制。

单片机中断触发方式代码

单片机中断触发方式代码

单片机中断触发方式代码1.引言中断是单片机中常用的一种编程方式,可通过中断从程序的正常执行流程中跳转,响应特定的事件或条件。

中断触发方式代码定义了中断的触发条件、中断程序的处理流程以及中断的优先级等相关配置,本文将介绍几种常见的单片机中断触发方式代码。

2.外部中断触发方式代码外部中断是指通过外部触发器产生中断请求,单片机在接收到中断请求后,根据相应的中断触发方式代码来响应中断。

以下是一个外部中断触发方式代码的示例:#i nc lu de<r eg52.h>s b it IN T0=P3^2;//外部中断0引脚v o id IN T0_I ni t(){I T0=1;//外部中断0触发方式为下降沿触发E X0=1;//使能外部中断0E A=1;//总中断使能}v o id IN T0_H an dl er()in te rr up t0{//中断处理程序}v o id ma in(){I N T0_I ni t();w h il e(1);}3.定时器中断触发方式代码定时器中断是通过定时器溢出产生中断请求,单片机在定时器溢出时,根据相应的中断触发方式代码来响应中断。

以下是一个定时器中断触发方式代码的示例:#i nc lu de<r eg52.h>v o id Ti me r0_I ni t(){T M OD=0x01;//定时器0工作在模式1T H0=0x FC;//定时器0初值设定为0xFC67,定时1m sT L0=0x67;E T0=1;//允许定时器0中断E A=1;//总中断使能T R0=1;//启动定时器0}v o id Ti me r0_H an dle r()in te rr up t1{//中断处理程序}v o id ma in(){w h il e(1);}4.串口中断触发方式代码串口中断是通过接收到数据或发送完成时产生中断请求,单片机在接收到中断请求后,根据相应的中断触发方式代码来响应中断。

中断服务程序

中断服务程序

单片机_C语言函数_中断函数(中断服务程序)在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。

中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。

(1)中断源:中断请求信号的来源。

(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。

期间涉及到CPU响应中断的条件,现场保护,现场恢复。

(3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。

优先级是可以编程的,而优先权是固定的。

80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。

80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制(1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。

在这里我们讲下注意的事项(1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。

(2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。

所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。

(3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。

单片机C语言函数中断函数(中断服务程序)

单片机C语言函数中断函数(中断服务程序)

单片机_C语言函数_中断函数(中断服务程序)在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。

中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。

(1)中断源:中断请求信号的来源。

(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。

期间涉及到CPU响应中断的条件,现场保护,现场恢复。

(3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。

优先级是可以编程的,而优先权是固定的。

80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。

80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制(1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。

在这里我们讲下注意的事项(1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。

(2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。

所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。

(3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机中断服务函数写法
一、在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。

(1)中断源:中断请求信号的来源。

(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效。

(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。

期间涉及到CPU响应中断的条件,现场保护,现场恢复。

(3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。

优先级是可以编程的,而优先权是固定的。

80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。

80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制
(1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1
(2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP
具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。

在这里我们讲下注意的事项
(1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。

(2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。

所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。

(3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。

(4)单片机复位后,TCON,SCON给位清零。

C51语言允许用户自己写中断服务子程序(中断函数)
首先来了解程序的格式:
void 函数名() interrupt m [using n]
{}
关键字interrupt m [using n] 表示这是一个中断函数
m为中断源的编号,有五个中断源,取值为0,1,2,3,4,中断编号会告诉编译器中断程序的入口地址,执行该程序时,这个地址会传个程序计数器PC,于是CPU开始从这里一条一条的执行程序指令。

n为单片机工作寄存器组(又称通用寄存器组)编号,共四组,取值为0,1,2,3
中断号中断源
0 外部中断0
1 定时器0
2 外部中断1
3 定时器1中断
4 串行口中断
这5个中断源的中断入口地址为:(在上一篇文章中讲到的ROM前43个存储单元就是他们,这40
个地址用来存放中断处理程序的地址单元,每一个类中断的存储单元只有8B,显然不是中断处理的程序,而是存放着中断处理程序的真正地址)
INT0:0003H 0
T0:000BH 1
INT1:0013H 2
T1: 001BH 3
串口: 0023H 4
中断向量(中断入口地址)= 中断号x8 +3
前面m意思很清楚,不同的m值表示这个函数是针对不同的中断源,比如m为1是表示它是定时器0的中断函数,
如void time0() interrupt 1{}
那么后面的using n 又是什么意思呢?在正在执行一个特定任务时,有更紧急的事情需要CPU来处理,涉及到中断优先权。

高优先权中断低优先权正在处理的程序,所以最好给每个优先程序分配不同的寄存器组。

CPU正在处理某个事件,突然另外一个事件需要处理,于是进入中断后,而你不想将现在执行的程序的各寄存器状态入栈,那么可以把这个中断程序放入另一个寄存器组,如切换到1组,然后退出中断时,再切回到0组(原来的程序在0组)。

为了更好的了解这里意思,你可以看看工作寄存器组的作用是什么。

下面的注意事项转自网络上其他朋友的文章(整理下,重复的去掉了,写的非常好):
(1)中断函数不能进行参数传递
(2)中断函数没有返回值
(3)在任何情况下都不能直接调用中断函数
(4)中断函数使用浮点运算要保存浮点寄存器的状态。

(5)如果在中断函数中调用了其它函数,则被调用函数所使用的寄存器必须与中断函数相同,被调函数最好设置为可重入的。

(6)C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容,具体如下:在程序
开始处对ACC、B、DPH、DPL和PSW入栈,结束时出栈。

中断函数未加using n修饰符的,开始时还要将R0~R1入栈,结束时出栈。

如中断函数加using n修饰符,则在开始将PSW入栈后还要修改PSW 中的工作寄存器组选择位。

(7)C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。

该向量包含一个到中断函数入口地址的绝对跳转。

(8)中断函数最好写在文件的尾部,并且禁止使用extern存储类型说明。

防止其它程序调用。

(9)在设计中断时,要注意的是哪些功能应该放在中断程序中,哪些功能应该放在主程序中。

一般来说中断服务程序应该做最少量的工作,这样做有很多好处。

首先系统对中断的反应面更宽了,有些系统如果丢失中断或对中断反应太慢将产生十分严重的后果,这时有充足的时间等待中断是十分重要的。

其次它可使中断服务程序的结构简单,不容易出错。

中断程序中放入的东西越多,他们之间越容易起冲突。

简化中断服务程序意味着软件中将有更多的代码段,但可把这些都放入主程序中。

中断服务程序的设计对系统的成败有至关重要的作用,要仔细考虑各中断之间的关系和每个中断执行的时间,特别要注意那些对同一个数据进行操作的ISR.。

相关文档
最新文档