MCU的定时器是个极其重要的资源,定时器可以衍生出很多功能,例如中断,PWM,输入捕捉等等。而我手上的ATmega328P有3个定时器,分别两个8位的和一个16位的。 现在我来分享一下我自己在使用定时器1用作中断的经验,我用定时器1定时1s的中断,然后在中断翻转PB5管脚的电平,实现一秒闪灯的效果。 下面是ATmega328P定时器的功能简介:
可以看出功能挺多的,在8位机里已经很不错了,可以满足你各种需求。 下面是定时器1的框图: 挺复杂的,我这里就不做过多的解释了,大家可以去看官方手册了解下。 定时器1的TCCR1A寄存器是控制PWM功能的,这里我没有用到PWM就可以吧这个寄存器的高四位设成0,低四位是设置定时器的工作方式,如下如:
可以看出,定时器有12中功能,其实有些功能是重叠的,如PWM,只不过是PWM的位宽不同而已。 接下来TTCR1B寄存器我们比较关心的是低3位是设置定时器输入时钟的分频数。
分频数可以看如下图表设置: 我这里设置了1024分频,也就是说定时器的输入时钟频率是系统时钟的1024分频。 接下来TCNT1是设置定时器的初始值,这个就像51定时器的装初值。 根据技术文档是这样计算的: TCNT1=0Xffff - 定时时间/(分频数* (1/晶振频率)) 分频数是调整计数的,越大计数越慢,一般有1、8、64、256、1024分频。 晶振频率就是板子上那个晶振,我们用的ATmega328P XINIM板子上的时钟来自EDGB提供的16M,所以要实现1S:TCNT1= 0XFFFF - 1 / (1024 *(1/16000000))= 0xFFFF –0x3D09=0XC2F6; 接着我们要打开定时器1的中断允许位。就是通过把TIFR1的最低位置一。
然后在中断对TCNT1装就可以了。
现在贴出我的代码: intmain(void)
{
cli();关全局中断
TCCR1A=0; //寄存器A是配置PWM的,这里我们只是使用定时功能,其实不需要配置
TCCR1B=(1<<CS12)|(1<<CS10);//寄存器B是配置定时功能的,现在配置的是1024分频
TCNT1=0XC2F6; //计数器初值,1s定时
TIMSK1=(1<<TOIE1); //溢出中断使能
DDRB|=(1<<DDB5); //13管脚对应的是芯片上PB5,设置为输出
PORTB|=(0<<PORTB5); ////设置为低电平输出
sei(); //开全局中断}
ISR(TIMER1_OVF_vect)
{
TCNT1=0xC2F6;//装值
PORTB=(~PORTB)&(1<<PORTB5);//翻转PB5的电平
} 附上视频效果链接:
|