基于51单片机频率测量仪的问题

王兰花 2018-07-23 10:31:19
我的思路就是t0计数,t1计时,然后在1602显示,但是误差很大,程序应该出现问题,可是我检查不出来。60kHz显示为000059Hz,希望大家能帮我看看!!
#include<reg51.h>
#define uchar unsigned char
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^2;
int k = 0;
int f;
uchar count;
uchar tab_freq[]={0,0,0,0,0,0,0}; //频率数组
void delay(int x){ //延时
int i;
for(i=x;i>0;i--);
}
void write_com(char com){ //写指令
P0=com;
RS=0;RW=0;EN=1;
delay(200);
EN=0;
}
void write_dat(char dat){ //写数据
P0=dat;
RS=1;RW=0;EN=1;
delay(200);
EN=0;
}
void lcd_init(){ //初始化
write_com(0x01);
write_com(0x38);
write_com(0x0f);
write_com(0x06);

}
void int_count0() interrupt 1{ //T0计数
k++;
}
void int_time1() interrupt 3{ //T1定时中断函数开始{
TH1=0x3c;
TL1=0xb0; //50MS
count++;
if(count>=20)
{
count=0;
TR0=0; //到1秒T0停止计数
TR1=0;
f=k;
k=0; //T1停止定时
TH1=0x3c;
TL1=0xb0;
}
}
void trans_count() //计算出一秒钟收到的脉冲数量
{
unsigned long int z;
int i;
z = f*65536 + TH0 * 256 + TL0;
if(z>9999999) //最大量程为999999
{z=9999999;}
for(i = 6;i > 0;i--)
{
tab_freq[i]=z%10+'0';
z /= 10;
}
}
void main(){
uchar i;
TMOD = 0x15; //T0为计数模式:方式1 T1为定时模式:方式1
TH0 = 0; //T0计数初始值
TL0 = 0;
TR0=1;
TR1=1;
TH1 = 0x3c; //T1定时初始值
TL1 = 0xb0; //50MS
EA = 1;
ET1 = 1; //允许T1定时中断
ET0 = 1; //允许T0计数中断
lcd_init();
trans_count();
for(i=0;i<7;i++)
{
write_dat(tab_freq[i]); //显示频率值
}
write_dat('H');
write_dat('z'); //显示Hz
delay(20000);
write_com(0x02);
}




...全文
559 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianxj001 2018-07-25
  • 打赏
  • 举报
回复
分辨率和你的计数读数定时周期密切相关,定时周期1S的,分辨率是频率的一个LSB。达到这个水平都可以认为正常。
程序是这样设计的:
选择一个定时器,选择1Hz的整数倍周期,设置定时器,然后在中断进行计数,到整数倍,就是1S。
选择另一个定时器,单纯计数模式,无中断,外脉冲计数,通过上一个定时器的1S周期,对定时器进行读数,清零,转换输出显示。
dceacho 2018-07-24
  • 打赏
  • 举报
回复
你自己找BUG吧
目前我只发现计时1秒时TL0,TH0没清零
worldy 2018-07-24
  • 打赏
  • 举报
回复
定时器0设置为计数模式,不要使用中断,定时器1设置计时模式,使用中断

定时器1中断发生时 两个全局变量R0、R1
R0=R1;
R1=count0;
dc=R1-R0;
f=dc/dT (dT为你的定时器1的定时值)
dceacho 2018-07-23
  • 打赏
  • 举报
回复
流程有问题
main()中执行到trans_count()时间太短了,计数太少,结果会有误差
王兰花 2018-07-23
  • 打赏
  • 举报
回复
引用 2 楼 hqyj34984395 的回复:
楼主可以看一下51单片机的视频教程呢,
。。。。我学过了
hqyj34984395 2018-07-23
  • 打赏
  • 举报
回复
楼主可以看一下51单片机的视频教程呢,
王兰花 2018-07-23
  • 打赏
  • 举报
回复
希望大家能帮我看看
王兰花 2018-07-23
  • 打赏
  • 举报
回复
引用 8 楼 wangfan027 的回复:

#include<reg51.h>
#define uchar unsigned char
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^2;
int k = 0;
int f;
uchar count;
uchar tab_freq[]={0,0,0,0,0,0,0}; //频率数组
unsigned long int z;
void delay(int x){ //延时
int i;
for(i=x;i>0;i--);
}
void write_com(char com){ //写指令
P0=com;
RS=0;RW=0;EN=1;
delay(200);
EN=0;
}
void write_dat(char dat){ //写数据
P0=dat;
RS=1;RW=0;EN=1;
delay(200);
EN=0;
}
void lcd_init(){ //初始化
write_com(0x01);
write_com(0x38);
write_com(0x0f);
write_com(0x06);

}
void int_count0() interrupt 1{ //T0计数
k++;
}
void int_time1() interrupt 3{ //T1定时中断函数开始{
TH1=0x3c;
TL1=0xb0; //50MS
count++;
if(count>=20)
{
count=0;
TR0=0; //到1秒T0停止计数
TR1=0;
f=k;
k=0; //T1停止定时

z = f*65536 + TH0 * 256 + TL0;
if(z>9999999) //最大量程为999999
{z=9999999;}

TH1=0x3c;
TL1=0xb0;

TR0=1;
TR1=1;
}
}
void trans_count() //计算出一秒钟收到的脉冲数量
{
int i;
for(i = 6;i > 0;i--)
{
tab_freq[i]=z%10+'0';
z /= 10;
}
}
void main(){
uchar i;
TMOD = 0x15; //T0为计数模式:方式1 T1为定时模式:方式1
TH0 = 0; //T0计数初始值
TL0 = 0;
TR0=1;
TR1=1;
TH1 = 0x3c; //T1定时初始值
TL1 = 0xb0; //50MS
EA = 1;
ET1 = 1; //允许T1定时中断
ET0 = 1; //允许T0计数中断
lcd_init();
while(1)
{
trans_count();
for(i=0;i<7;i++)
{
write_dat(tab_freq[i]); //显示频率值
}
write_dat('H');
write_dat('z'); //显示Hz
write_com(0x02);
delay(20000);
}
}
1602显示在变化,会一直加,所以循环有问题。是不是while??
dceacho 2018-07-23
  • 打赏
  • 举报
回复

#include<reg51.h>
#define uchar unsigned char
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^2;
int k = 0;
int f;
uchar count;
uchar tab_freq[]={0,0,0,0,0,0,0}; //频率数组
unsigned long int z;
void delay(int x){ //延时
int i;
for(i=x;i>0;i--);
}
void write_com(char com){ //写指令
P0=com;
RS=0;RW=0;EN=1;
delay(200);
EN=0;
}
void write_dat(char dat){ //写数据
P0=dat;
RS=1;RW=0;EN=1;
delay(200);
EN=0;
}
void lcd_init(){ //初始化
write_com(0x01);
write_com(0x38);
write_com(0x0f);
write_com(0x06);

}
void int_count0() interrupt 1{ //T0计数
k++;
}
void int_time1() interrupt 3{ //T1定时中断函数开始{
TH1=0x3c;
TL1=0xb0; //50MS
count++;
if(count>=20)
{
count=0;
TR0=0; //到1秒T0停止计数
TR1=0;
f=k;
k=0; //T1停止定时

z = f*65536 + TH0 * 256 + TL0;
if(z>9999999) //最大量程为999999
{z=9999999;}

TH1=0x3c;
TL1=0xb0;

TR0=1;
TR1=1;
}
}
void trans_count() //计算出一秒钟收到的脉冲数量
{
int i;
for(i = 6;i > 0;i--)
{
tab_freq[i]=z%10+'0';
z /= 10;
}
}
void main(){
uchar i;
TMOD = 0x15; //T0为计数模式:方式1 T1为定时模式:方式1
TH0 = 0; //T0计数初始值
TL0 = 0;
TR0=1;
TR1=1;
TH1 = 0x3c; //T1定时初始值
TL1 = 0xb0; //50MS
EA = 1;
ET1 = 1; //允许T1定时中断
ET0 = 1; //允许T0计数中断
lcd_init();
while(1)
{
trans_count();
for(i=0;i<7;i++)
{
write_dat(tab_freq[i]); //显示频率值
}
write_dat('H');
write_dat('z'); //显示Hz
write_com(0x02);
delay(20000);
}
}
王兰花 2018-07-23
  • 打赏
  • 举报
回复
引用 6 楼 wangfan027 的回复:
[quote=引用 5 楼 sinat_33854637 的回复:]
[quote=引用 4 楼 wangfan027 的回复:]
流程有问题
main()中执行到trans_count()时间太短了,计数太少,结果会有误差
什么意思?在trans_count()后面加延时吗[/quote]
从EA=1;到trans_count()就几微妙的时间,60KHz的信号接收到的数量估计不到50个,定时器50ms还一次都没触发,这样计算结果肯定不对
你要就加演示在trans_count()前面加
而且单片机程序一般都是要套一个大循环的,类似这样

void main(){
uchar i;
TMOD = 0x15; //T0为计数模式:方式1 T1为定时模式:方式1
TH0 = 0; //T0计数初始值
TL0 = 0;
TR0=1;
TR1=1;
TH1 = 0x3c; //T1定时初始值
TL1 = 0xb0; //50MS
EA = 1;
ET1 = 1; //允许T1定时中断
ET0 = 1; //允许T0计数中断
lcd_init();
while(1)
{
trans_count();
for(i=0;i<7;i++)
{
write_dat(tab_freq[i]); //显示频率值
}
write_dat('H');
write_dat('z'); //显示Hz
delay(20000);
write_com(0x02);
}
}


另外你定时器中20次计一秒,然后各种计数清零,这种处理方法也不太合理,刚清完后如果执行trans_count(); 结果会不对


[/quote]我按照你改了之后它先显示数字后来就没了...
dceacho 2018-07-23
  • 打赏
  • 举报
回复
引用 5 楼 sinat_33854637 的回复:
[quote=引用 4 楼 wangfan027 的回复:]
流程有问题
main()中执行到trans_count()时间太短了,计数太少,结果会有误差
什么意思?在trans_count()后面加延时吗[/quote]
从EA=1;到trans_count()就几微妙的时间,60KHz的信号接收到的数量估计不到50个,定时器50ms还一次都没触发,这样计算结果肯定不对
你要就加演示在trans_count()前面加
而且单片机程序一般都是要套一个大循环的,类似这样

void main(){
uchar i;
TMOD = 0x15; //T0为计数模式:方式1 T1为定时模式:方式1
TH0 = 0; //T0计数初始值
TL0 = 0;
TR0=1;
TR1=1;
TH1 = 0x3c; //T1定时初始值
TL1 = 0xb0; //50MS
EA = 1;
ET1 = 1; //允许T1定时中断
ET0 = 1; //允许T0计数中断
lcd_init();
while(1)
{
trans_count();
for(i=0;i<7;i++)
{
write_dat(tab_freq[i]); //显示频率值
}
write_dat('H');
write_dat('z'); //显示Hz
delay(20000);
write_com(0x02);
}
}


另外你定时器中20次计一秒,然后各种计数清零,这种处理方法也不太合理,刚清完后如果执行trans_count(); 结果会不对


王兰花 2018-07-23
  • 打赏
  • 举报
回复
引用 4 楼 wangfan027 的回复:
流程有问题
main()中执行到trans_count()时间太短了,计数太少,结果会有误差
什么意思?在trans_count()后面加延时吗

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧