频率是指周期性信号在单位时间(1s)内变化的次数,测量频率的仪器叫频率计。这一讲的实验主要介绍怎样用ATmega8和LCD1602液晶显示器组成数字频率计,频率测量范围为1Hz~4MHz,通过实验和学习使大家掌握ATmega8的定时器/计数器的功能和基本使用方法。
一、频率测量原理
频率测量有计数法和测量周期法这两种方法。计数法是在一定时间间隔T内计得信号重复变化的次数N,根据公式f=N/T就可以计算出频率,为了方便时间间隔T通常取1s,这样计数的结果就是频率;测量周期法是先测量信号的周期,再根据公式f=1/T即可计算出频率。上述两种测量方法各有优劣,为了提高测量精度,一般当信号频率较高采用计数法测量,而当频率较低时,由于计数法有±1的误差,这会引起较大的相对误差,因此在这种情况下就要采用测量周期法。本文为了简便只介绍计数法一种方法。
二、ATmega8的定时器 / 计数器
ATmega8单片机有3个定时器/计数器:两个8位的T/C0和T/C2,一个16位的T/C1。和51系列单片机不同的是这些定时器/计数器除有通常的定时和计数功能外,还具有捕捉、比较、PWM输出和实时时钟计数等功能。本文的实验中只用到T/CO和T/C1的计数和定时功能。
下面就案例编程中要用到的有关知识对T/CO和T/C1的有关功能进行介绍,读者在学习时参照配套程序的相关内容可加深理解。
1.8位的定时器/计数器T/C0
T/CO和T/C1都可以独立的通过预分频器将单片机的时钟频率分频后得到时钟源,也可从外部引脚输入时钟源。预分频器结构见下图。
(1)T/C0控制寄存器TCCR0
TCCR0的定义见下表。
位
7~3
2
1
0
TCCR0
CS02
CS01
CS00
TCCR0中的CS02~CS00这三个标志位用于选择时钟源,即确定预分频器的分频系数,默认值为0,其定义见下表。当选择使用外部时钟源时,在TO引脚上的逻辑电平的变化会驱动T/C0计数,这个特性使用户能通过软件来控制计数。
0
0
0
无时钟源(停止T/CO)
0
0
1
CK(系统时钟)
0
1
0
CK/8
0
1
1
CK/64
1
0
0
CK/256
1
0
1
CK/1024
1
1
0
外部TO脚.下降沿触发
1
1
1
外部TO脚,上升沿触发
(2)T/C0计数寄存器TCNT0
TCNT0是8位寄存器,其初始值为0x00,能直接进行读写访问,是T/CO的计数值寄存器。
(3)T/C0r扣断屏蔽寄存器TIMSK
位
7
6
5
4
3
2
1
0
TIMSK
OCIEE2
TOCIE2
TICIE1
OCIE1A
OCIE1B
TOIE1
-
TOIE0
TIMSK的定义见上表。TOIE0是T/CO溢出中断允许标志位(TOIE1是T/C1溢出中断允许标志位),当TOIE0被设为1,且状态寄存器SREG中的全局中断允许I位被设为1时,将使能T/C0溢出中断,若T/C0发生溢出时(TOV0=1),则执行T/CO溢出中断服务程序。
(4)T/C0中断标志寄存器TIFR
当T/CO产生溢出时,TOV0=1位被设置为1。当单片机转入执行T/CO溢出中断服务程序时,TOV0由硬件自动清零。
T/CO对每一个时钟CKT0加一计数,CKT0的来源由标志位CS02~CS00设定,当T/CO选择内部时钟源时,可用来作定时器;当选择从T0脚输入的脉冲信号作信号源时,可用来当计数器。一旦寄存器TCNT0的计数值达到0xFF时,下一个计数脉冲到来时便恢复为0x00,并继续向上开始计数。在TCNT0为0x00的同时,置溢出标志位TOV0为1,申请中断。当T/CO选择内部时钟源时,可用来作定时器,当选择从TO脚输入的脉冲信号作信号源时,可用来当计数器。在T/CO作定时器时,可以通过设置TCNTO的初始值和标志位CS02~CS00设定分频系数来设定定时时间。
2.16位的定时器/计数器T/CI
T/C1的中断屏蔽寄存器TIMSK、中断标志寄存器TIFR和T/CO使用同一个寄存器,有关标志位TOIE1、TOV1的定义和T/CO相应标志位的定义相同。T/C1除了具有T/CO的功能外,还有一些特殊的功能。
T/C1的控制寄存器有两个:TCCR1A和TCCR1B,TCCR1A主要用于T/C1的输出比较和PWM功能设定。TCCR1B主要用于T/C1输入捕获和时钟分频系数设定,TCCR1B的定义见下表。
位
7
6
5
4
3
2-0
TCCR1B
ICNC1
ICES1
-
WGMI3
WGMI2
CS2-CS10
由于T/C1的时钟源与T/CO的时钟源相同,因此标志位CS12~CS10和T/CO的标志位CS02~CS00的定义方法相同。
因为T/C1是16位定时器/计数器,因此T/C1的计数寄存器由TCNTIH并HTCNTIL这两个8位寄存器组成,TCNT1H存储高8位,TCNTIL存储低8位。TCNTIH和TCNT1L的初始值均为0x00,能直接进行读写访问。
T/C1用来作定时器、计数器的方法和T/CO相似。
三.数字频率计实验
1.实验电路
数字频率计主要由单片机ATmega8和液晶显示器LCD1602组成,采用七位数码显示。实验板上与数字频率计有关的电路部分见下图,脉冲信号通过Jl输入ATmega8的T1脚,频率测量结果通过LCD1602显示。
2.程序设计
程序有主函数、初始化函数、T/CO中断函数、T/C1中断函数、计数值处理函数、LCD显示函数和延时函数等部分组成。
程序中T/CO作定时器,定时时间为1秒。T/C1作计数器,记录由T1脚输入的的脉冲数。初始化函数中关于定时器/计数器设置的语句如下:
TCCR0=0x05;//T/C0工作于定时方式,内部1024分频
TCCRIB=0x06;//T/C1工作于计数方式,外部下降沿触发SREG=0x80;//开中断TIMSK=0x05;//T/C0、P/C1中断允许
TCNT0=4;//T/C0计数器初始值结合前面的内容就很容易搞清楚这些语句的含义。T/C1中断函数如下:
#pragma interrupt_andler
Timer1_0vf:9
void Timer1—ovf(void)
{n++;}
上面程序第一行中的数字9是中断向量,一旦T/C1的计数寄存器的计数值达到0xFFFF时,即申请中断通过中断向量转移到执行此中断函数。由于T/C1中断一次最多要输入65535(即0xFFFF)个脉冲,如果仅用它作为计数器,能记录的脉冲数最多只有65535个,也就是说用1秒作为计时单位能测量的最高频率为65535Hz。为了解决这一问题引进一个计数变量n,使得T/C1每中断一次n的值都加1,这样每过1s只要计算 65535×n+T/C1的计数寄存器计数值就能得到脉冲信号的频率了。
T/C1根据程序的设定在T1的下降沿对外部脉冲信号进行采样,为了确保对外部时钟的正确采样,要保持外部信号的转换时间至少为一个时钟周期。因此对于ATmega8的时钟频率为8MHz,假设输入的脉冲信号为方波,则能测量的最高频率为4MHz。 T/C0中断函数如下:
#pragma interrupt_handler
Timer0_ovf:10
void TimerO_ovf(void)
{
TCNT0=4;
k++:
if(k==31)//若计时满1s
{
uint m:
UNSigned long f;
k=0;
m=TCNTIL;
m=(TCNT1H<<8)+m; //取
T/C1 n次计数后计数的尾数
TCNT1H=O:
TCNT1L=0:
f:(unsigned long)
65536*n+m;//取频率值
Process(f,Data); //
计数值处理
Display(0,0,Data); /
/显示
n=O:
}
}
这一段程序主要有两个功能:一是作1秒钟定时器,二是进行数值计算并调用显示函数显示频率。
实验板上ATmega8的时钟频率为8MHz,一个时钟周期只有0.125μs,T/C0计数寄存器TCNT0计满256(即0xFF)个脉冲的时间也只有3.2ms,达不到1s定时的要求,为此采取两个措施解决这一问题,一是通过对标志值CS02~CS00的设置将时钟信号进行1024分频后再作为计数脉冲,从而延长脉冲周期;二是引入变量k对T/CO的中断次数进行计数,使得T/CO每中断一次k的值加1,这样总的延时时间为T/CO的定时时间和k的积。通过计算,我们取TCNT0的初始值为4,即TCNT0计满242个就产生一次中断,当k累加到31时所需的时间约为1s,即 (1024/8000000)×252×31=0.999936(s)≈ls,因此每过1s(即k累加到31)读一次总的脉冲数即可得到脉冲信号的频率。
3.频率测量
用下载线把配套程序的目标文件写入实验板上的ATmega8,接通实验板的电源,把一个输入幅度约5V的脉冲信号送到J 2接口,就可以在LCDl602液晶显示器显示出频率值。如果没有信号源,可以自己按下图用非门制作一个信号发生器供测试用。
在实际使用中由于被测信号往往幅度较小而且波形不规则,这时候必须加一个输入信号处理电路,其作用主要是对信号进行放大和整形。下图提供了一种用非门制作的电路。上图和下图两个电路可以用一个六非门电路CD4069做在一起,使用5V电源. 需要说明的是由于实验板上的ATmega8使用内部RC振荡器作时钟源,因此这个数字频率计的精度较低如果要提高测量精度必须使用外部晶振作时钟源。