当前位置:文档之家› MSP430G2433_IO口中断函数

MSP430G2433_IO口中断函数

MSP430G2433_IO口中断函数
MSP430G2433_IO口中断函数

#include "io430.h"

#include "in430.h"

//-----------------------------------------------------------------------------

//主函数

void main (void)

{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ;

P2REN |= GDO0_PIN;

P2IES |= GDO0_PIN; //使能GDO0中断发生在下降沿P2IFG = 0x00; //中断寄存器清零

P2IE |= GDO0_PIN; //中断使能

_EINT();

while(1)

{

}

}

#pragma vector=PORT2_VECTOR

__interrupt void p2_ISR (void)

{

P2IFG = 0X00;//清中断寄存器,

}

中断管理函数

中断管理函数 CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有76个中断,包括16个内核中断和60个可屏蔽中断,具有16级可编程的中断优先级。而我们常用的就是这60个可屏蔽中断,所以我们就只针对这60个可屏蔽中断进行介绍。 在MDK内,与NVIC相关的寄存器,MDK为其定义了如下的结构体: typedef struct { vu32 ISER[2]; u32 RESERVED0[30]; vu32 ICER[2]; u32 RSERVED1[30]; vu32 ISPR[2]; u32 RESERVED2[30]; vu32 ICPR[2]; u32 RESERVED3[30]; vu32 IABR[2]; u32 RESERVED4[62]; vu32 IPR[15]; } NVIC_TypeDef; STM32的中断在这些寄存器的控制下有序的执行的。了解这些中断寄存器,你才能方便的使用STM32的中断。下面重点介绍这几个寄存器: ISER[2]:ISER全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。上面说了STM32的可屏蔽中断只有60个,这里用了2个32位的寄存器,总共可以表示64个中断。而STM32只用了其中的前60位。ISER[0]的

bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~59;这样总共60个中断就分别对应上了。你要使能某个中断,必须设置相应的ISER位为1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO口映射等设置才算是一个完整的中断设置)。具体每一位对应哪个中断,请参考 stm32f10x_nvic..h里面的第36行处。 ICER[2]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与ISER的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和ICER一样。这里要专门设置一个ICER来清除中断位,而不是向ISER写0来清除,是因为NVIC的这些寄存器都是写1有效的,写0是无效的。具体为什么这么设计,请看《CM3权威指南》第125页,NVIC概览一章。 ISPR[2]:全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和ISER是一样的。通过置1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写0是无效的。 ICPR[2]:全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。其作用与ISPR相反,对应位也和ISER是一样的。通过设置1,可以将挂起的中断接挂。写0无效。 IABR[2]:全称是:Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和ISER一样,如果为1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。 IPR[15]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32的中断分组与这个寄存器组密切相关。IPR寄存器组由15个32bit的寄存器组成,每个可屏蔽中断占用8bit,这样总共可以表示15*4=60个可屏蔽中断。刚好和STM32的可屏蔽中断数相等。IPR[0]的[31~24],[23~16],[15~8],[7~0]分别对应中中断3~0,依次类推,总共对应60个外部中断。而每个可屏蔽中断占用的8bit并没有全部使用,而是只用了高4位。这4位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据SCB->AIRCR中中断分组的设置来决定。 这里简单介绍一下STM32的中断分组:STM32将中断分为5个组,组0~4。该分组的设置是由SCB->AIRCR寄存器的bit10~8来定义的。具体的分配关系如下表所示:

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

几种单片机的中断函数写法 写单片机程序,中断是免不了的。我比较喜欢用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)”的形式的函数。而且光看中断向量名一般都能知道是哪个中断源产生,再写个中断函数名作解释似乎有点重复。对于keil c用中断向量号的形式来表示中断源,感觉有点麻烦,记住中断源的中断号比记中

中断异常处理流程

计算机体系结构中,异常或者中断是处理系统中突发事件的一种机制,几乎所有的处理器都提供这种机制。异常主要是从处理器被动接受的角度出发的一种描述,指意外操作引起的异常。而中断则带有向处理器主动申请的意味。但这两种情况具有一定的共性,都是请求处理器打断正常的程序执行流程,进入特定程序的一种机制。若无特别说明,对“异常”和“中断”都不作严格的区分。本文结合经过实际验证的代码对ARM9中断处理流程进行分析,并设计出基于S3C2410芯片的外部中断处理程序。 1.异常中断响应和返回 系统运行时,异常可能会随时发生。当一个异常出现以后,ARM微处理器会执行以下几步操作: 1) 将下一条指令的地址存入相应连接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。 2)将CPSR复制到相应的SPSR中。 3)根据异常类型,强制设置CPSR的运行模式位。 4) 强制PC从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。 这些工作是由ARM内核完成的,不需要用户程序参与。异常处理完毕之后,ARM微处理器会执行以下几步操作从异常返回: 1)将连接寄存器LR的值减去相应的偏移量后送到PC中。 2)将SPSR复制回CPSR中。 3) 若在进入异常处理时设置了中断禁止位,要在此清除。 这些工作必须由用户在中断处理函数中实现。为保证在ARM处理器发生异常时不至于处于未知状态,在应用程序的设计中,首先要进行异常处理。采用的方式是在异常向量表中的特定位置放置一条跳转指令,跳转到异常处理程序。当ARM处理器发生异常时,程序计数器PC会被强制设置为对应的异常向量,从而跳转到异常处理程序。当异常处理完成以后,返回到主程序继续执行。可以认为应用程序总是从复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。 2.异常处理程序设计 2.1 异常响应流程

串口中断服务函数集

串口中断服务函数集 https://www.doczj.com/doc/6116603435.html, 2003-4-22 电子工程师网站 //本函数集来自“51单片机世界”,作者斑竹丁丁(聂小猛)。 //主页地址https://www.doczj.com/doc/6116603435.html, //串口中断服务程序,仅需做简单调用即可完成串口输入输出的处理 //出入均设有缓冲区,大小可任意设置。 //可供使用的函数名: //char getbyte(void);从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。 //getline(char idata *line, unsigned char n); 获取一行数据回车结束,必须定义最大输入字符数 //putbyte(char c);放入一个字节到发送缓冲区 //putbytes(unsigned char *outplace,j);放一串数据到发送缓冲区,自定义长度//putstring(unsigned char code *puts);发送一个定义在程序存储区的字符串到串口 //puthex(unsigned char c);发送一个字节的hex码,分成两个字节发。 //putchar(uchar c,uchar j);输出一个无符号字符数的十进制表示,必须标示小数点的位置,自动删除前面无用的零 //putint(uint ui,uchar j);输出一个无符号整型数的十进制表示,必须标示小数点的位置,自动删除前面无用的零 //delay(unsigned char d); 延时n x 100ns //putinbuf(uchar c);人工输入一个字符到输入缓冲区 //CR;发送一个回车换行 //********************************************************************** *** #include #define uchar unsigned char #define uint unsigned int #define OLEN 32 /* size of serial transmission buffer */ idata unsigned char outbuf[OLEN]; /* storage for transmission buffer */ unsigned char idata *outlast=outbuf; //最后由中断传输出去的字节位置unsigned char idata *putlast=outbuf; //最后放入发送缓冲区的字节位置 #define ILEN 12 /* size of serial receiving buffer */ idata unsigned char inbuf[ILEN]; unsigned char idata *inlast=inbuf; //最后由中断进入接收缓冲区的字节位置unsigned char idata *getlast=inbuf; //最后取走的字节位置 bit outbufsign0; //最后一个数据覵BUF发完标志发完=0 bit outbufsign; //输出缓冲区非空标志有=1 bit inbufsign; //接收缓冲区非空标志有=1 bit inbufful; //输入缓冲区满标志满=1

中断问题(详解)

概念:引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统(中断机构)。 80C51的中断系统有5个中断源,2个优先级,可实现二级中断嵌套(就是可以在嵌套过程中再次响应嵌套)。 中断源 1、INT0(P3.2),外部中断1。可由IT0(TCON.0)选择其为低电平有效还是下降沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志IE0(TCON.1)置1,向CPU 申请中断。 2、INT1(P3.3),外部中断2。可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置1,向CPU 申请中断。 3、TF0(TCON.5),片内定时/计数器T0溢出中断请求标志。当定时/计数器T0发生溢出时,置位TF0,并向CPU申请中断。 4、TF1(TCON.7),片内定时/计数器T1溢出中断请求标志。当定时/计数器T1发生溢出时,置位TF1,并向CPU申请中断。 5、RI(SCON.0)或TI(SCON.1),串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。 中断请求标志 1、TCON的中断标志 IT0(TCON.0):外部中断0触发方式控制位。 ●当IT0=0时:为电平触发方式。 ●当IT0=1时:为边沿触发方式(下降沿有效)。 IE0(TCON.1):外部中断0中断请求标志位。 IT1(TCON.2):外部中断1触发方式控制位。 IE1(TCON.3):外部中断1中断请求标志位。

单片机 中断函数 (1)

中断函数的使用:《单片机C语言编程与实例》 中断函数通过使用interrupt关键字和中断编号0-4来实现。 使用该扩展属性的函数声明语法如下: 返回值函数名interrupt n N对应中断源的编号 中断编号告诉编译器中断程序的入口地址,它对应者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口电量发光二极管,然后外部输入一脉冲串,则发光二极管亮、暗交替

STM32的基本概念及中断应用

STM32的基本概念及中断应用 1、基本概念 ARMCoetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组 第0组:所有4bit用于指定响应优先级; 第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级; 第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级; 第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级; 第4组:所有4位用于指定抢占式优先级。 所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。 有几点需要注意的是:

关于中断服务函数里面是否可以调用其他函数的问题

的值已经改变,从而导致程序运行不正确,反过来亦然。另一方面,func()与TaskB有直接的调用关系,因而其局部变量b与c不会被互相覆盖,但也不能保证func的局部变量c不会与TaskA或其他任务的局部变量形成可覆盖关系。 根据上述分析我们很容易就能够判断出TaskA和TaskB这两个函数是不可重入的(当然,func也不可重入)。那么如何让函数成为可重入函数呢?C51编译器采用了一个扩展关键字reentrant作为定义函数时的选项,需要将一个函数定义为可重入函数时,只要在函数后面加上关键字reentrant即可。厦门城论坛z' V- \0 L/ Z2 A. G) j 与非可重入函数的参数传递和局部变量的存储分配方法不同,C51编译器为可重入函数生成一个模拟栈(相对于系统堆栈或是硬件堆栈来说),通过这个模拟栈来完成参数传递和存放局部变量。模拟栈以全局变量?C_IBP、?C_PBP和?C_XBP作为栈指针(系统堆栈栈顶指针为SP),这些变量定义在DATA地址空间,并且可在文件startup.a51中进行初始化。根据编译时采用的存储器模式,模拟栈区可位于内部(IDATA)或外部(PDATA或XDATA)存储器中。如表1所示: 表1 s. h; j5 s) j- _4 @ 厦门电子城厦门城电子零件单片机电子,xmecity,电子制作,DIY,电脑元件,9 A/ c6 `2 `6 M4 | 注意:51系列单片机的系统堆栈(也叫硬件堆栈或常规栈)总是位于内部数据存储器中(SP为 8位寄存器, 只能指向内部),而且是“向上生长”型的(从低地址向高地址),而模拟栈是“向下生长”型的。https://www.doczj.com/doc/6116603435.html,, g! c) @% u( z) M/ r: x7 w 1、可重入函数参数传递过程剖析 T0 T$ T3 J. R# e 在进入剖析之前,先简单讲讲c51函数调用时参数是如何传递的。简单来说,参数主要是通过寄存器R1~R7来传递的,如果在调用时,参数无寄存器可用或是采用了编译控制指令“NOREGPARMS”,则参数的传递将发生在固定的存储器区域,该存储器区域称为参数传递段,其地址空间取决于编译时所选择的存储器模式。利用51单片机的工作寄存器最多传递3个参数,如表2所示。 表二 + D0 N+ f2 J2 X' ]. j 举两个例子:厦门城论坛6 }0 W( O: |- V func1(int a):“a”是第一个参数,在R6,R7中传递; func2(int b,int c, int *d):“b”在R6,R7中传递,“c”在R4,R5中传递,“*d”则在R1,R2,R3中传递。厦门电子城厦门城电子零件单片机电子xmecity, 电子制作,DIY,电脑元件,2 t, B$ L$ b9 D+ z7 U0 P x! G0 r

单片机_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(接收中断请求标志位)必须由软件清零。 (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 串行口中断 (在上一篇文章中讲到的ROM前43个存储单元就是他们,这5个中断源的中断入口地址为: 这40个地址用来存放中断处理程序的地址单元,每一个类中断的存储单元只有8B,显然不

C语言的定时器中断程序

C语言的定时器中断程序 #include #define uint unsigned int #define uchar unsigned char uchar code table[]= {0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; uchar aa,num; void main() { aa=0; num=0; TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1;

TR0=1; P2=0xf0; P0=0x3f; while(1) { if(aa==10) { aa=0; num++; if(num==10) { num=0; } P2=0xf0; P0=table[num]; } } } void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256;

aa++; } void timer0(void) interrupt 1 using 3 //中断部分代码,见下文的释疑{ …………… } 释疑:void Timer0() interrupt 1 using 1 Timer0 是函数名,随便取的 interrupt xx using y 跟在interrupt 后面的xx 值得是中断号,就是说这个函数对应第几个中断端口,一般在51中 0 外部中断0 1 定时器0 2 外部中断1 3 定时器1 4 串行中断 实际上编译的时候就是把你这个函数的入口地址方到这个对应中断的跳转地址 using y 这个y是说这个中断函数使用的那个寄存器组,51里面一般有4组 r0 -- r7寄存器,一共有32个,看看原码、补码就知道。正数的补码是对应的二进制数,符号位为零,负数的补码是它的绝对值对应的二进制数按位取反再加一,符号位为一。

中断服务程序流程图

第一讲: 第六章I/O接口原理-接口、端口、编址 回顾:微机系统的层次结构,CPU、主机、接口电路及外部设备之间的结构关联,输入/输出的一般概念。 重点和纲要:微机系统主机与外部设备之间的数据传送,包括I/O端口的寻址方式,输入/输出的传送控制方式。 讲授内容: 6. 1 输入/输出数据的传输控制方式 一、输入/输出的一般概念 1.引言 输入/输出是微机系统与外部设备进行信息交换的过程。输入/输出设备称为外部设备,与存储器相比,外部设备有其本身的特点,存储器较为标准,而外部设备则比较复杂,性能的离散性比较大,不同的外部设备,其结构方式不同,有机械式、电动式、电子式等;输入/输出的信号类型也不相同,有数字信号,也有模拟信号;有电信号,也有非电信号;输入/输出信息的速率也相差很大。因此,CPU与外部设备之间的信息交换技术比较复杂。 CPU与外设之间的信息交换,是通过它们之间接口电路中的I/O端口来进行的,由于同一个外部设备与CPU之间所要传送的信息类型不同,方向不同,作用也不一样(例如数据信息、状态信息、控制信息、输入/输出等),所以接口电路中可以设置多个端口来分别处理这些不同的信息。 2.输入/输出端口的寻址方式 微机系统采用总线结构形式,即通过一组总线来连接组成系统的各个功能部件(包括CPU、内存、I/O端口),CPU、内存、I/O端口之间的信息交换都是通过总线来进行的,如何区分不同的内存单元和I/O端口,是输入/输出寻址方式所要讨论解决的问题。

根据微机系统的不同,输入/输出的寻址方式通常有两种形式:(1).存储器对应的输入、输出寻址方式 这种方式又称为存储器统一编址寻址方式或存储器映象寻址方式。 方法:把外设的一个端口与存储器的一个单元作同等对待,每一个I/O端口都有一个确定的端口地址,CPU与I/O端口之间的信息交换,与存储单元的读写过程一样,内存单元与I/O端口的不同,只在于它们具有不同的的地址。优点: ①CPU对I/O端口的读/写操作可以使用全部存储器的读/写操作指令,也可 以用对存储器的不同寻址方式来对I/O端口中的信息,直接进行算术、逻辑运算及循环、移位等操作。 ②内存与外设地址的分配,可以用统一的分布图。 ③不需要专门的输入、输出操作指令。 缺点: ①内存与I/O端口统一编址时,在地址总线根数一定的情况下,使系统中 实际可以直 接寻址的内存单元数减少。 ②一般情况下,系统中I/O端口数远小于内存单元数,所以在用直接寻址方 式来寻址这些端口时,要表示一个端口地址,必须用与表示内存单元地址相同的字节数,使得指令代码较长,相应地读/写执行时间也较长,这对提高系统的运行速度是不利的。 Mortorola公司的M6800CPU等均采用这种寻址I/O端口的方式。 3. CPU与外设之间所传送的信息类型 CPU与I/O端口之间所交换的信息,可以有下列几种类型: ①数据信息:包括数字量、模拟量、开关量等,可以输入、也可以输出 ②状态信息:这是I/O端口送给CPU的有关本端口所对应的外设当前状态 的信息。供CPU进行分析、判断、决策。 ③控制信息:这是CPU送给I/O端口的控制命令,使相应的外部设备完成 特定的操作。 数据信息、状态信息和控制信息是不同类型的信息,它们所起的作用也不一样。但在8086/8088微机系统中,这三种不同类型的信息的输入、输出过程是相同的。为了加以区分,可以使它们具有不同的端口地址,在端口地址相同的情况下,可以规定操作的顺序,或者在输入/输出的数据中设置特征位。

外部中断函数

程序1:带标志位的程序 #include unsigned char a=0xfe,b,c; bit biaozhi=0; void delay(); main() { EA=1; EX0=1; IT0=1;//?D??3?ê??ˉ while(1) { if(biaozhi==1) { P2=a; delay(); b=a<<1; c=a>>7; a=b|c; //111,11110 if(a==0xfe) a=0xbf; biaozhi=0; } else P2=0xff; } } ex0() interrupt 0 { biaozhi=1; } void delay() { unsigned int x,y; for(x=2000;x>0;x--) for(y=3000;y>0;y--); } 程序2 :不带标志位的程序 #include unsigned char a=0xfe,b,c; bit biaozhi=0; void delay(); main()

{ EA=1; EX0=1; IT0=1;//?D??3?ê??ˉ while(1) { P2=0xff; } } ex0() interrupt 0 { unsigned char num; for(num=8;num>=1;num--) { P2=a; delay(); b=a<<1; c=a>>7; a=b|c; } } void delay() { unsigned int x,y; for(x=2000;x>0;x--) for(y=3000;y>0;y--); } 程序三:带标志位,小灯左右移动的程序 #include unsigned char a=0xfe,b,c,i,j; bit biaozhi=0; void delay(); main() { EA=1; EX0=1; IT0=1;//?D??3?ê??ˉ//按照1-2-3-4-5-6-7-8-7-6-5-4-3-2-1小灯移动一次while(1) { if(biaozhi==1) { for(i=8;i>0;i--) { P2=a;

中断控制

微机原理实验报告 实验名称:并行I/O接口实验 院系: 班级: 姓名: 学号: 一. 实验目的 掌握GPIO IP核的工作原理和使用方法 掌握中断控制方式的IO接口设计原理 掌握中断程序设计方法 掌握IO接口程序控制方法 查询方式 中断方式 延时方式

二. 实验环境 UltraEdit ; XilinxISE。 三、实验内容 最小系统的建立,查询方式与中断方式在counse显示独立开关操作总线连接方式 Gpio内部框图

中断寄存器 硬件电路框图

四.实验内容 1.最小系统的建立 打开Xilinx Platform studio平台,选择相关参数,建立相关文件。 将FPGA内存改为32K,添加UART类型接口,其他选择默认配置。 修改时钟设置:删除Exterinal Port 中的CLK_P与CLK_N并添加Clock_generator_0中的CLKIN修改名称为CLK。同时再将RS232的输入输出端口名修改RsRxRsTx。 最后再添加约束文件,约束引脚,保存。产生bit流,最小系统就建好了。 NET "CLK" LOC="E3"|IOSTANDARD="LVCMOS33"; NET "RESET" LOC="E16"|IOSTANDARD="LVCMOS33"; NET "RsRx" LOC="C4"|IOSTANDARD="LVCMOS33"; NET "RsTx" LOC="D4"|IOSTANDARD="LVCMOS33"; #OUTOUT 2.在最小系统基础上添加相应的IP核。分别是8位的Button,4位的Dip,中断 控制核(AXI Interrupt Controller IP)并与micorblace的中断信号线相连(刚开始我没有做这一步,结果一节课过去了,却怎么也做不出来),将Button,Dip添加为他的中断源,button Dip设置为仅输入其他端都设置为无连接。最后再添加相应的约束文件并保存。 NET "Dip_GPIO_IO_I_pin<0>" LOC="U9"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<1>" LOC="U8"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<2>" LOC="R7"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<3>" LOC="R6"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<4>" LOC="R5"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<5>" LOC="V7"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<6>" LOC="V6"|IOSTANDARD="LVCMOS33"; NET "Dip_GPIO_IO_I_pin<7>" LOC="V5"|IOSTANDARD="LVCMOS33"; NET "Button_GPIO_IO_I_pin<0>" LOC="F15"|IOSTANDARD="LVCMOS33";

IRQ0中断处理全过程

IRQ0中断处理全过程 1:系统注册IRQ0(时钟中断)的下半部分的处理过程。 在\kernel\sched.c的sched_init函数中 init_bh(TIMER_BH, timer_bh);/*TIMER_BH==0*/ init_bh(TQUEUE_BH, tqueue_bh);/*TQUEUE_BH==2*/ init_bh(IMMEDIATE_BH, immediate_bh);/*IMMEDIATE_BH==11*/ init_bh(TIMER_BH, timer_bh)把timer_bh函数注册为定时器的下半部分。 来看看init_bh是怎么处理的。 去掉一些加琐解琐的东西,就变成以下了。 void init_bh(int nr, void (*routine)(void)) { bh_base[nr] = routine; atomic_set(&bh_mask_count[nr], 0); bh_mask |= 1 << nr; } 就是简单的设置bh_base和bh_mask. 看看这些的定义: atomic_t bh_mask_count[32]; unsigned long bh_active = 0; unsigned long bh_mask = 0; void (*bh_base[32])(void); bh_base[] 31 bh_active 0 Bottom half handler(timer_bh) 31 bh_mask 0 不好意思,画的这么难看:P 如果bh_mask的第N位被置为1,则表明bh_base[]中的第N个指针指向了一个Bottom half 例程。 如果bh_active的第N位被置为1,则表明一旦调度进程许可,立即调用第N个Bottom hal f 例程。 bh_mask_count[]跟踪为每个下半部分提出的enable/disable请求嵌套对的数组。2.系统初始化时钟中断(IRQ0) ①先看看start_kernel(\init\main.c)吧 有几个跟时钟中断(IRQ0)相关的函数。 init_IRQ(); sched_init(); time_init(); sched_init()就是注册时钟中断的下半部分,其实IRQ0两个下半部分,一个前面已经看 到,还有一个下半部分init_bh(TQUEUE_BH, tqueue_bh);下面会看到。 ②init_IRQ函数在\arch\i386\kernel\irq.c 比较重要的调用就是init_ISA_irqs();

c51中断函数如何返回值

c51中断函数如何返回值 c51中断函数如何返回值 c51中断函数如何返回值 匿名提问 2009-04-20 16:14:40 发布 电脑软件 2个回答 BiG299792458 | 2009-09-25 08:19:33 有0人认为这个回答不错 | 有0人认为这个回答没有帮助 主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。 也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。 编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。 说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。 示例:假设Exam是int型全局变量,函数Squre_Exam返回Exam 平方值。那么如下函数不具有可重入性。

unsigned int example( int para ) { unsigned int temp; Exam = para; // (**) temp = Square_Exam( ); return temp; } 此函数若被多个进程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使Exam赋与另一个不同的para值,所以当控制重新回到“temp = Square_Exam( )”后,计算出的temp很可能不是预想中的结果。此函数应如下改进。 unsigned int example( int para ) { unsigned int temp; [申请信号量操作] //(1) Exam = para; temp = Square_Exam( ); [释放信号量操作] return temp; } (1)若申请不到“信号量”,说明另外的进程正处于给Exam赋值并计算其平方过程中(即正在使用此信号),本进程必须等待其释放信号后,才可继续执行。若申请到信号,则可继续执行,但其它进程必须等待本进程释放信号量后,才能再使用本信号。 保证函数的可重入性的方法: 在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量),对于要使用的全局变量要加以保护(如采取关中断、信号量等方法),这样构成的函数就一定是一个可重入的函数。 VxWorks中采取的可重入的技术有: * 动态堆栈变量(各子函数有自己独立的堆栈空间) * 受保护的全局变量和静态变量 * 任务变量

如果在中断服务函数 ISR 中使用寄存器

如果在中断服务函数ISR 中使用寄存器,那么必须处理好using 的使用问题: 1、中断服务函数使用using 指定与主函数不同的寄存器组(主函数一般使用Register bank 0)。 2、中断优先级相同的ISR 可用using 指定相同的寄存器组,但优先级不同的ISR 必须使用不同的寄存器组,在ISR 中被调用的函数也要使用using 指定与中断函数相同的寄存器组。用reentranr指明可重入函数。 3、如果不用using 指定,在ISR 的入口,C51 默认选择寄存器组0,这相当于中断服务程序的入口首先执行指令: MOV PSW #0 这点保证了,没使用using 指定的高优先级中断。可以中断使用不同的寄存器组的低优先级中断。 4、使用using 关键字给中断指定寄存器组,这样直接切换寄存器组而不必进行大量的PUSH 和POP 操作,可以节省RAM空间,加速MCU 执行时间。寄存器组的切换,总的来说比较容易出错,要对内存的使用情况有比较清晰的认识,其正确性要由你自己来保证。特别在程序中有直接地址访问的时候,一定要小心谨慎!至于“什么时候要用到寄存器组切换”,一种情况是:当你试图让两个(或以上)作业同时运行,而且它们的现场需要一些隔离的时候,就会用上了。在ISR 或使用实时操作系统RTOS 中,寄存器非常有用。 寄存器组使用的原则: 1、8051 的最低32 个字节分成4 组8 寄存器。分别为寄存器R0 到R7。寄存器组由PSW 的低两位选择。在ISR 中,MCU 可以切换到一个不同的寄存器组。对寄存器组的访问不可位寻址,C51 编译器规定使用using 或禁止中断的函数(#pragma disable )均不能返回bit 类型的值。 2、主程序(main函数)使用一组,如bank 0;低中断优先级的所有中断均使用第二组,如bank 1;高中断优先级的所有中断均使用再另外一组,如bank 2。显然,同级别的中断使用同一组寄存器不会有问题,因为不会发生中断嵌套;而高优先级的中断则要使用与低优先级中断不同的一组,因为有可能出现在低优先级中断中发生高优先级中断的情况。编译器会自动判断何时可使用绝对寄存器存取。 3、在ISR 中调用其它函数,必须和中断使用相同的寄存器组。当没用NOAREGS 命令做明确的声明,编译器将使用绝对寄存器寻址方式访问函数选定(即用using 或REGISTERBANK 指定)的寄存器组,当函数假定的和实际所选的寄存器组不同时,将产生不可预知的结果,从而可能出现参数传递错误,返回值可能会在错误的寄存器组中。 举一例子:当需要在中断内和中断外调用同一个函数,假定按照程序的流程控制,不会出现函数的递归调用现象,这样的调用会不会出现问题?若确定不会发生重入情况,则有以下两种情况: 1、如果ISR 和主程序使用同一寄存器组(主程序缺省使用BANK 0,若ISR 没有使用using 为其指定寄存器区,则缺省也使用BANK 0),则不需其他设置。 2、如果ISR 和主程序使用不同的寄存器组(主程序缺省使用BANK 0,ISR 使用using 指定了其他BANK),则被调用函数必须放在: #pragma NOAREGS #pragma AREGS 控制参数对中,指定编译器不要对该函数使用绝对寄存器寻址方式;或者也可在Options->C51,选中“Dont use absolute register accesses”,使所有代码均不使用绝对寄存器寻址方式(这样,执行效率将稍有降低)。不论以上的哪一种情况,编译器均会给出重入警告,需手工更改OVERLAY 参数,做重入说明。

相关主题
文本预览
相关文档 最新文档