AVR单片机中断
AVR单片机的捕获中断

AVR单片机的捕获中断//ICC-AVR application builder : 2007-5-29 下午 02:12:45 // Target : M16// Crystal: 11.059Mhz#include <iom16v.h>#include <macros.h>/***********预编译******************/#define uchar unsigned char#define uint unsigned int#define ulong unsigned long/**************全局变量****************/uchar Flag=0; //捕获次数定义uchar ReadFlag=0; //发送数据标志ulong rpm=0; //转速uchar i;uint CNT1=0; //第一次捕获值uint CNT2=0; //第二此捕获值uint CNT=0; //捕获差值uchar ZHSH=0x00,ZHSL=0x00;struct UARTSJ{uchar tou0,tou1,CDH,ZHSH,ZHSL,temp3,temp4,Crc;};struct UARTSJ TXout;//发送的数据帧void port_init(void){PORTA = 0x00;DDRA = 0x00;PORTB = 0x00;DDRB = 0x00;PORTC = 0x00; //m103 output onlyDDRC = 0x00;PORTD = 0x00;DDRD = 0x0E;}//Watchdog initialize// prescale: 256Kvoid watchdog_init(void){WDR(); //this prevents a timout on enablingWDTCR = 0x0C; //WATCHDOG ENABLED - dont forget to issue WDRs}//TIMER1 initialize - prescale:1// WGM: 0) Normal, TOP=0xFFFF// desired value: 1uSec// actual value: 0.995uSec (0.5%)void timer1_init(void){TCCR1B = 0x00; //stopTCNT1H = 0x00;TCNT1L = 0x00;ICR1H = 0x00;ICR1L = 0x00;TCCR1A = 0x00;TCCR1B = 0xC1; //start Timer}#pragma interrupt_handler timer1_capt_isr:6void timer1_capt_isr(void){//timer 1 input capture event, read (int)value in ICR1 using;// value=ICR1L; //Read low byte first (important)// value|=(int)ICR1H << 8; //Read high byte and shift into top byte while(TIFR&0x20) //捕获检测{TIFR|=0x20; //清除捕获标志CNT2=(ICR1H<<8)+ICR1L; //CNT2存放当前捕获值if(CNT2>CNT1)CNT=CNT2-CNT1; //CNT存放两次时间差elseCNT=0xffff-CNT2+CNT1;CNT1=CNT2; //CNT1存放上次捕获值rpm=(ulong)120E6/(ulong)CNT;Flag++; //检测到第一次捕获}if(Flag==2) //检测到第二此捕获{Flag=0;i=(uchar)rpm; //清除捕获检测标志ZHSH=i&0xff00;ZHSL=i&0x00ff; //数据处理ReadFlag=1; //标志传输有效CNT=0;CNT1=0;CNT2=0;} //清除捕获值及捕获差值}#pragma interrupt_handler timer1_compa_isr:7void timer1_compa_isr(void){//compare occured TCNT1=OCR1A}//UART0 initialize// desired baud rate: 4800// actual: baud rate:4800 (0.0%)// char size: 8 bit// parity: Disabledvoid uart0_init(void){UCSRB = 0x00; //disable while setting baud rateUCSRA = 0x00;UCSRC = BIT(URSEL) | 0x06;UBRRL = 0x8F; //set baud rate loUBRRH = 0x00; //set baud rate hiUCSRB = 0xB8;}#pragma interrupt_handler uart0_rx_isr:12void uart0_rx_isr(void){//uart has received a character in UDR}#pragma interrupt_handler uart0_udre_isr:13void uart0_udre_isr(void){//character transferred to shift register so UDR is now empty }//call this routine to initialize all peripheralsvoid init_devices(void){//stop errant interrupts until set upCLI(); //disable all interruptsport_init();watchdog_init();timer1_init();uart0_init();MCUCR = 0x00;GICR = 0x00;TIMSK = 0x20; //timer interrupt sourcesSEI(); //re-enable interrupts//all peripherals are now initialized}//void main(void){init_devices();while(1);//insert your functional code here...}//转速=1E6微秒/秒×1脉冲/时间间隔(微秒表示)×2圈/脉冲(看有几个汽缸)×60秒/分钟。
AVR单片机WinAVR及Proteus仿真外部中断

仿真的时候就可以按下那个button,看程序是否完成了应有的功能。
//LED灯状态标志位,0代表目前LED灯状态为灭,1代表LED灯目前状态为点亮
unsigned char led_flg = 0;
ISR(INT0_vect)//外部中断的中断服务程序,INT0_vectfromiom48p.h
{
EIFR &= ~(1<<INTF0);//清除中断标志位
_delay_ms(10);//延时去掉干扰
先打开这个MFile
将它另存到Hello_AVR下面,不要改它的名字,软件只认识Makefile这个名字,你若重命名了,还得再改还回来的。(在另存之前,这个界面下也可以做配置,可以配置完了再保存过去,效果也是一样的)
然后把它添加到工程文件夹Makefile下,打开Makefile文件,进行配置
绿色字体是注释,蓝色和黑色的是配置项。
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
extern void Exint_Iint(void);
#endif
avrexti.C:
#include <avrexti.h>
void Exint_Iint(void)//外部中断初始化函数
第4章avrmega16单片机中断实例

• 4) 中断嵌套
在中断发生后,SREG的I位由硬件清除,并由 RETI(中断返回)指令置位,从而允许子序列的中断响应。
由于 AVR 在响应一个中断的过程中通过硬件将 I 标志 位自动清零,这样就阻止了 MCU响应其它中断。因此通 常情况下,AVR 是不能自动实现中断嵌套的。 如要系统中必须要实现中断嵌套的应用,用户可在中 断服务程序中使用指令将全局中断允许位开放,通过间接 的方式实现中断的嵌套处理。
1) MCU 控制寄存器—MCUCR
• MCU 控制寄存器 MCUCR 的低 4 位为 INT0(ISC01、 ISC00)和 INT1(ISC11、ISC10)中断触发类型控制位。
2)MCU 控制和状态寄存器—MCUCSR
• MCU 控制和状态寄存器 MCUCSR 中的第6位(ISC2) 为 INT2 的中断触发类型控制位。
void main(void) { PORTA=0xFF; DDRA=0xFF; PORTD|=0x0C; DDRD|=0x00; //DDRD.3=0;DDRD.2=0; GICR|=0xC0; MCUCR=0x0A; MCUCSR=0x00; GIFR=0xC0; //清除INT0、INT1中断标志位 #asm("sei") //SREG|=0x80; SREG.7=1; while (1) { PORTA=led_7[counter]; } }
4) 通用中断标志寄存器—GIFR
• 注意:用户可以使用指令将 INTFn 清除,清除的方式是 写逻辑“1”到 INTFn,将标志清零。另外, 当INT0 (INT1) 设置为低电平触发方式时, 标志位 INTF0 (INTF1) 始终为“0”,这并不意味着不产生中断请求, 而是低电平触发方式是不带中断标志类型的中断触发。在 低电平触发方式时,中断请求将一直保持到引脚上的低电 平消失为止。 • 而在开放中断允许前,一般应通过向 GIFR 寄存器中的中 断标志位 INTFn 写入逻辑“1” ,将该中断的中断标志位 清除,然后开放中断。这样可以防止在改变ISCn 的过程
AVR单片机中断

AVR单片机中断
系统在正常运行主程序时,如果突然有一个重要的任务要马上处理,那么
系统就要保存现在的工作,然后再去处理这个任务,执行这个重要任务完毕以
后再返回原来的主程序继续运行,这就是中断。
主程序一旦进入中断服务程序,那么AVR 芯片将自动的关闭全局中断,在
这个期间不再执行其它的中断请求,直到中断程序结束以后芯片才自动的重新
开放全局中断。
(注意,在这个期间某些中断请求可能会被丢弃,某些请求会留下中断请求标致,一旦当前的中断执行完毕,这个有中断标致的请求就有可能
马上得到响应,如INT0 的下降沿触发就会留下中断请求标致,而低电平触发
就不会流下中断请求标致)。
如果你想在执行中断服务程序时响应另外一个更重要的中断,那么就要在中断服务程序中加入一条打开全局中断的语句。
使用ICC 快速建立中断服务程序程序文件
使用ICCAVR Application Builder 进行如下图所示的设置。
可以设置是否使用中断,上升延,下降延,低电平,任意的逻辑电平变化。
将生成的程序进行修改,DDRA = 0x01;PORTD = 0x0C; ,添加MAIN 函数,如下
//ICC-AVR application builder : 2006-12-8 17:04:44
// Target : M16
// Crystal: 7.3728Mhz
#include
#include
unsigned int i=0;。
AVR中断嵌套的说明

无论导致引脚电平变化的原因是来自单片机内部还是外部 只要引脚上的电平发生了变化 都可以触发该引脚上的电平变化中断
简单的说 中断就是在中断源触发的时候启动中断程序 而在没有中断源的时候不执行 如果不使用中断 如果要根据某个端口的变化而作相应的动作 就必须不断地查询端口的信号 而中断不用 这就是区别。。。
AVR单片机,其硬件系统不支持自动实现中断嵌套的处理。如果在系统设计中,必须使用中断嵌套处理,则需要由用户编写相应的程序,通过软件设置来实现中断嵌套的功能。
AVR中断嵌套处理是通过软件方式实现的。如在B中断服务中,如需要MCU能及时的响应A中断(不是等本次中断返回后再响应),B中断的服务程序应这样设计:(1)B中断的现场保护;(2)屏蔽除A以外其它的中断允许标志;(3)用指令SEI开放允许全局中断;(4)B中断服务;(5)用指令CLI禁止全局中断(6)恢复在本中断程序被屏蔽的中断允许标志;(7)B中断现场恢复;(8)B中断返回。 用户在编写中断处理服务程序中,应遵循中断服务程序尽量要短的原则
当MCU响应一个中断时,其硬件系统会自动中断返回地址压入系统堆栈,并将关闭全局中断响应(硬件将中断标志I位清0),清除该中断的中断标志位;执行中断返回指令RETI时,硬件会先允许全局中断响应(硬件将中断标志I位置1),然后从系统堆栈中弹出返回地址到PC程序计数器中,继续执行被中断打断的程序。除此之外,MCU的硬件没有对中断保护做其他处理。
中断优先级的概念是针对有多个中断源同时申请中断时,MCU如何响应中断,以及响应哪个中断而提出的。
AVR单片机外部中断C程序框架

AVR单片机外部中断C程序框架
Avrmega16a
单片机在studio4开发环境中外部中断C程序框架如下:
#include;
//头文件.
#include;
//中断头文件;
typedefunsignedcharuint8;
//习惯宏定义数据类型语法.应用时只需写入数据类型:
//
uint8s=0;
typedefunsignedintuint16;
//习惯宏定义数据类型语法.应用时只需写入数据类型:
//
uint16
i=0;
Intmain()
//主函数;
{
MCUCR=0Xnn:
//中断模式触发寄存器,用来设置外部中断引脚的触发方式,上升沿,下降
//沿,还是高电平或低电平方式;
GICR=0Xnn;
//局部中断使能,用来使能某个中断源.
Sei();
//全局中断使能,用来开启中断服务(中断总使能); //在此写入程序语句;
//
//如果外部中断源一旦被触发,程序就会立即执行中断服务函数;
}
//此↓‘n’是外部中断源序号有中断0,中断1,中断2.
SIGANL(SIG_INTRRUPTn)
//终端服务函数;
{
//在中断函数中,不能定义局部数据类型变量;
//在此写入中断程序;
}。
avr单片机的定时器、中断和PWM(转)

/s/blog_4aa25f130100go4v.html转中断:我的理解就是cpu执行时,遇到中断——根据对应的中断源(硬件或软件)——pc定位中断入口地址,然后根据这里的函数指针——跳转到相应的服务程序之所以上面()了硬件或软件,这里还涉及到向量中断和非向量中断:区别就在于确定中断源,如果是硬件编码了中断源的,直接跳转相应的服务函数则是向量中断。
而非向量中断指的是:如果发生中断了,但此时还不清楚是那个中断,需要查找标志位来确定跳转到那个中断区域。
可以发现向量中断肯定来的快些,这里为定时器的中断来做好准备。
再来看看avr单片机的定时器:定时器/计数1(16位)————分为普通模式,CTC模式,快速pwm模式,相位修正pwm模式,相位频率修正pwm模式,输入捕获模式。
普通模式:*1 寄存器TCCR1B(控制寄存器)7 6 5 4 3 2 1 0ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10CS12 CS11 CS10控制分频(内:预分频器):取值0-5对应了停止,无分频,8,64,256,1024当为110为下降沿驱动,111为上升沿驱动(外部):用于对外部信号的计数*2上面的计数结果放在计数寄存器TCNT1,TCNT0中(高低8位)*3中断屏蔽寄存器(TIMSK)OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1OCIE0 TOIE0TOIE1 :设置为溢出中断,置1嘿嘿,有了上面的3个寄存器就可以做秒表等了——思路为:设定控制寄存器(内分频,还是外部计数?)——装初值——设置中断方式(这里用了溢出)——打开中断注意点:装初值时需要先写高位TCNT1,再写低位TCNT0,读时相反TCCR1B=0x01;无分频TCNT1H=0x88;TCNT1L=0x88;TIMSK|=BIT(2); 再开中断SREG|=bit(7); 这样初始化oK!由于avr不像51无int code等之类定义的方法,用的是#pragma data:code 底下为存储的内容写中断也类似:#pragma interrupt_handler (中断函数名:向量号)miao:9(现在该理解向量中断吧)写好申明后就写函数体了void miao(){中断服务程序}这样作为普通用法就小功告成了总结一下就是模式,初值,中断(对应的3个寄存器)和具体C函数的写法CTC模式比较输出模式:用于输出50%占空比的方波信号,用于产生准确的连续定时信号硬件:对应了pd4,pd5输出比较b和a比较输出*1 寄存器TCCR1A(控制寄存器)功能多了寄存器也分a、b了^_^7 6 5 4 3 2 1 0com1A1 COM1A0 com1B1 COM1B0 FOC1A FOC1B W GM11 WGM10用到了4567和01 4、5控制b 6、7控制acom1A(B)1 COM1A(B)0 一般用00和01 WGM11,WGM10放在底下讲0 0 普通i/00 1 比较匹配时输出取反1 0 比较匹配时输出01 1 比较匹配时输出1*2 寄存器TCCR1B(控制寄存器)7 6 5 4 3 2 1 0ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10CS12、CS11、CS10为设置时钟源的WGM13,WGM12,WGM11,WGM10用于波形产生描述的位选择,有对应的表0-15 这里选了4:CTC-OCR1A-立即更新-最大 OCR1A (16位)输出比较寄存器-这里存放了上限值设置的目的是,计数上升到了设定的上限后就电平取反思路:先初始话,对应的复用i/o为输出——设定com1A(B)1,COM1A(B)0 为比较输出取反——设定上限值为ocr1A 就ok了0CR1A可以根据公式计算:具体公式看手册,这里因为我打不起来o(∩_∩)o...哈哈总结一下就是控制寄存器a,b以及上限的值即可产生方波快速PWM分8位9位10位快速pwm,以及自定义方式我的理解:OCR1A存放上限值,这样用上了A的功能,由上面可知A只能为方波了,且计数到这个值时取反下限值通过OCR1B来确定的,从而计数到这个值置0,从而可以发现在一个周期内 OCROB即为高电平的时间(确定占空比)如图TCCR1A=0x63;TCCR1B=0x1B; 工作方式(快速pwm15,64分频)和分频系数OcR1A=1249;OCCR1B=250; 设为100Hz PWM信号,和2毫秒的高电平时间总结一下就是控制寄存器:由上限值,和分频系数可以确定计数的时间,确定频率由下限值可以确定占空比怎么样?明白了吗?o(∩_∩)o...相位修正PWM和快速pwm一样,模式分8位9位10位快速pwm,以及自定义方式共5种对应123和10,11相位修正其实和上面的方法相同,只不过到最大值时,不是取反,而是计数--,直到到了下限时取反由上可以发现2图的区别吧,一个为到TOP后,直接置0,后者为--,且在top 不取反而是到了最小值是取的,周期故而也比快速的长了一倍,故频率为快速pwm的一半,但是占空比不变,这也是为什么叫快速pwm的原因TCCR1A=0x63;TCCR1B=0x13 工作方式(相位修正pwm11,64分频)和分频系数OcR1A=1249;OCCR1B=250; 设为100Hz PWM信号,和2毫秒的高电平时间相位频率修正PWM和相位修正的类似输入捕获。
AVR中断优先级

AVR 中断优先级AVR 单片机在同一个优先级中,中断向量入口地址越低,其优先级越高。
AVR 单片机在响应中断以后,会禁止系统响应其余中断。
如果程序需要在某个中断服务程序中响应其它中断事件,可以在该中断服务程序中用SEI 指令或_SEI()(IAR)、SEI()(ICCAVR)重新使能全局中断即可。
否则,AVR 单片机只有在退出中断进程时,才重新使能全局中断。
AVR(至少是ATmega16)单片机采用固定的硬件优先级方式,不支持通过软件对中断优先级重新设定。
AVR 有不同的中断源。
每个中断和复位在程序空间都有独立的中断向量。
所有的中断事件都有自己的使能位。
当使能位置位,且状态寄存器的全局中断使能位I 也置位时,中断可以发生。
根据程序计数器PC 的不同,在引导锁定位BLB02 或BLB12 被编程的情况下,中断可能被自动禁止。
这个特性提高了软件的安全性。
详见P247 存储器编程的描述。
程序存储区的最低地址缺省为复位向量和中断向量。
完整的向量列表请参见P43 中断。
列表也决定了不同中断的优先级。
向量所在的地址越低,优先级越高。
RESET 具有最高的优先级,第二个为INT0 – 外部中断请求0。
通过置位MCU 控制寄存器(MCUCR) 的IVSEL,中断向量可以移至引导Flash 的起始处。
编程熔丝位BOOTRST 也可以将复位向量移至引导Flash 的起始处。
具体参见P234 支持引导装入程序– 在写的同时可以读(RWW,Read-While-Write) 的自我编程能力。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
AVR单片机中断应用设计要点
四川侯鑫
AVR的中断源较多,尤其是AT-mega128,一共有35个外部及内部中断源。
通常。
Flash 程序存储器空间的最低位置(0×0000~0×0045)定义为复位和中断向量空间。
在中断向量表中,处于低地址的中断向量所对应的中断拥有高优先级。
所以,系统复位RESET优先级最高。
一、中断设计注意事项1.具备Bootloader功能的AVR。
其中断向量区可以在Flash程序存储器空间最低位置和Bootloader区的头部来回迁移,这主要用于配合Bootloadel程序的应用。
如果不使用Bootloadel-功能。
一般不使用中断向量区迁移。
2.Flash较小的AVR芯片。
其一个中断向量占据1个字的空间。
用于放置一条相对转移RJMP指令(范围-2k~+2k字),跳到中断服务程序。
对于不使用的中断。
在中断向量区中应放置1条中断返回指令RETI。
以增强程序的抗干扰性。
3.ATmega128的Flash空间为64k字节,因此它的一个中断向量占据2个字的空间。
用于放置一条绝对转移JMP指令(指令长度为2个字)。
跳到中断服务程序。
对于不使用的中断。
在中断向量区中应连续放置2条中断返回指令RETI,以增强程序的抗干扰性。
当使用汇编语言编写系统程序时应注意。
4.当MCU响应一个中断时.其硬件系统会自动将中断返回地址压入系统堆栈。
并关闭全局中断响应(硬件将中断标志I位清0).清除该中断的中断标志位;执行中断返回指令RETI 时,硬件会先允许全局中断响应(硬件将中断标志I位置1),然后从系统堆栈中弹出返回地址到程序计数器PC中,继续执行被中断的程序。
除此之外,MCU的硬件没有对中断保护做其他处理。
5.在编写中断服务程序时。
首先要编写中断现场保护程序。
如保护MCU的状态寄存器等。
在中断返回之前,不要忘记恢复中断现场。
6.如果设置和允许外部中断响应。
即使是外部INT0~INT7引脚设置为输出。
在引脚上的电平变化也会触发外部中断发生。
这一特性提供了使用软件产生中断的途径。
7.外部中断可选择采用上升沿触发、下降沿触发、电平变化(由高变低或由低变高)和低电平触发等方式,无外部高电平触发方式。
具体触发方式由外部中断控制寄存器EICRA(INT3:0)和EICRB(INT7:4)决定。
8.选择外部低电平方式触发中断时应注意:(1)引脚上的低电平必须一直保持到当前一条指令执行完成后才能触发中断。
(2)低电平中断并不置位中断标志位。
即外部低电平中断的触发不是由于中断标志位引起的,而是外部引脚上电平取反后直接触发中断(需要开放全局中断允许)。
因此,在使用低电平触发方式时,中断请求将一直保持到引脚上的低电平消失为
止。
即只要中断引脚的输入引脚保持低电平,则将一直触发产生中断。
所以,在低电平中断服务程序中,应有相应的操作命令,控制外部器件释放或取消加在外部引脚上的低电平。
二、中断优先及中断嵌套处理
1.AVR中断的优先级由该中断向量在中断向量区中的位置确定,处于低地址的中断向量所对应的中断拥有高优先级。
所以。
系统复位RESET拥有最高优先级。
2.当两个中断源同时申请中断时。
MCU先响应中断优先级高的中断。
低优先级的中断一般将保持中断标志位的状态(外部低电平中断除外),等待MCU响应处理。
3.MCU响应一个中断后,在进入中断服务前已由硬件自动清零全局中断允许位。
此时。
即使有更高优先级的中断请求,MCU也不会响应。
要等执行到RETI指令,从本次中断返回,并执行了一条指令后。
才能继续响应中断。
所以,在缺省情况下,AVR的中断不能嵌套。
AVR中断的优先级只是在有多个中断同时发生时才起作用。
此时,MCU将首先响应高优先级的中断。
4.AVR中断嵌套处理是通过软件方式实现的。
如果在B中断服务中,需要MCU能及时响应A中断(不是等本次中断返回后再响应),B中断的服务程序应这样设计:
(1)B中断的现场保护;(2)屏蔽除A以外的其它中断允许标志;(3)用指令SEI开放允许全局中断;(4)B中断服务;(5)用指令CLI禁止全局中断;(6)恢复在本中断程序被屏蔽的中断允许标志;(7)B中断现场恢复;(8)B中断返回。
5.采用软件方式实现中断嵌套处理的优点。
是让程序员可以根据不同的实际情况和需要来决定中断的重要性。
有更加灵活的手段处理中断响应和中断嵌套,如让低优先级的中断(此时很重要)打断高优先级中断的服务等。
但同时也增加了编写中断服务程序的复杂性。
6.由于AVR的指令执行速度比较高,因此。
在一般情况下。
不建议使用中断嵌套的处理方法。
当然,这还需要用户在编写中断处理服务程序中。
应遵循中断服务程序要尽量短的原则。
三、高级语言环境中。
中断服务程序的编写1.在高级语言开发环境中,都扩展和提供了相应编写中断服务程序的方法及模块。
但不同的高级语言开发环境中对编写中断服务程序的语法规则和处理方法是不同的。
在编写中断服务程序前。
应当对所使用开发平台、中断程序的编写方法、中断的处理方法等有较好的了解。
2.使用ICCAVR、CVAVR、BASCOM-AVR等高级语言编写中断服务程序时。
通常不必考虑对中断现场保护和恢复的处理。
因为编译器在编译中断服务程序的源代码时,会在生成的目标代码中自动加入相应的中断现场保护和恢复指令。
3.如果用户要编写效率更高或特殊的中断服务程序。
可以采用嵌入汇编、关闭编译系统的自动产生中断现场保护和恢复代码等措施。
但这需要对所使用的开发环境有更深的了解和掌握。
并具备较高的软件设计能力。