测周法测方波频率,用AT89S52单片机的外部中断0输入待测信号,定时器T0产生标准信号,外部中断输入信号(即待测信号)两个下跳沿分别控制定时器TO的开和关,这样即测得待测信号包含多少个标准信号,乘以标准信号周期取倒数即待测频率。不过现在数据测量出来了,就是想用串口与上位机串口通信,数据发不过去,或者发过去一直是00 00 00 00 00 00 00 00(八组00)程序如下:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long int
//#define CHU 100
sbit lcden=P3^1; //1602使能端
sbit lcdrs=P2^7; //命令、数据端
sbit RW=P2^6; //读写控制端
uchar i=0; //外部中断0下调沿次数,定时功能
ulong t=0; // T0定时模式软件计数
ulong num; //暂存1S计数次数中间变量
uchar n; //固定显示字符个数
ulong a,b,c,d; //个位,十位,百位
uint e,g;
uchar code table[]="maibo cishu :"; //第一排固定显示
uchar code table1[]=" ci/min"; //第二排固定单位显示
uchar code table2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //1602调用0到9数字库
void delay(uint z) // 1ms延时
{
uint a;
for(z;z>0;z--)
for(a=110;a>0;a--);
}
void write_com(uchar com) // 1602写命令
{
lcdrs=0;
P0=com;
RW=0;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) // 1602写数据
{
lcdrs=1;
P0=date;
RW=0;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init() // 1602初始化
{
lcden=0;
write_com(0x38); //功能设定,4/8位数据等
write_com(0x0e); //显示状态开/关
write_com(0x06); //设置光标
write_com(0x01); //清屏
write_com(0x80); //显示位址 第一行:80H-A7H 第二行:C0H-E7H
}
void display(ulong n)
{
a=n%10; //个位
b=n/10%10; //十位
c=n/100%10; //百位
d=n/1000%10; //千位
write_com(0xc6); //第二行第六个显示块
write_data(table2[d]);
delay(2);
write_com(0xc7); //第二行第六个显示块
write_data(table2[c]);
delay(2);
// if(c==0) //百位为0不显示
// {
// write_com(0xc5); //第二行第六个显示块
// write_data(0x20);
// delay(20);
// }
write_com(0xc8); //第二行第七个显示块
write_data(table2[b]);
delay(2);
// if(c==0&&b==0) //十位为0不显示
// {
// write_com(0xc6); //第二行第七个显示块
// write_data(0x20);
// delay(20);
// }
write_com(0xc9); //第二行第八个显示块
write_data(table2[a]);
delay(2);
}
void main()
{
// PS=1;
SCON=0x50; //串口模式1,允许接收;SM0 SM1 = 01; REN=1;
PCON=0x00; //波特率不倍增 SMOD=0;
TMOD=0x21; //定时器T0设置为定时模式1,服务程序为软件计时
ET0=0;
TR0=0;
TI=1; //TI 置1,以发送第一个字节
TR1=1; //启动定时器 T1
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TL1=0xfd;
TH1=0xfd; //波特率9600
EX0=1;//开外部中断0
IT0=1;//下降沿触发
// ES=1;
EA=1;
init(); // 1602初始化
while(1)
{
if(e==1)
{
display(num);
e=0;
ES=0;
SBUF=g; //向上位机传数据(此时为返回上位机发送的数据)
while(!TI);
ES=1;
TI=0; //软件清零TI,以准备发送下一帧数据
}
}
}
void exr0() interrupt 0
{
i++; //来一个外部脉冲计一次数
if(i==1)
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时满一次的时间T=CHU*t机器
ET0=1; //开定时器T0
TR0=1;
}
if(i==2) // 取i-1个周期来计数内部脉冲
{
ET0=0; //关定时器T0
TR0=0;
num=200000/t; //频率=num=1000/t 1为测了1次周期,为了显示小数点后3位再乘以1000 即1000000
// num=(40000000/10/t)*60/1000; //f=num=4000/t 4为测了4次周期,为了显示小数点后3位再乘以1000 即4000000
g=num;
//显示频率
i=0;
e=1;
t=0; //计数器清零
}
}
void timer0() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时满一次的时间T=CHU*t机器
t++; //定时满一次t加一
}