电路原理图如下:
单片机源程序如下:
- #include<reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- //单周期定闸门时间测量尽量降低误差
- //后续待实现:实现多周期定闸门时间测量以降低误差
- static bit end= 0; //周期开始结束标志,为减少中断服务工作量定义为全局变量
- uchar m=0; //保存定时器清零次数
- uchar u=0;
- uint xL,xH=0; //剩余计数次数
- unsigned long t0,c; //分别保存被测信号的周期和频率
- uchar a[]={'F',':','w','a','i','t','.','.','.','.','.','H','z'}; //频率数据结果保存
- sbit lcdrw=P1^6;
- sbit lcdrs=P1^7;
- sbit lcden=P2^4;
- void delay(uint s)//延时1MS
- {
- uint r,g;
- for(r=s;r>0;r--)
- for(g=10;g>0;g--); //原值为110,我改为了10,做实际产品时可能要改回去
- }
- /////////////////LCD1602的设置//////////////////
- void write_com(uchar com) // 写指令
- {
- lcdrs=0; //低电平0时选择指令寄存器
- P0=com;
- delay(5);
- lcden=1; //高电平(1)时读取信息
- delay(5);
- lcden=0; //负跳变时执行指令
- }
- void write_data(uchar date) // 写数据
- {
- lcdrs=1; //高电平1时选择数据寄存器
- P0=date;
- delay(5); //高电平(1)时读取信息
- lcden=1;
- delay(5);
- lcden=0; //负跳变时执行指令
- }
- void initlcd()//初始化LCD1602
- {
- lcdrw=0; //低电平(0)时进行写操作
- lcden=0; //负跳变时执行指令
- write_com(0x38);//显示模式设置
- write_com(0x0c); //显示开,开游标,不闪烁
- write_com(0x06); // 字符时整体不移动
- }
- ////////////LCD1602设置///////////////////////
- ///////////定时计数器外部中断设置//////////////
- void CTINT0_init() //定时计数器0和外部中断0初始化
- {
- TMOD = 0x1; //T0工作在模式1,定时方式FHP
- TH0=0; //定时计数器初值清零
- TL0=0;
- EA=1; //开总中断
- ET0=1; //开Timer0中断
- EX0=1; //开外部中断0
- IT0=1; //设置外部中断方式为下降沿触发
- }
- ///////////定时计数器外部中断设置//////////////
- ////////////////中断服务函数//////////////////
- void ITC0() interrupt 0 //外部中断0服务程序
- {
- if(end) //FHP被测信号一个周期结束做三件事情:1、记录周期相关数据;2、定时计数器清零并停止;3、告知下次中断为周期开始
- {
- u=m; //读定时计数器0溢出次数
- TR0=0; //停止计时器
- xH=TH0; //读定时计数器0当前值
- xL=TL0;
- end = 0; //设置下次中断为周期开始
- }
- else //FHP被测信号一个周期开始做一件事情:启动计时器
- {
- TH0=TL0=0; //定时计数器初值清零
- TR0=1; //启动计时器
- m=0; //溢出次数清零
- end = 1; // //设置下次中断为周期结束
- }
- }
- void TIME0() interrupt 1 //定时计数器0溢出中断服务程序
- {
- m++; //溢出次数加1
- }
- ////////////////中断服务函数//////////////////
- void main()
- {
- uchar i;
- CTINT0_init(); //定时计数器外部中断初始化
- initlcd(); //液晶显示初始化
- while(1)
- {
- t0=u*65536 + xH*256 + xL; //计算周期
- c=1000000000/t0; //计算频率,保存的是频率扩大了1000倍的值
- //计算结果逐位保存,首先是小数点后三位
- a[10]=c%10+'0';
- a[9]=(c/10)%10+'0';
- a[8]=(c/100)%10+'0';
- c /= 1000;//下面是整数部分
- a[6]=c%10+'0';
- a[5]=(c/10)%10+'0';
- a[4]=(c/100)%10+'0';
- a[3]=(c/1000)%10+'0';
- a[2]=(c/10000)%10+'0';
- write_com(0x80);
- for(i=0;i<=12;i++)
- {
- write_data(a[i]);
- delay(2); //现在延时只有0.2ms,实际做产品时可能要加长
- }
- }
- }
复制代码
所有资料51hei提供下载:
数字频率计单周期实现.rar
(563.21 KB, 下载次数: 87)
|