频率计 单片机实训报告.docx
《频率计 单片机实训报告.docx》由会员分享,可在线阅读,更多相关《频率计 单片机实训报告.docx(16页珍藏版)》请在冰豆网上搜索。
![频率计 单片机实训报告.docx](https://file1.bdocx.com/fileroot1/2023-2/6/7896d021-90fb-42d0-b1e0-b7dc9252488a/7896d021-90fb-42d0-b1e0-b7dc9252488a1.gif)
频率计单片机实训报告
《单片机原理及应用》实训报告
学号
姓名
指导教师:
2012年10月18日
实训题目:
频率计
1系统设计
1.1设计要求
1.1.1设计任务
使用555产生矩形波信号,输入到单片机进行测量频率。
1.1.2性能指标要求
1设计测频电路中波形产生部分硬件电路;
2根据测频法和测周法的优缺点选择并切换频率测量的方法.
3数码管显示频率测量的结果
4选作:
其他特殊功能。
1.2设计思路及设计框图
1.2.1设计思路
测试频率有两种方法,测周法与测频法,低频适用于测周法,高频适用测频法。
1测周法:
通过测量被测信号的周期的倒数得到频率,选用适当的时基,以被测信号作为计数的闸门进行测量,得到闸门内的计数值,与时基相乘即为被测信号的周期,周期的倒数即为频率。
该法适合测量频率低的信号。
2测频法:
通过频率的定义即单位时间的脉冲数,得到被测信号的频率。
选用适当的时基,如1秒,以此作为计数闸门,得到闸门内的计数值即为信号的频率。
该法适合测量频率高的信号。
外部的频率信号由单片机的外部中断0输入。
时基信号由内部定时器0产生,定时器1产生中断用来数码管的动态扫描。
测周法的实现:
外部中断由下降沿触发,第一次触发,打开定时器0,第二次触发关闭定时器,读出定时时间,即为周期,再转换成频率进行显示。
测频法的实现:
当第一个中断来临,打开定时器0,定时一秒,一秒的过程中,对中断次数进行统计,一秒后,停止计数,此时的数据即为频率。
555构成多谐振荡器电路。
输出高电平时间,及电容充电的时间0.693*(Ra+Rb)C;
输出低电平的时间,及电容放电时间0.693*Rb*C;
总的周期T=0.693*(Ra+2Rb)C;
占空比:
q=(Ra+Rb)/(Ra+2Rb);
由给定器件可知,两个滑阻若为0,则Ra=1K,Rb=1k,c=1uf,最小的周期为:
2.079*10E-3.
则最大的频率为1/2.079*10E-3=481HZ
最大周期:
0.693*(501000+2*501000)*1E-6=1.041s
最小的频率为1/1.041=0.96HZ;
该电路产生周期的范围是1hz到481hz
1.2.2总体设计框图
2各个模块程序的设计
主函数:
用于测频法测周法的切换
voidmain()
{
initial();
while
(1)
{
if(freq<=20)
{
cal_t();
}
else
{
cal_f();
}
}
}
数码管的显示:
uchara=0xfe;
ucharb=4;
ucharseg[10]={0xd7,0x14,0xcd,0x5d,//0~3
0x1e,0x5b,0xdb,0x15,//4~7
0xdf,0x5f
};
voiddisplay()
{
P0=a;
P2=seg[num[b-1]];//b由于硬件原因如此循环
a=a<<1|0x01;
b--;
if(b==0)
{
a=0xfe;
b=4;
}
}
频率的拆分计算:
voidtakeout(uintf)
{
num[3]=f/1000;
num[2]=f/100%10;
num[1]=f/10%10;
num[0]=f%10;
}
复位操作:
voidreset()
{
EX0=0;
TR0=0;
freqnum=0;
ms_0_1=0;
ms_10=0;
s=0;
time=0;
}
测周法程序设计:
voidcal_t()
{
EX0=1;
while(freqnum==0)
{
}
while(freqnum==1)
{
TR0=1;
if(ms_0_1)
{
time++;
ms_0_1=0;
}
if(time==10000)
{
freq=1;
reset();
return;
}
}
freq=10000/time;
takeout(freq);
reset();
}
测频法程序设计:
voidcal_f()
{
EX0=1;
TR0=1;
while(s==0)
{
}
freq=freqnum;
takeout(freq);
reset();
}
3调试过程
在调试过程中遇到了一些问题:
在频率测试到400hz时频率会跑飞,经过思考,是每次显示之前我都进行了一次频率的拆分,百位十位个位的计算,这个非常的消耗时间。
分析,并不是每次显示都需要计算,而是测试结束后只需计算一次就可以了。
所以把计算部分独立出来,写了takeout函数。
改正后显示正常。
数码管闪烁,之前使用延时的方法进行数码管动态显示。
由于计算,测频需要一定延时,导致数码管的延时时间加长会出现闪烁。
于是,数码管的动态扫描改为中断方式。
并且程序尽可能的执行效率较高,对计算测频不产生影响。
在调试555时,3脚示波器波形输出不是方波,于是测试2脚的波形,2脚正常,经过查找原因,是滑阻调的太大。
导致频率太低,将其调小后,频率升高,示波器可以测试正常。
4功能测试
4.1测试仪器与设备
示波器
4.2性能指标测试
由于555的电路原因产生的频率的范围是1hz到481hz,经测试与示波器比对,该频率计测试范围2hz到512hz。
4.3误差分析
测周法与测频法我都做了同步的处理,误差主要在单片机计时的所用的振荡源上面。
但是这个误差在1us完全可以忽略。
5实训心得体会
本次实训让我对程序的编写又有了进一步的认识。
画好流程图,有明确的思路非常有助于程序的编写。
我采用至上而下的编写方式完成。
在测频方面的算法方面我做了同步处理,使得误差减小。
本次由于是洞洞板焊接,我没有画pcb图,但是花了连线草图。
仍需要精心布局,尽量减少跳线。
在测试方面,熟练使用了示波器测试555,根据原理测试2,3脚的的波形,很快调试正常,是我明白通过懂得原理才能更好的上手。
6参考文献
喻宗泉.单片机原理与应用技术,西安科技大学出版社,2008年。
附录
附录1:
仿真图
附录2:
程序清单
#include"global.h"
#include"seg.h"
#include"isr.h"
#include"compute.h"
ucharh;
uchark;
voidmain()
{
initial();
while
(1)
{
if(freq<=20)
{
cal_t();
}
else
{
cal_f();
}
}
}
#include"seg.h"
#include"isr.h"
#include"compute.h"
uchara=0xfe;
ucharb=4;
ucharseg[10]={0xd7,0x14,0xcd,0x5d,//0~3
0x1e,0x5b,0xdb,0x15,//4~7
0xdf,0x5f
};
voiddisplay()
{
P0=a;
P2=seg[num[b-1]];//b由于硬件原因如此循环
a=a<<1|0x01;
b--;
if(b==0)
{
a=0xfe;
b=4;
}
}
#include"isr.h"
#include"seg.h"
#include"compute.h"
/*
定时器初始化
定时器0,产生时间脉冲:
0.1ms(用于测周法的基准时间)10ms(用于动态扫描数码管)1s(用于测频法的时间阀门)
*/
uchari,j;
ucharms_0_1,ms_10,s;
uintfreqnum;
ucharctime;
uchardistime;
ucharcount;
voidinitial()
{
TMOD=0x12;//8位重装模式
TH0=0x9c;
TL0=0x9c;//产生0.1ms的时间脉冲
TH1=0xec;
TL1=0x78;
ET0=1;
ET1=1;
TR1=1;
IT0=1;//下降沿触发
EA=1;
}
voidtime_pulse()interrupt1//产生0.1ms,10ms,1s三种脉冲
{
ms_0_1=1;
i++;
if(i==100)
{
ms_10=1;
i=0;
j++;
}
if(j==100)
{
s=1;
j=0;
}
}
voidfrequence()interrupt0
{
freqnum++;
}
voiddisp()interrupt3//10ms
{
TH1=0xec;
TL1=0x78;
/*count++;
if(count==5)
{
ctime=1;
}
distime=1;*/
display();
}
#include"compute.h"
#include"isr.h"
#include"seg.h"
uintfreq;
uinttime;
ucharnum[4];
voidtakeout(uintf)
{
num[3]=f/1000;
num[2]=f/100%10;
num[1]=f/10%10;
num[0]=f%10;
}
voidreset()
{
EX0=0;
TR0=0;
freqnum=0;
ms_0_1=0;
ms_10=0;
s=0;
time=0;
}
voidcal_t()
{
EX0=1;
while(freqnum==0)
{
}
while(freqnum==1)
{
TR0=1;
if(ms_0_1)
{
time++;
ms_0_1=0;
}
if(time==10000)
{
freq=1;
reset();
return;
}
}
freq=10000/time;
takeout(freq);
reset();
}
voidcal_f()
{
EX0=1;
TR0=1;
while(s==0)
{
}
freq=freqnum;
takeout(freq);
reset();
}
#ifndef_GLOBAL_H_
#define_GLOBAL_H_
#defineucharunsignedchar
#defineuintunsignedint
#include
#endif
#ifndef_SEG_H_
#define_SEG_H_
#include"global.h"
externvoiddisplay();
#endif
#ifndef_ISR_H_
#define_ISR_H_
#include"global.h"
externucharms_0_1,ms_10,s;
externuintfreqnum;
externucharctime;
externuchardistime;
externvoidinitial();
#endif
#ifndef_COMPUTE_H_
#define_COMPUTE_H_
#include"global.h"
externuintfreq;
externucharnum[4];
externvoidcal_t();
externvoidcal_f();endif;