当前位置:首页 > 单片机频率计数器 湖南工程学院课设
第4章 软件部分的设计
4.1 软件设计思路
在计数器工作方式下,加至外部引脚的待测信号发生从1到0的跳变时计数器加1。外部输入在每个机器周期被采样一次,这样检测一次从1到0的跳变至少需要2个机器周期(24个振荡周期),所以最大计数速率为时钟频率的1/24(使用12MHz时钟,最大计数速率为500kHz),也就是说,使用12MHz时钟的AT89C51单片机设计的频率计数器系统,所测信号的频率不能大于500kHz,若大于则必须通过分频器分频才能测试,而本次任务的要求是对0-300kHz的信号进行测量,所以可以直接进行。
利用AT89C51单片机的TO,T1的定时/计数器功能,来完成对输入的信号进行频率计数。设置定时器0工作方式1,定时1s,并产生方波信号从P1.1引脚输出。设置定时器1工作在计数方式1,对输入脉冲进行计数,溢出产生中断。将定时器1中断定义为优先。由于16位二进制加法计数器的最大计数值为65535,1s之内可能会产生多次溢出,所以需要在中断处理程序里对中断次数进行计数。1s到后,将中断次数和计数器里的数值取出进行综合处理,处理后的数据送显示。
定时器T0的计数初值:由于定时器T0工作在定时方式时最大的定时时间大约为65ms,若要定时1s,可以采用定时10ms,中断100次来完成1s的定时。对于定时10ms来说,用定时器方式1可实现。
机器周期为:
Tp=12/晶振频率=12/12MHz=1μs 计数初值为:
X=2^n-Tc=2^16-50000=15536=3CB0H 故THO=3CH,TL0=E0H。
信号频率的计算:T1工作在计数方式时最大的计数值为2^16,假设1s内溢出C1次,最后未溢出的计数值为C2,F=C1*2^16+C2=C1*65536 +(TH1*256+TL1)。
8
4.2 软件设计流程图
开始设置输入信号频率值是复位?否计数器、定时器工作数码管显示频率值结束
软件设计流程图
4.3 源程序编写
#include
unsigned long g_iCnt=0,g_CntLock; unsigned char g_cdisnum[6];
code unsigned char g_cDistable[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char cnt10ms=0; //延时
9
void delay(unsigned int cnt) {
while(--cnt); }
/*------------------------------------------------ 定时器初始化子程序
------------------------------------------------*/ void Init_Timer0(void) {
TMOD |= 0x01; //使用模式1,16位定时器,使用\符号可以在使用多个定时
器时不受影响
TH0=0x3C; //给定初值,这里使用定时器最大值从0开始计数一直到10ms溢出 TL0=0xB0;
EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 }
void ShowToSeg(unsigned long uiNumber) {
static unsigned long PreuiNumber; if(PreuiNumber != uiNumber) {
g_cdisnum[0]=uiNumber/100000; //把计算数字的每个位存入数组。 g_cdisnum[1]=(uiNumber/10000); g_cdisnum[2]=(uiNumber/1000); g_cdisnum[3]=(uiNumber/100); g_cdisnum[4]=(uiNumber/10); g_cdisnum[5]=(uiNumber); }
PreuiNumber = uiNumber; }
void Show() {
static char num=0;
ShowToSeg(g_CntLock); P1 = num;
P0=g_cDistable[g_cdisnum[num]]; num++; if(num>5) num=0; delay(40); }
char flag=0;
10
void main() {
EX0=1; //外部中断0开 IT0=1; //边沿触发 Init_Timer0();
EA=1; //全局中断开 while(1) {
//在此添加其他程序 Show(); } }
/*------------------------------------------------ 外部中断程序
------------------------------------------------*/ void ISR_Key(void) interrupt 0 using 1 {
g_iCnt++; }
void Timer0_isr(void) interrupt 1 using 1 {
TH0=0x3C; //给定初值, TL0=0xB0;
cnt10ms++; P2^=0x01; if(20==cnt10ms) {
cnt10ms=0;
g_CntLock=g_iCnt; g_iCnt=0; } }
11
共分享92篇相关文档