📄 plj.c
字号:
#include <reg52.h> // SFR声明
#include <intrins.h>
#include <math.h>
#define ulong unsigned long
#define uchar unsigned char
#define uint unsigned int
#define udouble unsigned double
#define SYSCLK 24000 // 系统时钟频率kHz
#define STACK_START 0x60//堆栈底部
#define STACK_END 0xAF//堆栈顶部
#define disp_bit_hide 0x60 //显示位消隐
#define ts_2ms (0xffff-7962/2)//2ms 24MHz*2 0xf073
#define ts_025s 124//0.25S=2mS*124
#define ts_05s 249//0.5S=2mS*249
#define ts_1s 501//1S=2mS*500
uint code JN[5]={10000,1000,100,10,1};
uint time_ref;
uint time_refs=ts_025s;
uchar xn=2,xnb=2; //xnb=计数时间的倒数
uchar led;
uchar led_bit;
uint freq_alu_word=0; //频率计数值
uint freq_alu_hb;
uint freq_alu_lb;
idata uchar freqh_word=0; // 频率值
idata ulong flowc_word=0; // 中间比较值
idata uchar dispbuf_bcd[5]; //显示缓冲区放5个值
idata uchar disp_bcd[5]; //显示缓冲地址
sbit cs245=P3^7; //位选74HC245,“0”有效
bit start=0; //频率计数开始标志
bit busy=0; //在一个时基内,频率计数完,频率计算开始标志
uchar code tabchar[64]={
0xb7,0x12,0x67,0x76,0xd2,0xf4,0xf5,0x16, //0~7,+00H
0xf7,0xf6,0xd7,0xf1,0xa5,0x73,0xe5,0xc5, //8~F,+08H
//数码显示:CHR 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
0xbf,0x1a,0x6f,0x7e,0xda,0xfc,0xfd,0x1e, //0.~7. +10h
0xff,0xfe,0xdf,0xf9,0xad,0x7b,0xed,0xcd, //8.~f. +18h
//数码显示带点:CHR 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,A.,B.,C.,D.,E.,F.
0x00,0x50,0x12,0x85,0x41,0x71,0xc7,0x97, // 灭 ,'-',-1 ,'R','r' ,'o','P','N','L'+20h
0xa1,0x51,0xd3,0x00,0x00,0x00,0x00,0x00, //L,n,H +28h
//字符显示: 灭 ,'-',-1 ,'R','r' ,'o','P','N','L','n','H'
0x08,0x58,0x1a,0x8d,0x49,0x79,0xcf,0x9f, // 灭. ,'-.',-1. ,'R.','r.' ,'o.','P.','N.'+30h
0xa9,0x59,0xdb,0x00,0x00,0x00,0x00,0x00 //L.,n.H.+38h
};//字符带点: 灭. ,'-.',-1. ,'R.','r.' ,'o.','P.','N.','L.','n.','H.
void disp_scan()
{ idata uchar buf;
static uint k=0;
k++;
if(k==500)
{k=0; P2=~P2;}
//led=4; //5个数码管
//led_bit=1; //LED位控制位,最低位选中,
cs245=0;
P3=disp_bit_hide; //显示位消隐
_nop_();
P3=0x7f&led_bit; //开第一个数码管
_nop_();
P1=0x00;
buf=dispbuf_bcd[led];
P1=tabchar[buf];
led--; //扫描位计数,更新下一个数码管缓冲区里显示数值
led_bit=led_bit<<1; //数码管位控移位,16进制数为,0x01,0x02,0x04,0x08,0x10,再回到0x01
//if((led_bit==0x10)|(led==0))
//{led_bit=1;led=4;} ////一次五位显示循环完毕,重新赋扫描初值
if(led>4|led_bit>0x10 |led_bit==0x00)
{led=4;led_bit=1;} //一次五位显示循环完毕,重新赋扫描初值
}
void disp_start() //显示(0.--9.)
{ uchar i;
for(i=0;i<5;i++)
{ dispbuf_bcd[i]=i+16;}//显示缓冲数据区里的值从0---4
//delay(500);
//for(j=5;j<10;j++)
//{dispbuf_bcd[j-5]=j+16;}
}
void freq_alu() //频率计算
{ ulong freq_reg; // 最终频率计算值 32位数
freq_reg=freq_alu_hb; //存高16位
freq_reg=freq_reg<<16; //移动16次 到32位的高16值
freq_reg=freq_reg+freq_alu_lb; //高16+低16位
freq_reg=freq_reg<<xnb;//计数值freq_reg/计数时间 (xnb=计数时间的倒数)
flowc_word=freq_reg; //计算出来的频率值
if(xn!=xnb){xnb=xn;}
}
void freq_bcd_n(ulong N)
{ ulong M;
uchar i,j,dot;
//N=flowc_word;
dot=3; //小数点默认在第3位(0000.0)K
if(N<100000)
{ dot=1; //小数点第一位
time_refs=ts_1s; //频率低于10,时基改变为1S
xnb=0;}
else if (N<1000000)
{ dot=2; //小数点定位在位2(000.00kHz)
time_refs=ts_05s; //默认时基
xn=1;
M=N%10;
N=N/10;
if(M>4){N++;} //末位四舍五入
}
else //if(N<10000000)
{ dot=3; //小数点定位在位3(0000.0kHz)
time_refs=ts_025s; //默认时基
xn=2;
M=N%100;
N=N/100;
if(M>49){N++;} //末位四舍五入
}
//BCD码转化成5位十进制数,最高位从disp_bcd[0]开始
for(i=0;i<=4;i++)
{disp_bcd[i]=N/JN[i];
N=N%JN[i];
}
disp_bcd[dot]=disp_bcd[dot]+0x10;//小数点位置 加16
if(dot=1&(disp_bcd[0]==0)) //如果小数点在第一位并且第一个数码管的值为0
{disp_bcd[0]=0x20;} //消隐
for(j=0;j<5;j++)
{dispbuf_bcd[j]=disp_bcd[j];}
}
void delay(uint n)
{ uint i;
uchar j;
for(i=0;i<n;i++)
for(j=0;j<255;j++)
{;;}
}
void freq_start()
{ //cs245=0;
EX0=0;//外中断0禁止
ET0=1;
ET1=1;
TR1=0;//停止计数
TF1=0;//清溢出标志
TH1=0;//清计数初值
TL1=0;
TH0=0xf0; //2毫秒定时初值
TL0=0x60;
freq_alu_word=0;
time_ref=time_refs;
TR0=1;
TR1=1;
PT0=1;
start=1;
}
void Timer0() interrupt 1 using 1
{
TF0=0; //中断溢出标志清0
TH0=0xf0; //2毫秒定时初值
TL0=0x60;
if(start) //如果频率计数开始
{if(time_ref--==0)
{freq_alu_lb=TH1*256+TL1;
freq_alu_hb=freq_alu_word;}
busy=1;
time_ref=time_refs;
freq_start();
}
disp_scan();
}
void Timer1()interrupt 3 using 1
{freq_alu_word++;}
void timer0_count1_init()
{ TMOD=0x51; //T0用来定时 T1用来计数
TH0=0xf0; //2毫秒定时初值
TL0=0x60;
TH1=0; //计数器1初值
TL1=0;
TR0=1;
TF0=0;
IT0=0; //下降沿有效
PT0=1; //中断0优先
EA=0;
}
void main()
{ led=4;
led_bit=1;
TMOD=0x51; //T0用来定时 T1用来计数
TH0=0xf0; //2毫秒定时初值
TL0=0x60;
TH1=0; //计数器1初值
TL1=0;
TR0=1;
ET0=1;
PT0=1;
timer0_count1_init(); //定时/计数初始化
EA=1;
disp_start(); //开始显示(0.-9.)
delay(1000); //延迟1S
freq_start(); //频率计数开始
for(;;)
{if(busy)
{freq_alu(); //频率计算
freq_bcd_n(flowc_word);//计算的频率值转化成10进制数 }
busy=0;
}
freq_start();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -