AVR studio 中断、计时器程序
AVR定时器中断初值计算方法
AVR定时器中断初值计算方法使用芯片ATMega16外部晶振定时器1(16位定时器)寄存器TCCR1B=0x04设定256预分频要利用定时器定时1秒1,4000000/256=15625说明定时器每当1/15625秒就会触发一次中断2,65535-15625=49910计算出要累加多少次才能在1秒后出发定时器1的溢出中断3,49910<==>C2F6将计算后的值换算成16进制4,TCNT1H=0xC2;对寄存器赋值TCNT1L=0xF6;=================================================例如用16位定时器TIMER1,4MHZ晶振,256分频,100ms定时,如何求得初值赋给TCNT165536-(4M/256)*=其中,4M是晶体频率,是定时时长单位秒。
对于8位的定时器T=(2^8-计数初值)*晶振周期*分频数=(2^8-计数初值)/晶振频率*分频数计数初值=2^8-T/晶振周期/分频数=2^8-T*晶振频率/分频数因为AVR一指令一周期IARForAVR精确延时C语言中,想使用精确的延时程序并不容易。
IAR中有这样的一个函数__delay_cycles(),该函数在头文件中定义,函数的作用就是延时N个指令周期。
根据这个函数就可以实现精确的延时函数了(但不能做到100%精确度)。
实现的方法:建立一个的头文件:#ifndef__IAR_DELAY_H#define__IAR_DELAY_H#include<>#defineXTAL8//可定义为你所用的晶振频率(单位Mhz)#definedelay_us(x)__delay_cycles((unsignedlong)(x*XTAL))#definedelay_ms(x)__delay_cycles((unsignedlong)(x*XTAL*1000)) #definedelay_s(x)__delay_cycles((unsignedlong)(x*XTAL*1000000 ))#endif注意:__delay_cycles(x),x必须是常量或则是常量表达式,如果是变量则编译报错!关于溢出中断不管是哪个单片机都是不断累加,使其寄存器溢出触发中断,然后跳转到中断函数处执行中断服务程序。
AVR定时器程序
要求是用定时器编写一个周期为2s的方波程序。
每隔一秒输出口跳变一次的那种。
GCC,Mega16,8M外部晶振其他看注释,熔丝位设为外部晶振,#include<avr/io.h>#include<avr/interrupt.h>int main(void){DDRB = 0xff;PORTB = 0xff;TCNT1H = 15535/256;TCNT1L = 15535%256; //计50000次才溢出TIMSK |= (1 << TOIE1);//使能中断TCCR1B |= (1 << CS11);//8分频sei();while(1){}}volatile unsigned int i;SIGNAL(SIG_OVERFLOW1){TCNT1H = 15535/256;TCNT1L = 15535%256;i ++;if(i >= 20) //晶振为8M,8分频,每次溢出为跳50000次,1s/ ((1/8000000)*50000*8)=20{//所以循环20次i = 0;PORTB ^= 0xff; //PB口接led,实现1s翻转。
}}实验17:TC0定时器溢出定★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★/*******************************************************************************Platform: ATmega16_Basic_V1.1开发板(/)1.Project : 范例16:TC0定时器溢出定时实验(ICC)2.Clock F : 内部1MHz3.Software: ICCAVR7.14C4.Author : 林夕依然5.Version : 10.04.166.Updata :ments:1、以学习板LED为硬件电路2、TC0用作定时器,理解TC0溢出中断的原理3、用程序生成向导配置TC0,溢出中断,产生1ms/20ms延时(只产生其中之一,不用的需要注释掉)4、定时公式:Time=PRE*(MAX-TCNT0+1)/F_cpu单位S ,其中,PRE为与分频数5、进行此实验需要安装上LED_EN短路块************************************************************ *******************///ICC-AVR application builder : 2008-12-15 PM 10:41:53// Target : M16// Crystal: 1.0000Mhz#include <iom16v.h>#include <macros.h>void port_init(void){PORTA = 0x00;DDRA = 0xFF;PORTB = 0xFF;DDRB = 0x00;PORTC = 0xFF; //m103 output onlyDDRC = 0x00;PORTD = 0xFF;DDRD = 0x00;}//TIMER0 initialize - prescale:8/256// WGM: Normal// desired value: 1mSec/20ms// actual value: 1.000mSec (0.0%)/19.968ms(0.16%)void timer0_init(void){TCCR0 = 0x00; //stop//TCNT0 = 0x83; //set count T=PRE*(MAX-TCNT0+1)/F_cpu=8*(255-130)/1MHz=1msTCNT0 = 0xB2; //set count T=PRE*(MAX-TCNT0+1)/F_cpu=256*(255-178+1)/1MHz=19.968msOCR0 = 0x7D; //set compare 程序中未使用//TCCR0 = 0x02; //start timer 8分频TCCR0 = 0x04; //start timer 256分频}#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVFvoid timer0_ovf_isr(void){//TCNT0 = 0x83; //reload counter value 重载TCNT0,使TC0重复从0x83-0xff计数TCNT0 = 0xB2; //reload counter value 重载TCNT0,使TC0重复从0xB2-0xff计数PORTA^=BIT(7)|BIT(6); //翻转PB6/PB7口,实现两个LED灯的1ms间隔亮灭}//call this routine to initialize all peripheralsvoid init_devices(void){//stop errant interrupts until set upCLI(); //disable all interruptsport_init();timer0_init();MCUCR = 0x00;GICR = 0x00;TIMSK = 0x01; //timer interrupt sourcesSEI(); //re-enable interrupts//all peripherals are now initialized }//void main(void){init_devices();//insert your functional code here...}。
AVR定时器中断初值计算方法
AVR 定时器中断初值计算方法使用芯片AT Mega16 外部晶振定时器1 (16位定时器)寄存器TCCR1B = 0x04 设定256预分频要利用定时器定时1秒1,4000000 / 256 = 15625 说明定时器每当1/15625 秒就会触发一次中断2,65535 - 15625 = 49910 计算出要累加多少次才能在1秒后出发定时器1的溢出中断3,49910 <==> C2 F6 将计算后的值换算成16进制4,TCNT1H = 0xC2 ; 对寄存器赋值TCNT1L = 0xF6 ;=================================================例如用16位定时器TIMER1,4MHZ晶振,256分频,100ms定时,如何求得初值赋给TCNT165536-(4M/256)*=其中,4M是晶体频率,是定时时长单位秒。
对于8位的定时器T=(2^8-计数初值)*晶振周期*分频数=(2^8-计数初值)/晶振频率*分频数计数初值=2^8-T/晶振周期/分频数=2^8-T*晶振频率/分频数因为AVR一指令一周期IAR For AVR 精确延时C语言中,想使用精确的延时程序并不容易。
IAR 中有这样的一个函数__delay_cycles(),该函数在头文件中定义,函数的作用就是延时N个指令周期。
根据这个函数就可以实现精确的延时函数了(但不能做到100%精确度)。
实现的方法:建立一个的头文件:#ifndef __IAR_DELAY_H#define __IAR_DELAY_H#include <>#define XTAL 8 //可定义为你所用的晶振频率(单位Mhz)#define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) )#define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) )#define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) )#endif注意:__delay_cycles(x),x必须是常量或则是常量表达式,如果是变量则编译报错!关于溢出中断不管是哪个单片机都是不断累加,使其寄存器溢出触发中断,然后跳转到中断函数处执行中断服务程序。
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中断
//版本 V1.00
// Target : M48
// Crystal: 8.0000Mhz
#include <iom48v.h>
#include <macros.h>
//定义字型数组
#pragma data:code
const unsigned tabs[]=
; TCCR1B = 0x00 关定时器
clr R2
sts 129,R2 ;P81->TCCR1B 关定时器
; TCNT1H = 0xFB 设置数据寄存器高字节
ldi R24,251
sts 133,R24;p85->TCNT1H TCNT1H与TCNT1L组成了T/C1的数据寄存器TCNT1
ldi R25,high(_tabs<<1)
mov R30,R18
clr R31
add R30,R24
adc R31,R25
lpm R2,Z
out 0x5,R2
ldi R24,242;点亮十位
out 0x8,R24
clr R2;改变_led标识的状态
sts _led,R2
L9:
out 0x8,R24
ldi R24,1;改变_led标识的状态
sts _led,R24
,显示十位
ldi R18,10;将秒数除10取整得到十位数
clr R19
lds R16,_second
clr R17
rcall _div16
ldi R24,low(_tabs<<1);字形送端口PORTB
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 单片机——中断系统
中断的优点
中断函数只在中断触发源触发的时候才会执行,其他时间不执行. 如果不使用中断而且如果要根据某个端口的变化而作相应的函数操作,就必须不断地查询端口的信号,而中断不用,只要端口一有变化,就会系统就会自动进入中断函数, 我觉得这就是中断的目的,也是优点.
中断优先级
1) AVR 单片机在同一个优先级中,中断向量入口地址越低,其优先级越高。
AVR 单片机在响应中断以后,会禁止系统响应其余中断。
如果程序需要在某
个中断服务程序中响应其它中断事件,可以在该中断服务程序中用重新使能全局中断即可。
否则,AVR 单片机只有在退出中断进程时,才重新使能全局中断。
2) AVR(至少是ATmega16)单片机采用固定的硬件优先级方式,不支持通过软件对中断优先级重新设定。
AVR 有不同的中断源。
每个中断和复位在程序空间都有独立的中断向量。
所有的中断事件都有自己的使能位。
当使能位置位,且状态寄存器的全局中。
此程序为AVR外部中断
//此程序为AVR外部中断,时钟中断,串行通信,IIC综合实例#include <iom16v.h>#include <macros.h>#define uchar unsigned char#define uint unsigned int#pragma interrupt_handler int2:19//外部中断2#pragma interrupt_handler timer0_ovf_isr:10//时钟中断#pragma interrupt_handler rec:12//串口接收中断void delay(uint ticks);//延时unsigned char const Tab[]={0x14,0x9F,0x38,0x1A,0x93,0x52,0x50,0x1F, 0x10,0x12,0x11,0xD0,0x74,0x98,0x70,0x71}; //数码管显示代码unsigned int count=0;//软件记数void main(){uchar Address,date;int x=0,j=0;init_devices();//中断设置CLI();//关总中断//INT2设置MCUCSR&=~0x40;//下降沿触发GIFR|=0x20;//清INT2标志GICR|=0x20;//开INT2中断//定时设置TCCR0 = 0x00; //stopTCNT0 = 0x83; //set countOCR0 = 0x7D; //set compare//TCCR0 = 0x03; //start timerTIMSK = 0x01; //timer interrupt sources//串口设置,波特率:9600UCSRB = 0x00; //disable while setting baud rateUCSRA = 0x00;UCSRC = BIT(URSEL) | 0x06;UBRRL = 0x33; //set baud rate loUBRRH = 0x00; //set baud rate hi//UCSRB = 0x08;UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);SEI();//开总中断PORTA=0x80;PORTC=Tab[8];//DS3231每秒产生一个中断:WriteDs3231_OneByte(0x0e,0x07);WriteDs3231_OneByte(7,0x80);WriteDs3231_OneByte(8,0x80);WriteDs3231_OneByte(9,0x80);WriteDs3231_OneByte(10,0x81);/*while(1){//读出并显示:date=ReadDs3231_OneByte(j++);//读取数据if(j==7)j=0;//循环读出00-06地址的数据:秒、分、时、星期、日期、月和年信息for(x=0;x<200;x++){PORTA=0x80;PORTC=Tab[date&0x0f];//显示个位delay(50);PORTA=0x40;PORTC=Tab[date>>4];//显示十位delay(50);}PORTA=0;//关闭显示delay(5000);}*/}void delay(uint ticks){uchar i;while(ticks--)for(i=100;i!=0;i--);//约0.1mS}void int2()//外部中断服务程序{CLI();PORTC=Tab[ReadDs3231_OneByte(0)&0x0f];SEI();}void timer0_ovf_isr(void)//定时中断服务程序{unsigned char data;TCNT0 = 0x83; //reload counter valueif(++count==3000)//1000个1mS等于1秒{count=0;data=ReadDs3231_OneByte(0)&0x0f;PORTC=Tab[data];printf("%dn",data);}}void rec()//接收中断服务程序{unsigned char data;data=UDR;PORTC=data;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////将生成的程序进行修改,DDRA = 0x01;PORTD = 0x0C; ,添加MAIN函数,如下∙//ICC-AVR application builder : 2006-12-8 17:04:44∙// Target : M16∙// Crystal: 7.3728Mhz∙∙#include <iom16v.h>∙#include <macros.h>∙∙unsigned int i=0;∙∙void port_init(void)∙{∙ PORTA = 0x00;∙ DDRA = 0x01;∙ PORTB = 0x00;∙ DDRB = 0x00;∙ PORTC = 0x00; //m103 output only∙ DDRC = 0x00;∙ PORTD = 0x0C; //使INT0,INT1对应口上拉电阻有效∙ DDRD = 0x00; //必须设置INT0,INT1对应口为输入∙}∙∙#pragma interrupt_handler int0_isr:2∙void int0_isr(void)∙{∙ //external interupt on INT0∙ i++; //在中断里进行操作∙}∙∙#pragma interrupt_handler int1_isr:3∙void int1_isr(void)∙{∙ //external interupt on INT1∙ PORTA = 0x01; //在中断里进行操作∙}∙∙//call this routine to initialize all peripherals∙void init_devices(void)∙{∙ //stop errant interrupts until set up∙ CLI(); //disable all interrupts∙ port_init();∙∙ MCUCR = 0x08; //INT1 的下降沿产生异步中断请求,INT0上升延∙ GICR = 0xC0; //INT0和INT1使能∙ TIMSK = 0x00; //timer interrupt sources∙ SEI(); //re-enable interrupts∙ //all peripherals are now initialized∙}∙∙void main(void)∙{∙ init_devices();∙ while(1) //死循环等待中断∙ ;∙}相关解释1. #pragma interrupt_handler int0_isr:22. 中断的约定表示方法:int0_isr有一个与之对应的应用程序void int0_isr(void),2为中断向量,值越小,优先级越高,INT0的优先级仅次于复位。
AVR单片机技术 定时器计数器中断应用教案
定时器/计数器中断应用
教案
教学目标知识目标:定时器/计数器中断应用;
能力目标:掌握AVR单片机定时器/计数器中断编程方法。
教学内容AVR单片机定时器/计数器中断应用
重点、难点定时器/计数器中断设置步骤;
定时器定时计算方法;
计数器计数值设定方法;
主程序和中断服务程序之间的关系;
教学方法趣味案例激励法;课堂讨论;归纳总结
教学组织案例引入:如果我们要设计一个时钟,如何实现?
问题引导:采用延时函数可以实现计时功能么?为什么?
知识展开:采用延时函数可以实现计时功能么?有什么问题?
课堂练习:如何利用定时器实现计时功能?
分析总结:定时器实现计时功能和利用延时函数实现计时功能有何利弊?尽量详细分析。
问题讨论AVRmega16有几个定时器?有什么不同?课后任务资料检索:计数器可以用来完成什么功能?教师备忘。
单片机avr中断寄存器中断c语言函数外部中断INT0,INT1,INT3介绍
单片机avr 中断寄存器中断c语言函数外部中断INT0,INT1,INT3 介绍
简介:中断的概念,ATmega16中断向量表,avr中断寄存器SREG,MCU控制和状态寄存器MCUCSR,通用中断控制寄存器GICR, MCU控制寄存器MCUCR,ICCAVR中断函数格式介绍
中断就是暂停正在执行的程序语句,转去执行另一功能(函数)的程序语句,执行完后,立即返回原先暂停执行的语句处,继续执行。
单片机的中断系统解决了单片机运算速度快,外设(如键盘)速度慢之间的数据传输问题,提高了单片机的实时性和数据处理能力。
中断源:产生中断的地方,ATmega16具有20个中断源和一个复位中断,不同的单片机中断源的个数是不一样的。
单片机的中断源分为外部中断源和内部中断源,有三个外部中断源有INT0,INT1,INT2,当连接在单片机引脚的上
的外部电平发生变化时,将产生相应的中断。
内部中断源由单片机内部的功能单元如定时器,串行通讯产生的中断。
按是否可屏蔽可分为,非屏蔽中断,和可屏蔽中断,非屏蔽中断有系统复位(reset)中断,可屏蔽中断:屏蔽指的的是中断可由软件编程控制是否允许中断,或禁止中断,大部分都是可屏蔽中断。
中断向量:单片
机的每个中断源都有一个固定的入口地址,这个地址由单片机的硬件决定的,单片机相应中断后,自动跳转到相应的地址,这个地址就叫中断矢量。
avr单片机定时器0溢出中断程序
avr单片机定时器0溢出中断程序2014年2月17日22:26:32芯片名称: AVR (艾特梅尔公司)mega16A 微控制器芯片;开发板: 自主研发的 YF-A1芯片开发板; (YF :是本人名字缩写 )第53次试验,用逻辑分析仪捕捉,输出于IO口的数字,脉冲信号,脉冲信号宽度:1.5~1.8微妙,每9~11个脉宽1.5us的信号时序中,夹杂着一个脉宽位为3微妙的高脉冲信号.我用了好几个小时都计算不出定时器0内部的时钟频率........哪里出错了呢?外部用12兆晶体整荡器;我的计算结论是:定时器0内部频率为32khz,但是这显然有问题.定时器时钟为内部8分频 TCCR0=0X02; TCNTO初始值250,即每6个时钟周期溢出一次,每溢出一次,PB口电平取反一次,就这样反向计算脉宽 1.5us ÷ 6 ==每一个被分频的时钟时间÷ 8 =时钟频率;/*写这个程序我用了3个多小时,反复实验.苍天不负有心人额,,哎╮(╯▽╰)╭,,,,,程序名:定时器0溢出中断概述:定时器每一毫秒溢出一次,溢出500次,即0.5秒 ,LED灯跳变一次,我发现,如果不将所有io口初始化,芯片将变得极其不稳定,无法正常工作,定时器0 溢出标志位TOV0 一旦溢出,进入中断服务程序后,将自动清零,再无需软件清零,我似乎明白了硬件清零的意思;finish time :2014年2月28日20:40:21; */#include ;#include ;#include;typedef unsigned char uint8;typedef unsigned int uint16;volatile uint16 a=0;void io(void){DDRA=0XFF;PORTA=0X00;DDRB=0XFF;PORTB=0X00;DDRC=0XFF;PORTC=0X00;DDRD=0XFF;PORTD=0X00;int main(void){io();TIMSK=0X01; // 溢出中断使能;sei();//全局中断使能;TCNT0=69; //定时器初始值1毫秒溢出;TCCR0=3;//64分频定时器开始运行!;PORTB=4;//8位LED共阳极使能;while(1); //死循环;}SIGNAL(SIG_OVERFLOW0) //中断服务程序;{static uint16 s=0; // 静态变量;TCNT0=69; //重设定时器初始值;s++;if(s==502)//每500毫秒PA口电平跳变一次!{ s=0;PORTA^=0XFF;}// TIFR=0X01;//将定时器0溢出标志位和比较匹配标志位置一清零;}。
AVR教程(十八):AVR 定时器中断程序
//ICR1H = 0x1C; //设置 TC1的 输入捕获寄存器 高8位值 //ICR1L = 0x20; //设置 TC1的 输入捕获寄存器 低8位值
注意事项: (1)若有加载库程序,请将光盘根目录下的“库程序”下的“ICC_H”文件夹拷到 D 验板 SMK 系列 SMK1632说明资料” ---------------------------------------------------------------------10101010101010101010101010101010101010101010101010101010101010101010*/ #include <iom16v.h> #include <macros.h> #define DISP_DDR DDRD #define DISP_PORT PORTD /*-------------------------------------------------------------------程序名称:定时器1初始化程序 程序功能: 注意事项:基于7.3728M 晶振 提示说明:晶振不要买到假的,要不然,调不出来还以为电脑有鬼! 输 入: 返 回: --------------------------------------------------------------------*/ void timer1_init(void) { TCCR1B = 0x00; //stop timer TCNT1H = 0xE3; //设置 TC1的 计数寄存器 高8位值,基于7.3728M 晶振 TCNT1L = 0xE1; //设置 TC1的 计数寄存器 低8位值,基于7.3728M 晶振 //OCR1AH = 0x1C; //设置 TC1的 输出比较寄存器 A 高8位值 //OCR1AL = 0x20; //设置 TC1的 输出比较寄存器 A 低8位值
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本程序应用了外部中断1、0,定时器中断0,
初始显示变量uname(100000),
按下中断1显示内容减1,中断0加1,定时器每隔一秒加1
显示子函数A VR_display;
频率1M
A口接数码管段选
B口接数码管位选
*/
#include<avr/io.h>
#include <avr/interrupt.h>
volatile unsigned long Ex_i; //定时器用的变量
volatile unsigned long uname=100000;//初始显示内容
/*=====0-9=====A-G=====*/
unsigned char table[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
//共阳极数码管的段码0 1 2 3 4 5 6 7 8 9 A B C D E F
/*0-7*/
unsigned char num[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//共阳极数码管的wei码0 1 2 3 4 5 6 7 8
void init_avrinter();//外部中断初始化
void init_avrtimer0();//计数器0初始化
void delay(unsigned int x);//延时函数
void AVR_display(unsigned long nnn);//显示函数
int main() //主程序
{
DDRA=0xff; //设置方向寄存器为输出
DDRB=0xff;
DDRD=0xff;
PORTD=0xff;
init_avrinter();
init_avrtimer0();
while(1)
{
A VR_display(uname);
}
}
void init_avrinter()//外部中断初始化
{
sei(); //开总中断
MCUCR |= (1 << ISC10)|(1 << ISC00)|(1 << ISC01); //INT1下(shang)降沿触发INT0上降沿触发
GICR |= (1 << INT1)|(1 << INT0);//使能INT1 INT0
}
void init_avrtimer0()//定时器0初始化
{
TCNT0 = 5;
TIMSK |= (1 << TOIE0);//使能TC0溢出中断
TCCR0 |= (1 << CS01);// 8分频
}
SIGNAL(SIG_INTERRUPT0)//外部中断0程序
{
uname++; //显示内容加1
}
SIGNAL(SIG_INTERRUPT1)//外部中断1程序
{
uname--; //显示内容减1
}
SIGNAL(SIG_OVERFLOW0)//外部中断1程序
{
Ex_i ++;
TCNT0 = 5;
if(Ex_i>=500)
{
Ex_i=0; uname++;
}
}
void delay(unsigned int x)//延时
{
unsigned int Dl_i;
for(Dl_i=0;Dl_i<x;Dl_i++);
}
void AVR_display(unsigned long nnn)//显示9999 9999一下十进制数
{
unsigned char n[8],i,j=8;
unsigned long nn;
nn = nnn;
for(i=0;i<8;i++)
{
n[i] = nn%10;
nn /= 10;
}
for(i=0;i<8;i++)
{
if(n[7-i])break;
j--;
}
for(i=0;i<j;i++)
{
PORTA = table[n[i]];
PORTB = num[7-i]; //板子上数码管位方向是高位到低位(7>>>0);
delay(270);
PORTA = 0xff;
PORTB = 0xff;
}
}。