中断interrupt using3的解析
基于C51中断过程及interrupt和using的使用
基于C51中断过程及interrupt和using的使用
8051 系列MCU 的基本结构包括:32 个I/O 口(4 组8 bit 端口);两个16 位定时计数器;全双工串行通信;6 个中断源(2 个外部中断、2 个定时/计数器中断、1 个串口输入/输出中断),两级中断优先级;128 字节内置RAM;独立的64K 字节可寻址数据和代码区。
中断发生后,MCU 转到 5 个中断入口处之一,然后执行相应的中断服务。
处理程序。
中断程序的入口地址被编译器放在中断向量中,中断向量位于程序代码段的最低地址处,注意这里的串口输入/输出中断共用一个中断向量。
8051的中断向量表如下:中断源中断向量
---------------------------
上电复位0000H
外部中断0 0003H
定时器0 溢出000BH
外部中断1 0013H
定时器1 溢出001BH
串行口中断0023H
定时器2 溢出002BH
interrupt 和using 都是C51 的关键字。
C51 中断过程通过使用interrupt 关键字和中断号(0 到31)来实现。
中断号指明编译器中断程序的入口地址中断序号对应着8051中断使能寄存器IE 中的使能位,对应关系如下:
IE寄存器C51中的8051的
的使能位中断号中断源
--------------------------------
IE.0 0 外部中断0
IE.1 1 定时器0 溢出。
interrupt、using关键字的用法
C语言在8051单片机上的扩展(interrupt、using关键字的用法)直接访问寄存器和端口定义sfr P0 0x80sfr P1 0x81sfr ADCON; 0xDEsbit EA 0x9F操作ADCON = 0x08 ;P1 = 0xFF ;io_status = P0 ;EA = 1 ;在使用了interrupt 1 关键字之后,会自动生成中断向量在ISR中不能与其他"后台循环代码"(the background loop code) 共享局部变量因为连接器会复用在RAM中这些变量的位置,所以它们会有不同的意义,这取决于当前使用的不同的函数复用变量对RAM有限的51来将很重要。
所以,这些函数希望按照一定的顺序执行而不被中断。
timer0_int() interrupt 1 using 2{unsigned char temp1 ;unsigned char temp2 ;executable C statements ;}"interrupt"声明表示向量生成在(8*n+3),这里,n就是interrupt参数后的那个数字这里,在08H的代码区域生成LJMP timer0_int 这样一条指令"using" tells the compiler to switch register banks on entry to an interrupt routine. This "context" switch is the fastest way of providing a fresh registerbank for an interrupt routine's local data and is to be preferred to stacking registers for very time-critical routines. Note that interrupts of the same priority can share a register bank, since there is no risk that they will interrupt each other.'using' 告诉编译器在进入中断处理器去切换寄存器的bank。
51单片机interrupt用法
51单片机interrupt用法1. 什么是51单片机interrupt?51单片机是一种常用的嵌入式微控制器,被广泛应用于各种电子设备中。
中断是一种特殊的处理机制,它允许单片机在执行某个任务的过程中,临时暂停当前的任务,去处理其他紧急事件。
这些紧急事件可以是来自外部设备的信号、计时器溢出等。
2. 为什么要使用interrupt?使用interrupt的好处是可以及时响应外部事件,提高系统的实时性和可靠性。
不使用interrupt的话,单片机只能按照预定的程序执行,无法即时响应外部事件,造成系统的延迟和不稳定。
3. 如何使用interrupt?首先,我们需要了解51单片机的interrupt架构。
51单片机有两个interrupt源,分别是外部中断和定时器/计数器中断。
外部中断:单片机的P3口(即引脚INT0和INT1)可以接收外部中断信号。
当INT0引脚检测到高电平脉冲时(可以通过软件设置为下降沿触发或低电平触发),单片机就会执行外部中断的相关程序。
INT1引脚类似。
定时器/计数器中断:单片机的定时器/计数器模块可以设置定时中断。
定时器可以根据一定的时钟源进行计数,当计数值达到预设值时,就会触发中断。
通过设置计数器的工作模式和计数初值,可以灵活控制定时中断的触发时间和频率。
对于外部中断,我们可以通过设置相应的中断控制寄存器来选择触发方式(下降沿触发、低电平触发等)。
然后,在主程序中需要响应外部中断的地方,我们可以编写一个中断服务程序(ISR),用来处理中断事件。
中断服务程序需要使用关键字”interrupt”进行声明,同时需要保存现场(将寄存器的值及其他关键状态保存在堆栈中),以便中断结束后能够正确恢复。
对于定时器/计数器中断,我们首先需要对定时器进行初始化设置,选择时钟源和工作模式。
然后,我们可以设置计数初值和中断触发时间。
当计数器达到预设值时,中断程序会被执行。
下面我们就来介绍一个常见应用案例:使用外部中断实现按键控制LED的亮灭。
Keil+C编译器常见警告与错误信息的解决方法
໕ᐺࡇᇙቧᇦ本章列出了编程中可能遇到的致命错误语法错误和警告信息每节包括一个信息的主要说明和消除错误或警告条件可采取的措施致命错误致命错误立即终止编译这些错误通常是命令行指定的无效选项的结果当编译器不能访问一个特定的源包含文件时也产生致命错误致命错误信息采用下面的格式C51 FATAL-ERROR –ACTION<current action>LINE:<line in which the error is detected>ERROR:<corresponding error message> C51 TERMIANTED.C51 FATAL-ERROR –ACTION<current action>FILE:<file in which the error is detected>ERROR:<corresponding error message> C51 TERMIANTED.下面说明Action和Error中可能的内容ActionsALLOCATING MEMORY编译器不能分配足够的存储区来编译指定的源文件CREATING LIST-FILE / OBJECT-FILE / WORKFILE编译器不能建立列表文件OBJ文件或工作文件这个错误的出现可能是磁盘满或写保护或文件已存在和只读GENERATING INTERMEDIATE CODE源文件包含的一个函数太大不能被编译器编译成虚拟代码尝试把函数分小或重新编译OPENING INPUT-FILE编译器不能发现或打开所选的源或包含文件PARSING INVOKE-/#PRAGMA-LINE当在命令行检测到参数计算或在一个#pragma中检测到参数计算就产生这样的错误PARSING SOURCE-FILE/ANALYZING DECLARATIONS源文件包含太多的外部参考减少源文件访问的外部变量和函数的数目WRITING TO FILE当写入列表文件OBJ文件或工作文件时遇到的错误Errors‘(‘ AFTER CONTROL EXPECTED一些控制参数需要用括号包含一个参数当没有左括号时显示本信息‘)’ AFTER PARAMETER EXPECTED本信息表示包含没有参数的右括号BAD DIGIT IN NUMBER一个控制参数的数字参数包含无效字符只能是十进制数CAN’T CREATE FILE在FILE行定义的文件名不能建立CAN’T HA VE GERERAL CONTROL IN INVOCATION LINE一般控制例如EJECT不能包含在命令行把这些控制用#pragma声明放在源文件中FILE DOES NOT EXIST没有发现定义在FILE行的文件FILE WRITE-ERROR因为磁盘空间不够写到列表预打印工作或目标文件时出错IDENTIFIER EXPECTED当DEFINE控制没有参数时产生本信息DEFINE要求一个参数作为标识符这和C语言的规则相同MEMORY SPACE EXHAUSTED编译器不能分配足够的存储区来编译指定的源文件如果始终出现这个信息应该把源文件分成两个或多个小文件再重新编译MORE THAN100ERRORS IN SOURCE-FILE在编译时检测到的错误超过100个这使编译器终止MORE THAN256SEGMENTS/EXTERNALS在一个源文件中的参考超过256个单个的源文件不能有超过256个函数或外部参考这是INTEL目标模块格式OMF-51的历史的限制包含标量和/或bit声明的函数在OBJ文件中生成两个有时候三个段定义NON-NULL ARGUMENT EXPECTED所选的控制参数需要用括号包含一个参数例如一个文件名或一个数字OUT OF RANGE NUMBER一个控制参数的数字参数超出范围例如OPTIMIZE控制只允许数字0到6值7就将产生本错误信息PARSE STACK OVERFLOW解析堆栈溢出如果源程序包含很复杂的表达式或如果块的嵌套深度超过31级就会出现这个错误PREPROCESSOR LINE TOO LONG32K一个中间扩展长度超过32K字符PREPROCESSOR MACROS TOO NESTED在宏扩展期间预处理器所用的堆栈太大这个信息通常表示一个递归的宏定义但也可表示一个宏嵌套太多RESPECIFIED OR CONFLICTING CONTROL一个命令行参数指定了两次或命令行参数冲突SOURCE MUST COME FROM A DISK-FILE源和包含文件必须存在控制台CON CI或类似的设备不能作为输入文件UNKNOWN CONTROL所选的控制参数不认识语法和语义错误语法和语义错误一般出现在源程序中它们确定实际的编程错误当遇到这些错误时编译器尝试绕过错误继续处理源文件当遇到更多的错误时编译器输出另外的错误信息但是不产生OBJ文件语法和语义错误在列表文件中生成一条信息这些错误信息用下面的格式*** ERROR number IN LINE line OF file:error message这里number错误号line对应源文件或包含文件的行号file产生错误的源或包含文件名error message对错误的叙述说明下表按错误号列出了语法和语义错误错误信息列出了主要说明和可能的原因和改正100跳过不可打印字符0x??在源文件中发现一个非法字符注意不检查注释中的字符101字符串没结束一个字符串没有用双引号终止102字符串太长一个字符串不能超过4096个字符用串联符号\在逻辑上可延长字符串超过4096个字符这个模式的行终止符在词汇分析时是连续的103无效的字符常数一个字符常数的格式无效符号\c是无效的除非c是任何可打印的ASCII字符125声明符太复杂20一个目标的声明可包含最多20个类型修饰符[]*这个错误经常伴随着错误126126类型堆栈下溢类型声明堆栈下溢这个错误通常死错误125的副产品127无效存储类一个目标用一个无效的存储空间标识符声明如果一个目标在一个函数外用存储类auto或register声明就会产生本错误129在标记前缺少本错误通常表示前一行缺少分号当出现本错误时编译器会产生很多错误信息130值超出范围在一个using或interrupt标识符后的数字参数是无效的using标识符要求一个0到3之间的寄存器组号interrupt标识符要求一个0到31之间的中断矢量号131函数参数重复一个函数有相同的参数名在函数声明中参数名必须是唯一的132没在正式的参数列表一个函数的参数声明用了一个名称没在参数名列表中例如char function(v0,v1,v2)char *v0,*v1,*v5;/* ‘v5’没在正式列表中 */{/* … */}134函数的xdata/idata/pdata/data不允许函数通常位于code存储区不能在别的存储区运行函数默认定义为存储类型code135bit的存储类错bit标量的声明可能包含一个static或extern存储类register或alien类是无效的136变量用了voidvoid类型只允许作为一个不存在的返回值或一个函数的空参数列表voidfunc(void)或和一个指针组合void *138Interrupt()不能接受或返回值一个中断函数被定义了一个或多个正式的参数或一个返回值中断函数不能包含调用参数或返回值140位在非法的存储空间bit标量的定义可以包含可选的存储类型data如果没有存储类型则默认为data因为位通常在内部数据存储区当试图对一个bit标量定义别的数据类型时会产生本错误141临近标志语法错误期待别的标志…编译器所见的标志是错误的参考所显示的期待的内容142无效的基地址一个sfr或sbit声明的基地址是错误的有效的基地址范围在0x80到0xFF之间如果用符号基地址^位号声明则基地址必须是8的倍数143无效的绝对位地址sbit声明中的绝对位地址必须在0x80到0xFF之间144基地址^位号无效的位号sbit声明中定义的位号必须在0到7之间145未知的sfr146无效sfr一个绝对位基地址^位号的声明包含一个无效的基地址标识符基地址必须是已经声明的sfr任何别的名称是无效的147目标文件太大单个目标文件不能超过6553564K字节-1149struct/union包含函数成员struct或union不能包含一个函数类型的成员但是指向函数的指针是可以的150struct/union包含一个bit成员一个union不能包含bit类型成员这是8051的结构决定的151struct/union自我关联一个结构不能包含自己152位号超出位域位域声明中指定的位号超过给定基类的位号153命名的位域不能为零命名的位域为零只要未命名的位域允许为零154位域指针指向位域的指针不允许155位域要求char/int位域的基类要求char或int unsigned char和unsigned int类型也行156alien只允许对函数157alien函数带可变参数存储类alien只对外部PL/M-51函数允许符号ch a r*,…在alien函数中是非法的PL/M-51函数通常要求一个固定的参数表158函数包含未命名的参数一个函数的参数列表定义包含一个未命名的抽象类型定义这个符号只允许在函数原型中159void后面带类型函数的原型声明可包含一个空参数列表例如int func(void)在void后不能再有类型定义160void无效void类型只在和指针组合或作为一个函数的不存在的返回值中是合法的161忽视了正式参数在一个函数内一个外部函数的声明用了一个没有类型标识符的参数名列表例如extern yylex(a,b,c);180不能指向一个函数指向一个函数的类型是无效的尝试用指针指向一个函数181操作数不兼容对给定的操作符至少一个操作数类型是无效的例如~float_type183左值不能修改要修改的目标位于code存储区或有const属性因此不能修改184sizeof非法操作数sizeof操作符不能确定一个函数或位域的大小185不同的存储空间一个目标声明的存储空间和前一个同样目标声明的存储空间不同186解除参照无效一个内部编译器问题会产生本信息如果本错误重复出现请和技术支持接洽187不是一个左值所需的参数必须是一个可修改的目标地址188未知目标大小因为没有一个数组的维数或间接通过一个void指针一个目标的大小不能计算189&对bit/sfr非法取地址符’&’不允许对bit目标或特殊函数寄存器sfr190&不是一个左值尝试建立一个指针指向一个未知目标193非法操作类型193对ptr非法add/sub193对bit的非法操作193错误操作数类型当对一个给定的操作符用了非法的操作数类型时产生本错误例如无效的表达式如bit*bit ptr+ptr或ptr*anything这个错误信息包括引起错误的操作符下面的操作对bit类型的操作数是可行的赋值=OR/复合OR||=AND/复合AND&&=XOR/复合XOR^^=bit比较= =!=取反~bit操作数可和别的数据类型在表达式中混用在这种情况类型转换自动执行194*间接指向一个未知大小的目标间接操作符*不能和void指针合用因为指针所指的目标的大小是未知的195*间接非法*操作符不能用到非指针参数196存储空间可能无效转换一个常数到一个指针常数产生一个无效的存储空间例如 char*p=0x91234198sizeof返回零sizeof操作符返回一个零199->’的左边要求struct/union指针->操作符的左边参数必须是一个struct指针或一个union指针200.左边要求struct/union.操作符的左边参数要求必须是struct或union类型201未定义的struct/union给定的struct或union名是未知的202未定义的标识符给定的标识符是未定义的203错误的存储类参考名本错误表示编译器的一个问题如果重复出现请接洽技术支持204未定义的成员给定的一个struct或union成员名是未定义的205不能调用一个中断函数一个中断函数不能象一个正常函数一样调用中断的入口和退出代码是特殊的207参数列表声明为void参数列表声明为void的函数不能从调用者接收参数208太多的实参函数调用包含太多的实参209太少的实参调用函数包含太少的实参210太多的嵌套调用函数的嵌套调用不能超过10级211调用不是对一个函数一个函数的调用项不是对一个函数或函数指针求值212间接调用寄存器的参数不匹配通过一个指针的间接函数调用不包含实际的参数一个例外是当所有的参数可以通过寄存器传递这是由于Cx51所用的传递参数的方法被调用的函数名必须是已知的因为参数写到被调用函数的数据段但是对间接调用来说被调用函数的名称是未知的213赋值符的左边不是一个左值赋值符的左边要求一个可修改目标的地址214非法指针转换bit float或集合类型的目标不能转换为指针215非法类型转换struct/union/void不能转换为任何别的类型216标号用在非数组中或维数超出一个数组引用包含太大的维数或目标不是一个数组217非整数索引一个数组的维数表达式必须是char unsigned char int或unsigned int类型别的类型都是非法的218控制表达式用了void类型在一个while for或do的限制表达式中不能用类型void219long常数缩减为int一个常数表达式的值必须能用一个int类型表示220非法常数表达式期望一个常数表达式目标名变量或函数不允许出现在常数表达式中221非常数case/dim表达式一个case或一个维数[ ]必须是一个常数表达式222被零除223被零取模编译器检测到一个被零除或取模225表达式太复杂需简化一个表达式太复杂必须分成两个或多个子表达式226重复的struct/union/enum标记一个struct union或enum名早已定义227表示一个union标记一个union名称早已定义为别的类型228表示一个struct标记一个struct名早已定义为别的类型229表示一个enum标记一个enum名早已定义为别的类型230未知的struct/union/enum标记指定的struct union或enum名未定义231重复定义指定的名称已被定义232重复标号指定的标号已定义233未定义标号表示一个标号未定义有时候这个信息会在实际的标号的几行后出现这是所用的未定义标号的搜索方法引起的234{堆栈范围溢出31超过了最多31个嵌套块超出的嵌套块被忽略235参数<数字>不同类型函数声明的参数类型和函数原型中的不同236参数列表的长度不同函数声明中的参数数目和函数原型中的不同237函数早已定义试图声明一个函数体两次238重复成员239重复参数试图定义一个已存在的struct成员或函数参数240超出128个局部bit在一个函数内不能超过128个bit标量241auto段太大局部目标所需的空间超过模式的极限最大的段大小定义如下SMALL128字节COMPACT256字节LARGE65535字节242太多的初始化软件初始化软件的数目超过初始化目标的数量243字符串超出范围字符串中的字符数目超出字符串初始化的数目244不能初始化错误的类型或类试图初始化一个bit或sfr245未知的pragma跳过本行#pragma状态未知所以整行被忽略246浮点错误当一个浮点参数超出32位的范围就产生本错误32位IEEE值的范围是±1.175494E-38到±3.402823E+38247非地址/常数初始化一个有效的初始化表达式必须是一个常数值求值或一个目标名加或减去一个常数248集合初始化需要大括号给定struct或union初始化缺少大括号{}249段<名>段太大编译器检测到一个数据段太大一个数据段的最大的大小由存储空间决定250\esc值超过255一个字符串常数中的转义序列超过有效值范围最大值是255252非法八进制数指定的字符不是一个有效的八进制数252主要控制放错地方行被忽略主要控制必须被指定在C模块的开头在任何#include命令或声明前253内部错误ASMGEN\CLASS在下列情况下出现本错误一个内在函数例如_testbit_被错误激活这种情况是在没有函数原型存在和实参数目或类型错误对这种原因必须使用合适的声明文件INTRINS.H STRING.H参考第八章中的instrinsic函数Cx51确认一个内部一致性问题请接洽技术支持255switch表达式有非法类型在一个switch表达式没有合法的数据类型256存储模式冲突一个包含alien属性的函数只能包含模式标识符small函数的参数必须位于内部数据区这适用于所有的外部alien声明和alien函数例如alien plm_func(char c) large {…}产生错误256257alien函数不能重入一个包含alien属性的函数不能同时包含reentrant属性函数参数不能跳过虚拟堆栈传递这适用于所有的外部alien声明和alien函数258struct/union成员的存储空间非法非法空间的参数被忽略一个结构的成员或参数不能包含一个存储类型标识符但指针所指的目标可能包含一个存储类型例如struct vp{char code c;int xdata i; };产生错误258struct v1{char c;int xdata *i; };是正确的struct声明259指针不同的存储空间一个空指针被关联到别的不同存储空间的空指针例如char xdata *p1;char idata *p2;p1 = p2; /* 不同的存储空间 */260指针断开一个空指针被关联到一些常数值这些值超过了指针存储空间的值范围例如char idata *p1 = 0x1234; /* 结果是0x34 */261reentrant()内有bit一个可重入属性的函数的声明中不能包含bit目标例如int func1(int i1) reentrant {bit b1,b2; /* 不允许 */return(i1-1);}262using/disable不能返回bit值用using属性声明的函数和禁止中断#pragma disable的函数不能返回一个bit值给调用者例如bit test(void) using 3{bit b0;return(b0);}产生错误262263保存/恢复堆栈保存溢出/下溢#pragma save的最大嵌套深度是八级堆栈的pragma save和restore工作根据LIFO后进先出规则264内在的<内在的名称>声明/激活错误本错误表示一个内在的函数错误定义参数数目或省略号如果用标准的.H文件就不会产生本错误确认使用了Cx51所有的.H文件不要尝试对内在的库函数定义自己的原型265对非重入函数递归调用非重入函数不能被递归调用因为这样会覆盖函数的参数和局部数据如果需要递归调用需声明函数为可重入函数267函数定义需要ANSI类型的原型一个函数被带参数调用但是声明是一个空的参数列表原型必须有完整的参数类型这样编译器就可能通过寄存器传递参数和适合应用的调用机制268任务定义错误任务ID/优先级/using任务声明错误271asm/endasm控制放错地方asm和endasm声明不能嵌套endasm要求一个汇编块前面用asm开头例如#pragma asm...汇编指令...#pragma endasm272asm要求激活SRC控制在一个源文件中使用asm和endasm要求文件用SRC控制编译那么编译器就会生成汇编源文件然后可以用A51汇编273asm/endasm在包含文件中不允许在包含文件中不允许asm和endasm为了调试在包含文件不能有任何的可执行代码274非法的绝对标识符绝对地址标识符对位目标函数和局部函数不允许地址必须和目标的存储空间一致例如下面的声明是无效的因为间接寻址的范围是0x00到0xFFidata int _at_ 0x1000;278常数太大当浮点参数超出32位的浮点值范围就产生本错误32位IEEE值的范围是±1.175494E-38到±3.402823E+38279多次初始化试图多次初始化一个目标280没有使用符号/标号/参数在一个函数中声明了一个符号标号或参数但没有使用281非指针类型转换为指针引用的程序目标不能转换成一个指针282不是一个SFR引用本函数调用要求一个SFR作为参数283asmparms参数不适合寄存器参数不适合可用的CPU寄存器284<名称>在可覆盖空间函数不再可重入一个可重入函数包含对局部变量的明确的存储类型标识符函数不再完全可重入300注释未结束一个注释没有一个结束符*/301期望标识符一个预处理器命令期望一个标识符302误用#操作符字符操作符#没有带一个标识符303期望正式参数字符操作符#没有带一个标识符表示当前所定义的宏的一个正式参数名304错误的宏参数列表宏参数列表没有一个大括号逗号分开的标识符列表305string/char常数未结束一个字符串活字符常数是无效的典型的后引号丢失306宏调用未结束预处理器在收集和扩展一个宏调用的实际的参数时遇到输入文件的结尾307宏名称参数计算不匹配在一个宏调用中实际的参数数目和宏定义的参数数目不匹配本错误表示指定了太少的参数308无效的整数常数表达式一个if/elif命令的数学表达式包含一个语法错误309错误或缺少文件名在一个include命令中的文件名参数是无效的或没有310条件嵌套过多20源文件包含太多的条件编译嵌套命令最多允许20级嵌套311elif/else控制放错地方312endif控制放错地方命令elif else和endif只有在if ifdef或ifndef命令中是合法的313不能清除预定义的宏名称试图清除一个预定义宏用户定义的宏可以用#undef命令删除预定义的宏不能清除314#命令语法错误在一个预处理器命令中字符#必须跟一个新行或一个预处理器命令名例如if/define/ifdef…315未知的#命令名称预处理器命令是未知的316条件未结束到文件结尾endif的数目和if或ifdef的数目不匹配318不能打开文件文件名指定的文件不能打开319文件不是一个磁盘文件指定的文件不是一个磁盘文件文件不能编辑320用户自定义的内容本错误号未预处理器的#error命令保留#error命令产生错误号320送出用户定义的错误内容终止编译器生成代码321缺少<字符>在一个include命令的文件名参数中缺少结束符例如#include<stdio.h325正参名称重复一个宏的正参只能定义一次326宏体不能以##开始或结束##不能是一个宏体的开始或结束327宏宏名超过50个参数每个宏的参数数目不能超过50警告警告产生潜在问题的信息他们可能在目标程序的运行过程中出现警告不妨碍源文件的编译警告在列表文件中生成信息警告信息用下面的格式*** WARNING number IN LINE line OF file: warning message这里number错误号line在源文件或包含文件中的对应行号file错误产生的源或包含文件名warning message警告的内容下表按号列出了警告警告信息包括一个主要的内容和可能的原因和纠正措施173缺少返回表达式一个函数返回一个除了int类型以外的别的类型的值必须包含一个返回声明包括一个表达式为了兼容旧的程序对返回一个int值的函数不作检查182指针指向不同的目标一个指针关联了一个不同类型的地址185不同的存储空间一个目标声明的存储空间和前面声明的同样目标的存储空间不同196存储空间可能无效把一个无效的常数值分配给一个指针无效的指针常数是long或unsigned long编译器对指针采用24位3字节低16位代表偏移高8位代表选择的存储空间198sizeof返回零一个目标的大小计算结果为零如果目标是外部的或如果一个数组的维数没有全知道则值是错误的206缺少函数原型因为没有原型声明被调用的函数是未知的调用一个未知的函数通常是危险的参数的数目和实际要求不一样如果是这种情况函数调用不正确没有函数原型编译器不能检查参数的数目和类型要避免这种警告应在程序中包含函数的原型函数原型必须在函数被调用前声明注意函数定义自动生成原型209实参太少在一个函数调用中包含太少的实参219long常数被缩减为int一个常数表达式的值必须能被一个int类型所表示245未知的pragma本行被忽略#pragma声明是未知的因此整行程序被忽略258struct/union成员的存储空间方法参数的存储空间被忽略一个结构的成员或一个参数不能指定存储类型但是指针所指的目标可以包含一个存储类型例如struct vp{ char code c;int xdata i; };产生警告258struct v1{ char c;int xdata *i; };对struct是正确的声明259指针不同的存储空间两个要比较的指针没有引用相同的存储类型的目标260指针折断把一个指针转换为一个更小偏移区的指针转换会完成但大指针的偏移会折断来适应小指针261bit在重入函数一个reentrant函数不能包含bit因为bit标量不能保存在虚拟堆栈中265名称对非重入函数递归调用发现对一个非重入函数直接递归这可能是故意的但对每个独立的情况进行功能性检查通过生成的代码间接递归由连接/定位器检查271asm/endams控制放错地方asm和endasm不能嵌套endasm要求一个以asm声明开头的汇编块例如#pragma asm...汇编指令...#pragma endasm275表达式可能无效编译器检测到一个表达式不生成代码例如void test(void) {int i1,i2,i3;i1,i2,i3; /* 死表达式 */i1 << i3; /* 结果未使用 */}276常数在条件表达式编译器检测到一个条件表达式有一个常数值在大多数情况下是一个输入错误例如void test(void) {int i1,i2,i3;if( i1 = 1) i2 = 3; /* 常数被赋值 */while( i3 = 2); /* 常数被赋值 */}277指针有不同的存储空间一个typedef声明的存储空间冲突例如typedef char xdata XCC; /* 存储空间xdata */typedef XCC idata PICC; /* 存储空间冲突 */280符号/标号未使用一个符号或标号定义但未使用307宏名称参数计算不匹配一个宏调用的实参的数目和宏定义的参数数目不匹配表示用了太多的的参数过剩的参数被忽略317宏名称重新定义无效一个预定义的宏不能重新定义或清除参考138页的预定义宏常数322未知的标识符在一个#if命令行的标识符未定义等效为FALSE323期望新行发现多余字符一个#命令行正确但包含多余的非注释字符例如#include <stdio.h> foo。
DSP(TMS320C6713)入门之旅三、中断的理解和使用
学习一个芯片的功能时,我的建议是先学会如何用C语言点亮一个LED灯,然后就是学习一下使用他的中断,因为在做芯片的时候,各个厂家有自己的一套自己的方法。
所以使用中断的就必须了解很多概念,比如如何打开中断,如何安装自己的中断子服务程序,等等!先介绍一下什么叫中断:你在下象棋,突然电话响了,你回屋接电话,然后回来继续下象棋,这个过程就叫做中断响应过程(中断过程)。
CPU执行正常任务———————下象棋保护现场———————————-你已经想好要―将军‖,先在脑海中记下来。
中断发生———————————-电话响-中断服务程序—————————-接电话恢复现场———————————-回来后恢复刚才想法中断返回———————————-你回来继续下象棋中断屏蔽———————————-Boss 正在训话,要求所有电话关机,你不能接电话了。
非屏蔽中断——————————-你内急,即使是Boss 在训话,你还是得到外面去嘘嘘。
可屏蔽中断——————————-你在―闭关修炼‖,可以不受外界干扰所以我们在使用中断之前先得告诉CPU,我们要使用那个中断,当中断发生的时候,你的执行程序的去向(也就是中断服务子程序),最后在返回我们被中断的函数。
这样就完成了我们的中断历程!看看6713执行中断的流程:一、使能了全局中断和子中断,那么CPU每执行一条指令之前就去查询一下有没有中断被置位,如果有产生的,那么CPU就要跳转!二、软件把CPU内部的寄存器A0~A15,B0~B15,等等这些寄存器的值推入堆栈保存,把当前PC寄存器的值放入IRP寄存器中以备中断返回能找到当前被打断的位置(保存现场,中断函数前面得加interrupt关键字)三、CPU的PC指针读出中断向量表的地址,也就是把(ISTP寄存器的值+子中断向量偏移量)装入PC寄存器,这样就执行跳转。
四、在中断向量表里一般有就用跳转指令,这样就可以跳转到我们用C语言编写的中断服务子程序中。
Keil C51中using的用法
Keil C51 中using 的用法
Keil C51 中using 的用法在C51 中断程序中很多时候会用到using 关键字,但是很多人并不明白到底是什么意思,这里转帖一篇帮助大家理解。
如果在中断服务函数ISR 中使用寄存器,那么必须处理好using 的使用问题:
1、中断服务函数使用using 指定与主函数不同的寄存器组(主函数一般使用Register bank 0)。
2、中断优先级相同的ISR 可用using 指定相同的寄存器组,但优先级不同的ISR 必须使用不同的寄存器组,在ISR 中被调用的函数也要使用using 指定与中断函数相同的寄存器组。
3、如果不用using 指定,在ISR 的入口,c51 默认选择寄存器组0,这相当于中断服务程序的入口首先执行指令:
MOV PSW #0
这点保证了,没使用using 指定的高优先级中断。
可以中断使用不同的寄存器组的低优先级中断。
4、使用using 关键字给中断指定寄存器组,这样直接切换寄存器组而不必进行大量的PUSH 和POP 操作,可以节省RAM 空间,加速MCU 执行时间。
寄存器组的切换,总的来说比较容易出错,要对内存的使用情况有比
较清晰的认识,其正确性要由你自己来保证。
特别在程序中有直接地址访问的
时候,一定要小心谨慎!至于什么时候要用到寄存器组切换,一种情况是:当
你试图让两个(或以上)作业同时运行,而且它们的现场需要一些隔离的时候,就会用上了。
在ISR 或使用实时操作系统RTOS 中,寄存器非常有用。
寄存器组使用的原则:。
C51的中断函数
C51的中断函数C51的中断函数的格式为:void FuncIr(void) interrupt x [using y]以下是一些分析:一、中断函数是一个特殊的函数,没有参数,也没有返回值;但是程序中允不允许使用return呢?答案是允许的,不过只能用"return;",不能用"return(z);";用在一些需要快速返回的地方,对应的汇编会有多个ret语句,相对效率会高一些。
二、using的用法,using可以修饰任何函数,不过个人建议只用来修饰中断函数;简单的说,“using”会指定工作寄存器组,由于中断函数一般都是比较紧急的事情,有时一条语句都会斤斤计较,所以使用using切换寄存器组可以省去一些压栈的动作,由于51只有两级中断,同级中断不能被打断,因此,我们可以同级中断设成同样的寄存器组,从某种意义上来说,有一组寄存器是多余的。
同时个人建议中断函数应该使用using这个关键字。
三、中断中调用函数,首先要讨论中断函数中调用函数的必要性,前天在论坛上我和别人争论过这个问题,现在我还是这个观点:有些情况中断中调用函数还是必要的,这个时候是不是该调用函数,其实和普通函数差不多,首先是这个函数如果调用多次,或者要带一些参数什么的就更加必要的;前天有人跟我叫劲,说假如只调用一次且无参数无返回的函数要直接写,因为如果用函数,至少会增加CALL和RET两条语句,我不敢苟同,我是实际调试发现的,当你程序比较复杂时,你将那部分单独拉出来做成函数,可能代码和时间都会更好。
四、中断中调用的函数最好不要被中断外的其它函数调用,因为会出现“重复调用”的警告,有时这种调用是很致命的,有人说这个函数可以用reentrant来修饰,是的,的确可以这样解决,不过个人不建议这么做,也许这样会跟你减少很多堆栈空间,并且整个程序的优化要差很多,个人建议出现这种情况就把这个函数写两遍,分成两个函数分别调用。
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. 中断函数调用其他函数,则要保证使用相同的寄存器组,否则出错。
Linux设备树语法详解-中断【转】
Linux设备树语法详解-中断【转】Linux内核从3.x开始引⼊设备树的概念,⽤于实现驱动代码与设备信息相分离。
在设备树出现以前,所有关于设备的具体信息都要写在驱动⾥,⼀旦外围设备变化,驱动代码就要重写。
引⼊了设备树之后,驱动代码只负责处理驱动的逻辑,⽽关于设备的具体信息存放到设备树⽂件中,这样,如果只是硬件接⼝信息的变化⽽没有驱动逻辑的变化,驱动开发者只需要修改设备树⽂件信息,不需要改写驱动代码。
⽐如在ARM Linux内,⼀个.dts(device tree source)⽂件对应⼀个ARM的machine,⼀般放置在内核的"arch/arm/boot/dts/"⽬录内,⽐如exynos4412参考板的板级设备树⽂件就是"arch/arm/boot/dts/exynos4412-origen.dts"。
这个⽂件可以通过$make dtbs命令编译成⼆进制的.dtb ⽂件供内核驱动使⽤。
基于同样的软件分层设计的思想,由于⼀个SoC可能对应多个machine,如果每个machine的设备树都写成⼀个完全独⽴的.dts⽂件,那么势必相当⼀些.dts⽂件有重复的部分,为了解决这个问题,Linux设备树⽬录把⼀个SoC公⽤的部分或者多个machine共同的部分提炼为相应的.dtsi⽂件。
这样每个.dts就只有⾃⼰差异的部分,公有的部分只需要"include"相应的.dtsi⽂件, 这样就是整个设备树的管理更加有序。
我这⾥⽤`Linux4.8.5源码⾃带的dm9000⽹卡为例来分析设备树的使⽤和移植。
这个⽹卡的设备树节点信息在"Documentation/devicetree/bindings/net/davicom-dm9000.txt"有详细说明,其⽹卡驱动源码是"drivers/net/ethernet/davicom/dm9000.c"。
c语言interrupt用法
c语言interrupt用法在C语言中,可以使用中断(interrupt)来处理硬件设备的事件或特定的软件事件。
中断是一种硬件或软件产生的信号,它会打断当前正在执行的程序,并立即转移控制权到一个特定的中断处理程序。
以下是使用中断的一般步骤:1. 定义中断处理程序:- 中断处理程序是一个函数,用于处理中断事件。
- 可以使用关键字```__interrupt```或特定的中断修饰符(例如```__attribute__((interrupt))```)来标识该函数为中断处理程序。
- 通常,中断处理程序应该是短小、高效的,并尽量避免执行耗时操作。
2. 配置中断向量表:- 中断向量表是一个数据结构,用于将中断向量号(中断号)映射到相应的中断处理程序。
- 可以使用特定的语法来配置中断向量表,以确保当发生中断时,正确的中断处理程序被调用。
3. 初始化中断:- 在程序的初始化阶段,需要配置相关的硬件设备或设置相应的标志位,以启用或禁用中断。
- 通常,需要设置相关的中断控制器(例如PIC、NVIC)来使能或禁用特定的中断或中断源。
4. 处理中断:- 当中断事件发生时,硬件会自动触发中断,并将控制权转移到相应的中断处理程序。
- 在中断处理程序中,可以执行与中断相关的操作,例如读取中断源的数据、清除中断标志位、保存上下文等。
- 处理完中断事件后,可以使用特定的指令(例如```return from interrupt```)来返回到被中断的程序继续执行。
需要注意的是,中断处理程序应该尽量简洁高效,并且对共享资源(如全局变量)进行适当的保护,以避免竞态条件和数据不一致等问题。
此外,合理的中断优先级设置也非常重要,以确保高优先级的中断能够及时响应并处理。
举例说明c语言中断服务函数的语法
C语言中断服务函数的语法是在编写嵌入式系统时非常重要的一部分。
它可以帮助程序员在出现特定事件时及时响应并处理,从而提高系统的可靠性和效率。
一、基本语法在C语言中,中断服务函数的语法通常包括以下几个部分:1. 中断服务函数的声明:一般是在全局范围内使用关键字“void”声明,并在函数名前加上关键字“interrupt”或“__interrupt”。
2. 中断服务函数的定义:在函数定义中,需要使用适当的中断服务函数标志符(例如在Keil C中使用“__interrupt”)来告知编译器这是一个中断服务函数。
3. 中断服务函数的实现:根据具体的中断事件,程序员需要在中断服务函数中编写相应的处理代码,以响应中断事件并进行处理。
二、举例说明举例来说明C语言中断服务函数的语法,我们可以以Keil C为例进行讲解。
在Keil C中,可以通过以下步骤编写中断服务函数:1. 在全局范围内声明中断服务函数,例如:```cvoid interrupt PORT1_ISR(void);```2. 在代码中使用中断服务函数标志符“__interrupt”进行定义,例如:```cvoid __interrupt(PORT1_ISR) Port1_ISR(void){// 在此处编写中断服务函数的处理代码}```3. 在中断服务函数的实现中,可以根据具体的中断事件编写处理代码,例如:```cvoid __interrupt(PORT1_ISR) Port1_ISR(void){// 清除中断标志位P1IFG &= ~BIT0;// 在此处添加其他中断服务函数的处理代码}```三、个人观点和理解中断服务函数在嵌入式系统中起着至关重要的作用,它能够及时响应外部事件并进行相应的处理,从而提高系统的实时性和可靠性。
在编写中断服务函数时,需要充分理解中断的工作原理和具体的中断事件,同时也需要对C语言的语法有深入的了解,才能编写高质量的中断服务函数。
c51 using用法
MOV PSW #0
这点保证了,没使用 using 指定的高优先级中断。可以中断使用不同的寄存器组的低优先级中断。
4、 使用 using 关键字给中断指定寄存器组,这样直接切换寄存器组而不必进行大量的 PUSH 和 POP 操作,可以节省RAM空间,加速 MCU 执行时间。寄存器组的切换,总的来说比较容易出错,要对内存的使用情况有比较清晰的认识,其正确性要由你自己来保证。特别在程序中有直接地址访问的时候, 一定要小心谨慎!至于“什么时候要用到寄存器组切换”,一种情况是:当你试图让两个(或以上)作业同时运行,而且它们的现场需要一些隔离的时候,就会用上 了。在 ISR 或使用实时操作系统RTOS 中,寄存器非常有用。
IE寄存器 C51中的 8051的
的使能位 中断号 中断源
--------------------------------
IE.0 0 外部中断0
IE.1 1 定时器0 溢出
IE.2 2 外部中断1
IE.3 3 定时器Байду номын сангаас 溢出
IE.4 4 串口中断
IE.5 5 定时器2 溢出
有 了这一声明,编译器不需理会寄存器组参数的使用和对累加器A、状态寄存器、寄存器B、数据指针和默认的寄存器的保护。只要在中断程序中用到,编译器会把它 们压栈,在中断程序结束时将他们出栈。C51 支持所有 5 个 8051 标准中断从 0 到 4 和在 8051 系列(增强型)中多达 27 个中断源。
interrupt 和 using 在C51中断中的使用
8051 系列 MCU 的基本结构包括:32 个 I/O 口(4 组8 bit 端口);两个16 位定时计数器;全双工串行通信;6 个中断源(2 个外部中断、2 个定时/计数器中断、1 个串口输入/输出中断),两级中断优先级;128 字节内置RAM;独立的 64K 字节可寻址数据和代码区。中断发生后,MCU 转到 5 个中断入口处之一,然后执行相应的中断服务
中断中断优先级
. TF0,TF1:定时器/计数器0,1(T/C0,T/C1)溢出中断请求标志;
当T/C0,1计数溢出时由硬件置位(TF0/TF1=l);
当CPU响应中断由硬件清除(TFO/TF1=0).
三,与中断有关的寄存器
2,串行口控制寄存器SCON
TI RI
1→下降沿触发方式,INT0/INT1管脚上高到低的负跳变可引起中断;
0→电平触发方式, INT0/INT1管脚上低电平可引起中断.
. IE0,IE1:外部中断0,1请求标志位;
当外部中断0,l依据触发方式满足条件,产生中断请求时由硬件置位 (IE0/IE1=1);当CPU响应中断时由硬件清除(IE0/IE1= 0).
1→T/C0,T/Cl开中断;0→T/C0,T/Cl关中断.
. ES:串行口中断允许位;
1→串行口开中断;0→串行口关中断.
. ET2:定时器/计数器2(T/C2)溢出中断允许位;
1→T/C2开中断;0→T/C2关中断.
. EA:CPU开/关中断控制位.
1→CPU开中断.0→CPU关中断.
片内定时器/计数器0溢出中断请求;
片内定时器/计数器1溢出中断请求;
片内串行口发送/接收中断请求.
三,与中断有关的寄存器
1,定时/计数器控制寄存器TCON
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
D7 D6 D5 D4 D3 D2 D1 D0
. IT0,IT1:外部中断0,1触发方式选择位,由软件设置;
当T/C工作在计数器时,计数脉冲来自外部脉冲输入管脚T0(P3.4)或T1(P3.5),当T0或T1脚上负跳变时计数值加1.识别管脚上的负跳变需两个机器周期,即24个振荡周期.所以T0或T1脚输入的可计数外部脉冲的最高频率为1/24fosc,当晶振为12MHZ时,最高计数率为500kHz,高于此频率将计数出错.
interrupt函数使用
void INT0()interrupt 0 using 1{.........}interrupt 0 指明是外部中断0;interrupt 1 指明是定时器中断0;interrupt 2 指明是外部中断1;interrupt 3 指明是定时器中断1;interrupt 4 指明是串行口中断;using 0 是第0组寄存器;using 1 是第1组寄存器;using 2 是第2组寄存器;using 3 是第3组寄存器;51单片机内的寄存器是R0--R7(不是R0-R3)R0-R7在数据存储器里的实际地址是由特殊功能寄存器PSW里的RS1、RS0位决定的。
using 0时设置 RS1=0,RS0 =0,用第0组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。
R0(00H)....R7(07H)using 1时设置 RS1=0,RS0 =1,用第1组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。
R0(08H)....R7(0FH)using 2时设置 RS1=1,RS0 =0,用第2组寄存器,R0--R7的在数据存储区里的实际地址是08H-0FH。
R0(10H)....R7(17H)using 3时设置 RS1=1,RS0 =1,用第3组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。
R0(18H)....R7(1FH)比方说定时100ms,分别用查询法和中断法实现查询法#include<reg52.h>void main(){TMOD=0X01;//定时器0方式1TH0=(65536-10000)%256;//定时器器初值TL0=(65536-10000)/256;ET0=0;//关定时器0中断TR0=1;while(TF0==0);//若定时完成则中断标志位TF0为1,在此不断查询TF0 TR0=1;//完成定时关闭定时器while(1); //等待}中断法#include<reg52.h>void main(){TMOD=0X01;//定时器0方式1TH0=(65536-10000)%256;//定时器器初值TL0=(65536-10000)/256;EA=1;//开总中断ET0=1;//关定时器0中断TR0=1;//打开定时器while(1); //等待}void isr_timer0 interrupt 1{TR0=0;//关闭定时器}另一个实例:P3.2口接有一个按键,未按下为高电平,按下则为低电平,当按下键时点亮一个led灯查询法#include<reg52.h>sbit led=P1^1;//led是共阴极接法sbit key=P3^2//按键接到p3.0口void main(){led=0;//熄灭所有灯while(key==1);//没有键按下则等待(不断查询p3.0的状态)led=1;//点亮灯while(1);}中断法#include<reg52.h>sbit led=P1^1;//led是共阴极接法void main(){led=0;//熄灭所有灯while(1);}void isr_led interrupt 0{led0=1;//点亮灯}。
interrupt3的中断条件
interrupt3的中断条件
Interrupt3是一个由硬件设备发出的信号,是计算机系统中的一个中断。
它的主要作用是通知计算机系统,需要立即停止当前正在执行的任务,并且切换到另一个任务。
具体来说,当某个硬件设备发出中断信号时,计算机系统中的操作系统内核就会接收到中断信号,并执行相应的处理程序,以处理由硬件设备发出的中断信号。
因此,Interrupt3的中断条件就是硬件设备发出中断信号。
如需了解更多关于Interrupt3的中断条件的信息,建议查阅相关技术手册或咨询计算机专家。
interrupt、using关键字的用法
interrupt、using关键字的用法C语言在8051单片机上的扩展(interrupt、using关键字的用法)直接访问寄存器和端口定义sfr P0 0x80sfr P1 0x81sfr ADCON; 0xDEsbit EA 0x9F操作ADCON = 0x08 ;P1 = 0xFF ;io_status = P0 ;EA = 1 ;在使用了interrupt 1 关键字之后,会自动生成中断向量在ISR中不能与其他"后台循环代码"(the background loop code) 共享局部变量因为连接器会复用在RAM中这些变量的位置,所以它们会有不同的意义,这取决于当前使用的不同的函数复用变量对RAM有限的51来将很重要。
所以,这些函数希望按照一定的顺序执行而不被中断。
timer0_int() interrupt 1 using 2{unsigned char temp1 ;unsigned char temp2 ;executable C statements ;}"interrupt"声明表示向量生成在(8*n+3),这里,n就是interrupt参数后的那个数字这里,在08H的代码区域生成LJMP timer0_int 这样一条指令"using" tells the compiler to switch register banks on entry to an interrupt routine. This "context" switch is the fastest way of providing a fresh registerbank for an interrupt routine's local data and is to be preferred to stacking registers for very time-critical routines. Note that interrupts of the same priority can share a register bank, since there is no risk that they will interrupt each other.'using' 告诉编译器在进入中断处理器去切换寄存器的bank。
interrupt3的中断条件
interrupt3的中断条件Interrupt3是一种中断条件,它在特定的情况下触发中断程序的执行。
这种中断条件通常用于处理紧急情况或重要事件,以确保系统的稳定性和安全性。
下面将以Interrupt3的中断条件为题,进行创作,以人类的视角叙述。
标题:突如其来的电话让我心生疑惑我正坐在办公室里,专心投入到工作中。
突然,电话铃声划破了宁静的空气,我有些意外地接起了电话。
“喂,你好,请问是XXX公司吗?”电话那头传来一个陌生男声。
“是的,这里是XXX公司,请问你有什么事情吗?”我礼貌地回答道。
“对不起,打扰了。
我是警察局的警官,我们收到了一份紧急报警,需要你们的协助。
”电话那头的声音听起来紧张又严肃。
我心中顿时升起一股不安的感觉,紧张地问道:“发生了什么事情?我们能够如何帮助你们?”警官的声音稍稍缓和了一些:“我们接到了一起疑似炸弹威胁的报警,地址就是你们公司的办公楼。
我们需要你们立即疏散所有员工,确保他们的安全。
”听到这个消息,我顿时感到一阵恐慌。
我赶紧站起身来,大声呼喊着:“大家听我说,我们收到了一份疑似炸弹威胁的报警,请大家迅速有序地离开办公楼,确保自己的安全!”办公室里的员工们纷纷起身,有些人神情惊恐,有些人则保持着冷静。
大家都聚集在一起,互相安慰和鼓励。
紧张的气氛弥漫在空气中,让人无法忽视。
我迅速联系了公司的安全人员,并向他们汇报了警察局的电话内容。
安全人员立即采取了必要的措施,通知了警方,并开始疏散员工。
在紧急情况下,每个人都展现出了自己的冷静和勇敢。
大家有条不紊地从楼梯走下,尽快离开办公楼。
虽然人们的脸上都带着紧张和担忧,但大家还是保持着秩序,尽量减少恐慌和混乱。
我们在公司外面的安全区域聚集在一起,等待警方的进一步指示。
时间仿佛变得缓慢起来,每一秒钟都让人感到漫长。
经过一番紧张的等待,警方最终确认了我们公司办公楼的安全。
原来,那通电话只是一起恶作剧。
虽然这次中断让我们经历了一场惊心动魄的紧急疏散,但它也提醒了我们重视安全意识,时刻保持警惕。
interrupt interrupted isinterrupt方法对比、区别与联系
interrupt interrupted isinterrupt方法对比、区别与联系`interrupt`、`interrupted` 和`isInterrupt` 方法是在Java 编程语言中与线程中断相关的三个方法。
它们在处理线程中断时有所不同,但同时又有一定的联系。
下面详细介绍这三个方法的区别和联系:1. interrupt(中断)方法:`interrupt` 方法位于Thread 类中,用于中断当前线程。
当一个线程调用该方法时,它会立即停止执行,并释放锁资源。
但是,与其他线程之间的通信不会受到影响。
也就是说,如果一个线程调用了`interrupt` 方法,那么它会被中断,但不会影响其他线程的正常运行。
2. interrupted(中断状态)方法:`interrupted` 方法也位于Thread 类中,它用于检查当前线程是否被中断。
当一个线程调用`interrupted` 方法并返回`true` 时,说明该线程已经被中断。
如果返回`false`,则表示当前线程尚未被中断。
此方法主要用于判断线程的中断状态,不能用于中断线程。
3. isInterrupt(中断检查)方法:`isInterrupt` 方法位于ThreadInterruptor 类中,它用于检查指定的线程是否处于中断状态。
与`interrupted` 方法类似,该方法也用于判断线程的中断状态,不能用于中断线程。
区别与联系:这三个方法的主要区别在于它们的作用和用途不同。
`interrupt` 方法用于中断线程,使其立即停止执行;而`interrupted` 和`isInterrupt` 方法主要用于检查线程的中断状态。
然而,它们之间也存在一定的联系,因为它们都与线程的中断相关。
在实际编程中,开发者可以使用这些方法来处理线程中断,从而实现多线程编程的灵活性和可靠性。
例如,当一个线程需要等待其他线程完成任务时,可以使用`interrupt` 方法中断等待线程,使其释放资源。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
在默认状态下,func使用寄存器组0(BANK0),那么当int_0调用func时是否存在当传递参数时会造成参数传递错误?
谢谢!
如果在中断服务函数 ISR 中使用寄存器,那么必须处理好 using 的使用问题:
1、中断服务函数使用 using 指定与主函数不同的寄存器组(主函数一般使用 Register bank 0)。
举一例子:当需要在中断内和中断外调用同一个函数,假定按照程序的流程控制,不会出现函数的递归调用现象,这样的调用会不会出现问题?若确定不会发生重入情况,则有以下两种情况:
1、如果 ISR 和主程序使用同一寄存器组(主程序缺省使用BANK 0,若 ISR 没有使用 using 为其指定寄存器区,则缺省也使用 BANK 0),则不需其他设置。
void intersvr0(void) interrupt 0 using 1(2008-01-11 16:47:33)转载▼标签: 杂谈 分类: 技术文章(电子)
void←这里的void表示函数类型
interrupt 0 ←这里的0表示中断源编号
using 1 ←这里的1表示选用的寄存器组别
串行口TI/RI 00023H TI/RI
中断优先级别从上到下依次降低
8051 系列 MCU 的基本结构包括:32 个 I/O 口(4 组8 bit 端口);两个16 位定时计数器;全双工串行通信;6 个中断源(2 个外部中断、2 个定时/计数器中断、1 个串口输入/输出中断),两级中断优先级;128 字节内置RAM;独立的 64K 字节可寻址数据和代码区。中断发生后,MCU 转到 5 个中断入口处之一,然后执行相应的中断服务
2、中断优先级相同的ISR 可用 using 指定相同的寄存器组,但优先级不同的 ISR 必须使用不同的寄存器组,在 ISR 中被调用的函数也要使用 using 指定与中断函数相同的寄存器组。
3、如果不用 using 指定,在 ISR 的入口,C51 默认选择寄存器组0,这相当于中断服务程序的入口首先执行指令:
在MCS-51单片机中,单片机类型不同,中断源个数也有差别.例如8051有5个中断源,8052有6个中断源.现以8051为例
中断源 中断服务入口地址 中断标志
外部中断INT0 0003H IE0
定时器T0 000BH TF0
外部中断INT1 0013H IE1
定时器T1 001BH TF1
2、如果 ISR 和主程序使用不同的寄存器组(主程序缺省使用BANK 0,ISR 使用 using 指定了其他 BANK),则被调用函数必须放在:
#pragma NOAREGS
#pragma AREGS
控制参数对中,指定编译器不要对该函数使用绝对寄存器寻址方式;或者也可在 Options->C51,选中“Don't use absolute register accesses”,使所有代码均不使用绝对寄存器寻址方式(这样,执行效率将稍有降低)。不论以上的哪一种情况,编译器均会给出重入警告,需手工更改 OVERLAY 参数,做重入说明。
关于using:
您在文中说明“这一做法的缺点是所有调用中断的过程都必须使用指定的同一个寄存器组”是不是这个意思?
举个例子来说:
定义一个函数
void func(unsigned char i) {
...
if(++i==0x12) {
...
}
...
}
有如下一个中断函数
void int_0(void) interrupt 0 using 1 {
寄存器组使用的原则:
1、8051 的最低32 个字节分成 4 组 8 寄存器。分别为寄存器R0 到R7。寄存器组由PSW 的低两位选择。在 ISR 中,MCU 可以切换到一个不同的寄存器组。对寄存器组的访问不可位寻址,C51 编译器规定使用 using 或 禁止中断的函数(#pragma disable)均不能返回 bit 类型的值。
处理程序。中断程序的入口地址被编译器放在中断向量中,中断向量位于程序代码段的最低地址处,注意这里的串口输入/输出中断共用一个中断向量。8051的中断向量表如下:
中断源 中断向量
---------------------------
上电复位 0000H
外部中断0 0003H
定时器0 溢出 000BH
using 关键字用来指定中断服务程序使用的寄存器组。用法是:using 后跟一个0 到3 的数,对应着 4 组工作寄存器。一旦指定工作寄存器组,默认的工作寄存器组就不会被压栈,这将节省 32 个处理周期,因为入栈和出栈都需要 2 个处理周期。这一做法的缺点是所有调用中断的过程都必须使用指定的同一个寄存器组,否则参数传递会发生错误。因此对于using,在使用中需灵活取舍。
3、在 ISR 中调用其它函数,必须和中断使用相同的寄存器组。当没用 NOAREGS 命令做明确的声明,编译器将使用绝对寄存器寻址方式访问函数选定(即用 using 或 REGISTERBANK 指定)的寄存器组,当函数假定的和实际所选的寄存器组不同时,将产生不可预知的结果,从而可能出现参数传递错误,返回值可能会在错误的寄存器组中。
MOV PSW #0
这点保证了,没使用 using 指定的高优先级中断。可以中断使用不同的寄存器组的低优先级中断。
4、使用 using 关键字给中断指定寄存器组,这样直接切换寄存器组而不必进行大量的 PUSH 和 POP 操作,可以节省RAM空间,加速 MCU 执行时间。寄存器组的切换,总的来说比较容易出错,要对内存的使用情况有比较清晰的认识,其正确性要由你自己来保证。特别在程序中有直接地址访问的时候,一定要小心谨慎!至于“什么时候要用到寄存器组切换”,一种情况是:当你试图让两个(或以上)作业同时运行,而且它们的现场需要一些隔离的时候,就会用上了。在 ISR 或使用实时操作系统RTOS 中,寄存器非常有用。
外部中断1 0013H
定时器1 溢出 001BH
串行口中断 0023H
定时器2 溢出 002BH
interrupt 和 using 都是 C51 的关键字。C51 中断过程通过使用 interrupt 关键字和中断号(0 到 31)来实现。中断号指明编译器中断程序的入口地址中断序号对应着 8051中断使能寄存器IE 中的使能位,对应关系如下:
2、主程序(main函数)使用一组,如 bank 0;低中断优先级的所有中断均使用第二组,如 bank 1;高中断优先级的所有中断均使用再另外一组,如 bank 2。显然,同级别的中断使用同一组寄存器不会有问题,因为不会发生中断嵌套;而高优先级的中断则要使用与低优先级中断不同的一组,因为有可能出现在低优先级中断中发生高优先级中断的情况。编译器会自动判断何时可使用绝对寄存器存取。
IE寄存器 C51中的 8051的
的使能位 中Leabharlann 号 中断源 --------------------------------
IE.0 0 外部中断0
IE.1 1 定时器0 溢出
IE.2 2 外部中断1
IE.3 3 定时器1 溢出
IE.4 4 串口中断
IE.5 5 定时器2 溢出
有了这一声明,编译器不需理会寄存器组参数的使用和对累加器A、状态寄存器、寄存器B、数据指针和默认的寄存器的保护。只要在中断程序中用到,编译器会把它们压栈,在中断程序结束时将他们出栈。C51 支持所有 5 个 8051 标准中断从 0 到 4 和在 8051 系列(增强型)中多达 27 个中断源。
3、还有一种办法:如果被调用函数的代码不是很长,还是将该函数复制一份,用不同的函数名代替,这种情况适合ROM有足够多余的空间。
因此,对using关键字的使用,如果没把握,宁可不用,交给编译系统自己去处理好了