/*注:定时器中断的例子,简单的频率计,初学者留意各引脚电
压极性和电压值,不可超出5V,我们只是做学习实验,不要
超出51hei单片机学习板的承受范围,否则要求对电子非常熟悉,
不然会烧坏芯片, 版权:www.51hei.com,注意:P1.3与P1.7要相连接
如果是测量外部频率要共地.
*/
#include
#include
#define uchar unsigned char//宏定义
#define uint unsigned int
sbit Fin=P1^3; //测量频率管脚
sbit Fout=P1^7; //发生频率管脚
uchar code table[]={0x3f,0x06,0x5b,//数码管显示的数值
0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,};
void display(uchar *lp,uchar lc); //显示子函数
void delay(); //延时子函数
void mee_F(); //测频率子函数
void mee_T(); //测周期子函数
void Fry_mee(); //测频测周选择的子函数
uchar l_tmpdata[8]; //程序显示的缓冲区
bit int_flag; //中断事件相应的标志
uint fry; //保存的频率值
void init() ;
void main() //主函数
{
init(); // 调用初始化函数
}
void init() //初始化函数
{
uint tmp; //数据转换缓冲区
uint i=2000;//显示延时,提高亮度
EA=1; //打开总中断
TMOD=0x11;//工作方式3
TH0=256-(50000/256); //装入初值
TL0=256-(50000%256);
TH1=256-500/256;
TL0=256-500%256;
ET0=1; //定时器0开
ET1=1; //定时器1开
TR1=1; //启动定时器1
while(1)
{
Fry_mee();//开始测量
l_tmpdata[0]=tmp/10000; //测量完后将整数分离出来
tmp=tmp%10000; //进行显示
l_tmpdata[1]=tmp/1000;
tmp=tmp%1000;
l_tmpdata[2]=tmp/100;
tmp=tmp%100;
l_tmpdata[3]=tmp/10;
l_tmpdata[4]=tmp%10;
while(i--) //显示延时,提高亮度
{
display(l_tmpdata,5); //用数字显示频率
}
i=2000; //从新装入初值
}
}
void time0() interrupt 1 //定时器0的中断函数
{
int_flag=1; //中断标志
}
void time1() interrupt 3 //定时器1的中断函数,用来产生频率
{
TH1=(65536-1000)/256; //从新赋值
TL1=(65536-1000)%256;
Fout=!Fout; //?反,产生频率,即频率发生器
}
void Fry_mee()
{
if(fry<2000) //?于2k的,侧周
mee_T();
else if(fry>=2000) //大于2k的,测频
mee_F();
}
//测频原理:用一个标准的50ms计数中断,对被测信号计数
void mee_F() //测频子函数
{
bit lhj_old=1,lhj_new=1; //定义起始状态
uint f_count=0;//计数变量
int_flag=0;
TH0=(65536-50000)/256;//定时器,初值50ms
TL0=(65536-50000)%256;
TR0=1; //启动定时器0
while(1) //死循环,测频
{
lhj_new=Fin; //?现在频率引脚的状态
if(lhj_old!=lhj_new) //与前一刻的值比较
f_count++;
lhj_old=lhj_new; //将新值赋给旧值
if(int_flag) //如果到了定时时间
{
TR0=0; //关闭定时器0
fry=f_count*10; //计算频率,f_count=f_count*20/2
//一个周期有2个跳变,20个周期为1s
return; //返回
}
}
}
//测周原理:以被测信号的一个周期为中断源,对单片机及其
//周期进行计数读?定时器的值为计数值
void mee_T() //测周子函数
{
bit lhj_old=0,lhj_new=0; //定义初始状态
uchar temp_flag=0;
uint t_count; //计数变量
TH0=0; //赋初始值
TL0=0;
while(1) //死循环,测周
{
lhj_new=Fin; //取现在的频率发声引脚的状态
if(lhj_old&&!lhj_new) //当下降沿来临时,启动定时器
{
temp_flag++;
TR0=1; //启动定时器并开始计数
}
if(temp_flag==2)
{
TR0=0; //停止计数
t_count=TH0*256+TL0;//取得当前的计数值
fry=1000000/t_count;//计算频率,这个1000000是
//晶振12M经12分频的计数脉冲
return; //返回
}
lhj_old=lhj_new;
}
}
void display(uchar *lp,uchar lc) //显示子函数
{
uchar i;
P2=0;
P1=0xf8;
for(i=0;i
P2=table[lp[i]];
delay();
if(i==7)
break;
P2=0;
P1++;
}
}
void delay() //延时子函数
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
上一篇:定时器计数LED显示的简单程序
下一篇:按键控制音阶声音输出
推荐阅读最新更新时间:2024-03-16 13:12