打开APP
未登录
开通VIP,畅享免费电子书等14项超值服
开通VIP
首页
好书
留言交流
下载APP
联系客服
数字频率计 用单片机定时器和中断来实现 带流程图 调试程序 实物图
共同成长888
>《单片机程序》
2019.12.30
关注
分享一个用单片机定时器和int0中断来实现的数字频率计.下面是所有资料下载:
单片机频率计diy.zip
(909.7 KB, 下载次数: 74)
流程图、调试、实测图片
LCD初始化:
测忙:
低频测量:
高频测量:
主程序流程:
总电路图:
电源:
仿真调试:
实测拍摄:
源程序:
# include
# include //为了后面的_nop_而包含的
/*****************************************
P0------DB0~DB7
P2.5------RS
P2.6------RW
P2.7------E
*****************************************/
# define uchar unsigned char
# define uint unsigned int
# define ulint unsigned long int
# define LCD_DB P0 //P0口送数据
typedef bit BOOL; //51头文件里面没有,要定义
uchar data count=0; //外部脉冲个数 (低)
ulint data time; //总计时时间
uchar data T0_count=0; //计数器T0计数值(低)
uint data freq10; //10倍实际频率 (低)
uint data f_count; //高频脉冲个数 (高)
uchar data t; //作为50ms*10=500ms,t=10 (高)
uint data fg; //高低频标志fg=2测高频,fg=1测低频
sbit LCD_RS=P2^5;
sbit LCD_RW=P2^6;
sbit LCD_E=P2^7;
uchar table1[]=" Frequence: ";
uchar table2[]=" Hz ";
uchar table3[]=" Welcome ";
uchar table4[]=" on_no ";
/*****************函数声明**********************/
void LCD_init(void); //初始化函数
void LCD_write_command(uchar command); //写指令函数
void LCD_write_data(uchar dat); //写数据函数
void delay_n50us(uint n); //延时函数
BOOL LCD_bz(); //测忙
void initial(); //高频测量定时器初始化
void lcepin();
void hcepin(); //高频率测量
void chuan();
//*******************LCD显示********************
//******************初始化函数***************
void LCD_init(void)
{
delay_n50us(30); //延时
LCD_write_command(0x38); //设置8位格式,2行,5x7
delay_n50us(10); //延时
LCD_write_command(0x38); //设置8位格式,2行,5x7
delay_n50us(10); //延时
LCD_write_command(0x38); //设置8位格式,2行,5x7
LCD_write_command(0x38); //设置8位格式,2行,5x7
LCD_write_command(0x08); //显示关闭
LCD_write_command(0x01); //清除屏幕显示
LCD_write_command(0x06); //设定输入方式,增量不移位
LCD_write_command(0x0c); //整体显示,关光标,不闪烁
delay_n50us(10); //延时
}
//*********测忙函数*****************
BOOL LCD_bz()
{
BOOL result;
LCD_RS = 0; //读状态要求。低
LCD_RW = 1; //高
LCD_E = 1; //高
_nop_();
_nop_();
_nop_();
_nop_();
result = (BOOL)(P0 & 0x80);
LCD_E = 0; //拉低,为写准备高脉冲
return result;
}
//********写指令函数************
void LCD_write_command(uchar dat)
{
while(LCD_bz());
LCD_E=0; //先拉低,准备高脉冲
LCD_RS=0; //拉低
LCD_RW=0; //拉低
LCD_E=1; //拉高
LCD_DB=dat;
delay_n50us(10);
LCD_E=1; //使能,高脉冲
delay_n50us(20);
LCD_E=0; //拉低
}
//********写数据函数*************
void LCD_write_data(uchar dat)
{
while(LCD_bz());
LCD_E=0; //先拉低,准备高脉冲
LCD_RS=1; //拉高
LCD_RW=0; //拉低
LCD_DB=dat;
delay_n50us(10); //延时
LCD_E=1; //使能,高脉冲
delay_n50us(20);
LCD_E=0; //拉低
}
//************延时函数***************
void delay_n50us(uint n)
{
uint i;
uint j;
for(i=n;i>0;i--)
for(j=2;j>0;j--) ;
}
//*****************************************
//*************T0计时(低)*************
void timer0() interrupt 1
{
T0_count++;
}
//*****INT0中断函数(计外部脉冲)(高、低)*******
void counter() interrupt 0
{
if(fg==1)
{
count++; //低频个数计数加1
if(count==1)
TR0=1; //T0启动
if(count==11) //计完十个周期
{
TR0=0;
EX0=0;
count++;
}
}
if(fg==2)
f_count++; //高频脉冲个数加1
}
//******************低频率测量*****************
void lcepin()
{
EX0=1; //INT0中断允许
TR0=0;
time=0; //总计时时间清零
while(1) //等待10个周期完成
{
if(count>11) break;
}
count=0; //外部脉冲个数清零
time=T0_count*65536+TH0*256+TL0; //总的计时时间
T0_count=0; //计数器计数值清零
TH0 = 0; //计数器初值全部清0
TL0 = 0;
freq10=10000000/time; //取出整数部分
if(freq10>=1000)
fg=2; //频率大于1000修改标志位
else{
table2[4]=0x30+(freq10/100); //百位
freq10=freq10%100;
if(table2[4]<0x31) //百位判断消隐
table2[4]=0x20;
table2[5]=0x30+(freq10/10); //十位
if((table2[5]<0x31)&&(table2[4]<0x31)) //十位消隐
table2[5]=0x20;
table2[6]=0x30+(freq10%10); //个位
table2[7]='.';
table2[8]=0x30+((10000000%time)*10)/time; //小数第一位
table2[9]=0x20; //清空,防止乱码
table2[10]=0x20;
table2[11]=0x20;
}
}
//****************************************************
//****************高频测量定时计数器初始化***********
void initial()
{
TMOD=0x11; //T1计时工作方式1
IT0=1; //INT0下降沿触发
TH1=0x3c;
TL1=0xb0; //定时初值的计算:50ms*20=1s
EA=1; //全局中断允许
ET1=1; //T1中断允许
TH0=0; //清零
TL0=0; //清零
ET0=1; //定时器0中断允许
TR0=0; //关T0中断
TR1=0; //关T1中断
}
//******************高频率测量*****************
void hcepin()
{
t=20;
f_count=0; //脉冲计数初值为0,
EX0=1; //INT0中断允许,开始计数
TR1=1; //启动定时器1
while(EX0); //等待INT0中断关闭
TR1=0; //关T1中断
f_count=f_count-1; //得实际频率
if(f_count<1000)
fg=1;
else
{
table2[4]=0x30+(f_count/10000); //万位
if(table2[4]<0x31)
table2[4]=0x20; //万位消隐
f_count=f_count%10000;
table2[5]=0x30+(f_count/1000); //千位
f_count=f_count%1000;
table2[6]=0x30+(f_count/100); //百位
f_count=f_count%100;
table2[7]=0x30+(f_count/10); //十位
f_count=f_count%10;
table2[8]=0x30+(f_count); //个位
table2[9]= 0x20;
table2[10]= 0x20;
table2[11]= 0x20;
}
}
//**************内部计时T1(高)****************
void dingshit1() interrupt 3
{
TH1=0x3c;
TL1=0xb0; //重装初值
t--;
if(t==0)
{
EX0=0; //1秒定时结束INT0中断关闭,结束计数
t=20;
}
}
//*****************************************************************
//************主函数*********************
void main(void)
{ uint j; //用于控制字符串输出的位置
LCD_init(); //LCD初始化
IP=0x01;
fg=1; //首次进入为测低频
LCD_write_command(0x80); //写第一行 “Welcome”
for(j=0;j<15;j++)
{
LCD_write_data(table3[j]);
}
LCD_write_command(0xc0); //写第二行 “on_no”
for(j=0;j<15;j++)
{
LCD_write_data(table4[j]);
}
initial(); //初始化
while(1)
{
if(fg==2)
{
hcepin(); //进入高频测量
}
if(fg==1)
{
lcepin(); //进入测低频
}
LCD_write_command(0x80); //写第一行 “Frequence:”
for(j=0;j<15;j++)
{
LCD_write_data(table1[j]);
}
LCD_write_command(0xc0); //写第二行 “频率值”
for(j=0;j<15;j++)
{
LCD_write_data(table2[j]);
}
}
}
复制代码
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报
。
打开APP,阅读全文并永久保存
查看更多类似文章
猜你喜欢
类似文章
【热】
打开小程序,算一算2024你的财运
51单片机的LCD12864显示
晨辉教你轻松学51--------液晶篇(1602)
[51单片机] 初学者自制的时钟:每行代码都有备注,进来不亏
基于AT89S52单片机的LCD12864液晶显...-数码硬件信息网
1602显示程序
模数转换IC ADC0809的使用制做之二
更多类似文章 >>
生活服务
热点新闻
留言交流
回顶部
联系我们
分享
收藏
点击这里,查看已保存的文章
导长图
关注
一键复制
下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!
联系客服
微信登录中...
请勿关闭此页面
先别划走!
送你5元优惠券,购买VIP限时立减!
5
元
优惠券
优惠券还有
10:00
过期
马上使用
×