×
单片机 > 单片机程序设计 > 详情

单片机+UA741放大整形1~10K频率计

发布时间:2024-06-02 发布时间:
|

设计要求
(1)可测正弦波、方波信号的频率,频率范围:1 Hz~10 kHz。
(2)信号Vpp为0.1 ~3 V。
(3)测试结果显示于液晶。
1.2设计总体方案
用一个定时器来定时1秒,用一个计数器来数在定时1秒内有多少次外部中断,定时器和计数器定时工作在方式1,即16位定时器/计数器。然后定时1S结束后,把计数器里面的高8位和低8位的数值取出来,换算成10进制数赋值给频率,刚好数值变化多少,频率就是多少Hz.

1.3系统结构框图

2系统硬件电路设计

2.1总体电路图

图2、总体电路图

2.2各单元模块功能

①STC89C52RC:

具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。另外 STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35MHz,6T/12T可选。

图3、STC89C52RC引脚图

②LCD1602液晶显示屏:

1602采用标准的16脚接口,其中:

第1脚:VSS为电源地

第2脚:VCC接5V电源正极

第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。

第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。

第6脚:E(或EN)端为使能(enable)端,高电平(1)时读取信息,负跳变时执行指令。

第7~14脚:D0~D7为8位双向数据端。

第15~16脚:空脚或背灯电源。15脚背光正极,16脚背光负极。

主要功能:用来显示频率

③LM393比较器:

lm393引脚图

图4、 LM393内部结构图

LM393主要功能:

输出负载电阻能衔接在可允许电源电压范围内的任何电源电压上,不受 Vcc端电压值的限制,输出部分的陷电流被可能得到的驱动和器件的β值所限制。当达到极限电流(16mA)时,输出晶体管将退出而且输出电压将很快上升。输出饱和电压被输出晶体管大约60ohm 的γSAT限制。当负载电流很小时,输出晶体管的低失调电压(约1.0mV)允许 输出箝位在零电平。

④UA741集成运放:

UA741的2脚是反相输入端,3脚是同相输入端,6脚是输出端,7脚接正电源,4脚接负电源(双电源工作时或地(单电源工作时),1脚和5脚是失调电压调零端,8脚是空脚内部没有任何连接。如下图——

图5、 UA741引脚图

主要功能:把信号放大,得到所需要的电压幅值。

⑤11.0592Mhz晶振:

晶体振荡器,能产生振荡,其特点是固有频率十分稳定,而且震动具有多谐性,除了奇频震动外还有奇次谐波泛音震动.性能上,晶振的品质因素Q和特性阻抗都非常高,而且接入系数很小,因此具有很高的频率稳定度,提供单片机工作时钟

2.3模块电路设计

电路的关键部分还是放大整形电路,下面是放大整形电路的设计模块

总体电路:

图6 、放大整形总体电路图

放大器部分:

图7、 放大部分电路图

根据实际器件的设计,我们放大器放大倍数为Au=101倍

具体算法如下

假定放大器同向输入端电压为Ui,放大器放大输出电压端电压Uo,则回路近似有以下关系

(公式1)

则放大倍数为: (公式2)

比较器部分:

图8、 比较电路设计图

我们给比较器反向输入端的基准电压为2.5v,输出端接一个上拉电阻增强输出引脚的驱动能力。当同向输入端电压大于反向输入端电压(2.5V)时,比较器输出高电平,当同向输入端电压低于反向输入端电压(2.5V)时,比较器输出低电平。
因此,以2.5V为界,当输入电压变化时,输出端反映出两种状态,高电位和低电位。

3系统软件设计

3.1程序流程图

3.2程序主要模块

程序包括,定时模块,计数模块,显示模块

定时模块是用来定时1秒给计数器,计数器在这1秒数了多少个数,再把数了多少个数拿去给显示模块显示。

4系统仿真及调试

4.1Proteus仿真

图10、 Proteus仿真图一

图11、 Proteus仿真图二

4.2实物研制及调试

4.2.1方波频率测试

结论

实训过程中遇到了很多问题,这个题目不仅关于如何写单片机的程序,还要理清放大整形电路的设计思路,一刚开始,我们也不知道怎么设计放大整形电路。然后去百度借鉴别人的设计思路,设计过程也很懊恼,各种器件的取值怎么选取,由于实验室的器材种类有限,我们还得根据实际出发,选择合适的器件。放大整形电路设计完成后,我们就根据电路来搭个原理图。我是第一次使用Altium Designer来画PCB的,使用操作有点陌生,我就根据老师的演示和课后看课本慢慢熟悉Altium Designer画PCB的过程,最后完成了自己的PCB电路。后面就是打印PCB焊接电路的过程了,实物做出来后,和仿真的还是有很大差别,特别是放大器部分,单电源无法工作,这就给我们的电路造成一个很大的错误,最后我们改成了双电源工作,电路其他部分因为双电源工作的影响,我们也改了一下。最终完成了我们的频率计的设计,频率也能测得出来了。总之实训过程很有趣和考验我们的设计能力,在实训中体会学习的快乐。



附录一:实物图

图12、实物图一

图13、实物图二


#include"reg51.h"
#define uint unsigned int
#define uchar unsigned char
#define DATAPORT P2
sbit RS=P3^2;
sbit RW=P3^6;
sbit E=P3^7;
sbit fangbo1=P3^0;//提供10Hz左右的自检信号
sbit fangbo2=P3^1;//提供1Hz左右的自检信号
uchar num;
uint f=0;//频率f
uchar code table[]="0123456789.";
uchar code table1[]="=sHZFT: ero!";
void init(void); //初始化函数声明
void writeCOM(uchar i); //写命令函数声明
void writeData(uchar j); //写数据函数声明
void fbusy(void); //检查忙函数声明
void display(); //写显示函数
void delay(uint mux)
{
uint i,j;

for(i=mux;i>0;i--)
for(j=120;j>0;j--);

}

void main()
{
TMOD=0x51;//定时器·0工作在方式1,计数器1工作在方式1,晶振11.0592M,机器周期为12/f.
TL0=(65536-46080)%256; //定时50ms初值为T(定时时间,秒)*F(晶振频率 HZ)/12, 46080、45872
TH0=(65536-46080)/256;
TL1=0;
TH1=0;
ET0=1;
EA=1;
init();
while(1)
{
TR0=1;//打开定时器
TR1=1;//打开计数器
while(num==20)
{
num=0;//定时计算清
TR0=0;//关闭定时器
TR1=0; //关闭计数器
f=(TH1*256)+TL1;//计算频率
delay(10);
TH1=0;//计数清0
TL1=0;//计数清0
}
display();//显示结果


}

}
//定时1S溢出
void interr_zd2()interrupt 1
{
TL0=(65536-46080)%256;
TH0=(65536-46080)/256;
num++;
fangbo1=~fangbo1;//产生个10Hz左右的方波
if(num==10){fangbo2=~fangbo2;}//产生个1Hz左右的方波
}
//显示屏数据
void display()
{
writeCOM(0x80);
writeData(table1[4]);//显示F:
writeData(table1[6]);
writeCOM(0x8c);
writeData(table1[2]);// 显示HZ
writeData(table1[3]);
writeCOM(0xc0);
writeData(table1[5]); // 显示T:
writeData(table1[6]);
writeCOM(0xcd);
writeData(table1[1]);// 显示S
if(f<10) //频率1位数
{
writeCOM(0x85);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table[f]);

}
if((f>=10)&(f<100))//频率2位数
{
writeCOM(0x85);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table[f/10]);
writeData(table[f%10]);


}
if((f>=100)&(f<1000))//频率3位数
{
writeCOM(0x85);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table[f/100]);
writeData(table[f%100/10]);
writeData(table[f%10]);

}
if((f>=1000)&(f<10000))//频率4位数
{
writeCOM(0x85);
writeData(table1[7]);
writeData(table1[7]);
writeData(table[f/1000]);
writeData(table[f%1000/100]);
writeData(table[f%100/10]);
writeData(table[f%10]);

}
if((f>=10000)&(f<=50000))//频率5位数
{
writeCOM(0x85);
writeData(table1[7]);
writeData(table[f/10000]);
writeData(table[f%10000/1000]);
writeData(table[f%1000/100]);
writeData(table[f%100/10]);
writeData(table[f%10]);

}
if(f>50000) //超出50khz提示错误
{
writeCOM(0x84);
writeData(table1[7]);
writeData(table1[8]);
writeData(table1[9]);
writeData(table1[9]);
writeData(table1[10]);
writeData(table1[9]);
writeData(table1[11]);
writeCOM(0xc3);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[7]);
writeData(table1[8]);
writeData(table1[9]);
writeData(table1[9]);
writeData(table1[10]);
writeData(table1[9]);
writeData(table1[11]);


}
if((0 {
writeCOM(0xc3);
writeData(table[1000000/f/1000000]);
writeData(table[10]);
writeData(table[1000000/f%1000000/100000]);
writeData(table[1000000/f%100000/10000]);
writeData(table[1000000/f%10000/1000]);
writeData(table1[7]);
writeData(table[1000000/f%1000/100]);
writeData(table[1000000/f%100/10]);
writeData(table[1000000/f%10]);
}
if(f==0) //显示周期、频率为0时算周期比较特殊
{
writeCOM(0xc3);
writeData(table[0]);
writeData(table[10]);
writeData(table[0]);
writeData(table[0]);
writeData(table[0]);
writeData(table1[7]);
writeData(table[0]);
writeData(table[0]);
writeData(table[0]);
}
}
//初始化函数
void init()
{
writeCOM(0x01); //清屏
writeCOM(0x38); //读8位数据,显示两行,使用5*7的字型
writeCOM(0x0c); //显示器开,光标关,字符不闪烁
writeCOM(0x06); //字符不动,光标自动右移一位
}
//检查忙函数
void fbusy()
{
DATAPORT=0xff; //读之前向端口写1,确保读数正确
RS=0;RW=1;
E=0;E=1; //正脉冲读
while(DATAPORT&0x80) //忙,等待
{E=0;E=1;}
}
//写命令函数
void writeCOM(uchar i)
{
fbusy();
RS=0;RW=0;
E=1;
DATAPORT=i;
E=0; //负脉冲写
}
//写数据函数
void writeData(uchar j)
{
fbusy();
RS=1;RW=0;
E=1;
DATAPORT=j;
E=0; //负脉冲写
}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于单片机的医院护理呼叫对讲系统设计