找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9014|回复: 4
打印 上一主题 下一主题
收起左侧

原创的单片机+UA741放大整形1~10K频率计Proteus仿真与实物设计

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

制作出来的实物图如下:


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)



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<f)&(f<=50000)) //计算周期,显示
                {        
              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;       //负脉冲写               
}


全部资料51hei下载地址:
频率计(1~10KHz).zip (251.61 KB, 下载次数: 71)
实训文档.docx (511.62 KB, 下载次数: 24)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:855588 发表于 2020-12-6 20:27 | 只看该作者
你好,请问有ad原理图和封装源文件吗
回复

使用道具 举报

板凳
ID:855588 发表于 2020-12-6 20:32 | 只看该作者
你好,有ad的原理图和pcb图吗
回复

使用道具 举报

地板
ID:734289 发表于 2020-12-11 17:47 | 只看该作者
你好,请问如果我还想测交流信号的电压并在液晶屏上显示该怎么做?
回复

使用道具 举报

5#
ID:734289 发表于 2020-12-11 17:49 | 只看该作者
你好,如果我还想测正弦波的峰峰值并显示该怎么做
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表