找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5051|回复: 0
收起左侧

51单片机频率计Proteus仿真+程序+元件清单 LCD1602显示

[复制链接]
ID:118735 发表于 2019-5-28 21:41 | 显示全部楼层 |阅读模式
51单片机频率计,可以测量0-500Khz的频率 ,采用计数器的方式采集,里边附有论文资料。采用Proteus仿真,程序在下边压缩包里,自取按键支持保存频率和回看历史记录数据
0.jpg 0.jpg
1.单片机+最小系统+LCD1602液晶显示模块+NE555模块+电位器调节模块+按键模块
      2.采用LCD1602液晶显示频率值,测量范围0~500KHZ(理论上500KHZ,实际480KHZ左右)。
      3.配有鳄鱼夹,可以随意测量外部的频率。拨动开关,也可以测NE555产生的频率,通过电位器调节频率值的大小。

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

仿真截图

仿真截图


元件清单:
1    104    直插瓷片电容    2
2    10uf    直插电解电容    1
3    30p    直插瓷片电容    2
4    LCD1602    液晶显示器    1
5    CON2    排针2-Pin    1
6    12MHZ    晶振    1
7    SW-PB    按键6X6X5MM    1
8    POWER    DC电源插座    1
9    S9013    NPN三极管    1
10    10K    色环电阻    1
11    1k    色环电阻    2
12    2.2k    色环电阻    1
13    10K    电位计可调电阻    1
14    SW-SPST    波动开关    1
15    SW8*8    自锁开关    1
16    MCU    单片机    1
17    555    555芯片    1
配套器材            
1    导线    XXcm    1
2    焊锡    XXcm    1
3    USB转DC3.5mm电源线    系统供电    1
4    7*9万用板        1
5    单片机插座    40脚IC座    1
6    IC插座    8脚IC座    1
7    2P杜邦线    公对母    1
8    16P排针        1
9    16P排母        1

单片机源程序如下:
  1. //包含头文件
  2. #include <reg52.h>
  3. #include <math.h>
  4. #define uc unsigned char
  5. #define ui unsigned int
  6. #define     u8                          unsigned char
  7. #define     u16                   unsigned int
  8. #define     uchar                          unsigned char
  9. #define     uint                   unsigned int
  10. unsigned char dispbuf[6]={0,0,0,0,0,0};   //显示数据暂存数组
  11. unsigned char temp[6];                                           //频率值暂存数组
  12. unsigned char T0count;                                           //计数器计满次数,计满一次对应的脉冲数为65536个
  13. unsigned int timecount;                                   //定时器定时1秒的变量,每次对应为50ms,计20次对应就是1秒,然后计算一秒内的计数器脉冲个数
  14. bit flag;                                                                   //计时到1秒时该标志位置1,进行脉冲数的运算,得出结果送显示,然后该位清零,重新开始脉冲计数
  15. unsigned long x;                                                   //计算脉冲的数据范围一般比较大,所以用无符号长整形变量定义该变量


  16. /***********************************************************************************************************
  17. LCD1602相关函数
  18. ***********************************************************************************************************/
  19. //LCD管脚声明 (RW引脚实物直接接地,因为本设计只用到液晶的写操作,RW引脚一直是低电平)
  20. sbit LCDRS = P2^7;
  21. sbit LCDEN = P2^6;
  22. sbit D0                 = P0^0;
  23. sbit D1                 = P0^1;
  24. sbit D2                 = P0^2;
  25. sbit D3                 = P0^3;
  26. sbit D4                 = P0^4;
  27. sbit D5                 = P0^5;
  28. sbit D6                 = P0^6;
  29. sbit D7                 = P0^7;
  30. //LCD延时
  31. void LCDdelay(uint z)                  //该延时大约100us(不精确,液晶操作的延时不要求很精确)
  32. {
  33.   uint x,y;
  34.   for(x=z;x>0;x--)
  35.     for(y=10;y>0;y--);
  36. }
  37. //LCD写数据
  38. void LCD_WriteData(u8 dat)         
  39. {
  40.         if(dat&0x01)D0=1;else D0=0;
  41.         if(dat&0x02)D1=1;else D1=0;
  42.         if(dat&0x04)D2=1;else D2=0;
  43.         if(dat&0x08)D3=1;else D3=0;
  44.         if(dat&0x10)D4=1;else D4=0;
  45.         if(dat&0x20)D5=1;else D5=0;
  46.         if(dat&0x40)D6=1;else D6=0;
  47.         if(dat&0x80)D7=1;else D7=0;
  48. }
  49. //写命令
  50. void write_com(uchar com)
  51. {
  52.   LCDRS=0;                                 
  53.         LCD_WriteData(com);
  54.   LCDdelay(5);
  55.   LCDEN=1;
  56.   LCDdelay(5);
  57.   LCDEN=0;
  58. }
  59. //写数据
  60. void write_data(uchar date)
  61. {
  62.   LCDRS=1;
  63.         LCD_WriteData(date);
  64.   LCDdelay(5);
  65.   LCDEN=1;
  66.   LCDdelay(5);
  67.   LCDEN=0;
  68. }

  69. /*------------------------------------------------
  70.               选择写入位置
  71. ------------------------------------------------*/
  72. void SelectPosition(unsigned char x,unsigned char y)
  73. {     
  74.         if (x == 0)
  75.         {     
  76.                 write_com(0x80 + y);     //表示第一行
  77.         }
  78.         else
  79.         {      
  80.                 write_com(0xC0 + y);      //表示第二行
  81.         }        
  82. }
  83. /*------------------------------------------------
  84.               写入字符串函数
  85. ------------------------------------------------*/
  86. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
  87. {     
  88.         SelectPosition(x,y) ;
  89.         while (*s)
  90.         {     
  91.                 write_data( *s);     
  92.                 s ++;     
  93.         }
  94. }
  95. //========================================================================
  96. // 函数: void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)
  97. // 应用: LCD_Write_Char(0,1,366,4) ;
  98. // 描述: 在第0行第一个字节位置显示366的后4位,显示结果为 0366
  99. // 参数: x:行,y:列,s:要显示的字,l:显示的位数
  100. // 返回: none.
  101. // 版本: VER1.0
  102. // 日期: 2013-4-1
  103. // 备注: 最大显示65535
  104. //========================================================================
  105. void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)
  106. {     
  107.         SelectPosition(x,y) ;

  108.         if(l>=5)
  109.                 write_data(0x30+s/10000%10);        //万位
  110.         if(l>=4)
  111.                 write_data(0x30+s/1000%10);                //千位
  112.         if(l>=3)
  113.                 write_data(0x30+s/100%10);                //百位
  114.         if(l>=2)
  115.                 write_data(0x30+s/10%10);                        //十位
  116.         if(l>=1)
  117.                 write_data(0x30+s%10);                //个位

  118. }

  119. //1602初始化
  120. void Init1602()
  121. {
  122.   uchar i=0;
  123.   write_com(0x38);//屏幕初始化
  124.   write_com(0x0c);//打开显示 无光标 无光标闪烁
  125.   write_com(0x06);//当读或写一个字符是指针后一一位
  126.   write_com(0x01);//清屏
  127.         
  128. }
  129. void display()                                                          //显示函数
  130. {
  131.         unsigned int j;                                                  //定义变量用于显示延时        
  132.         if(dispbuf[5]!=0)                                          //如果十万位不为0
  133.         {
  134.                 LCD_Write_Char(1,6,dispbuf[5],1) ;
  135.                 for(j=50;j>0;j--);
  136.         }
  137.         else
  138.         {
  139.                 SelectPosition(1,6) ;
  140.                 write_data(' ');        //万位
  141.         }
  142.         if(dispbuf[8]!=0||dispbuf[4]!=0)          //如果十万位和万位都不等于零
  143.         {
  144.                 LCD_Write_Char(1,7,dispbuf[4],1) ;
  145.                 for(j=50;j>0;j--);
  146.         }
  147.         else
  148.         {
  149.                 SelectPosition(1,7) ;
  150.                 write_data(' ');        //万位
  151.         }

  152.         LCD_Write_Char(1,8,dispbuf[3],1) ;
  153.         for(j=50;j>0;j--);

  154.         LCD_Write_Char(1,10,dispbuf[2],1) ;
  155.         for(j=50;j>0;j--);

  156.         LCD_Write_Char(1,11,dispbuf[1],1) ;
  157.         for(j=50;j>0;j--);

  158.         LCD_Write_Char(1,12,dispbuf[0],1) ;
  159.         for(j=50;j>0;j--);
  160. }




  161. void main(void)                                                   //主函数
  162. {
  163.         unsigned char i;
  164.         TMOD=0x15;                                                           //定义T1为定时模式,T0位计数模式
  165.         TH0=0;
  166.         TL0=0;                                                                   //计数器清零
  167.         TH1=0x3c;
  168.         TL1=0xb0;                                                           //定时器赋值(定时50ms)
  169.         TR1=1;                                                                   //打开定时器T1
  170.         TR0=1;                                                                   //打开计数器T0
  171.         ET0=1;                                                                   //打开中断允许
  172.         ET1=1;                                                                  //打开中断允许
  173.         EA=1;                                                                   //打开中断总开关
  174.         Init1602();                          //调用初始化显示函数
  175. //**********************0123456789ABCDEF***************
  176.         LCD_Write_String(0,0,"The Frequency:");  //开机界面
  177.         LCD_Write_String(1,0,"        3.570kHz");  //

  178.         while(1)                                                           //进入循环,因为括号内为常数1,不会变化,所以该表达式一直成立,又称死循环
  179.         {        
  180.                 display();                                                  //调用显示函数
  181.                 if(flag)                                                   //判断1秒时间是否到
  182.                 {
  183.                         flag=0;                                           //标志位清零,计算完脉冲数后重新开始计时计数
  184.                         x=T0count*65536+TH0*256+TL0;  //读取1秒时间内的计数个数(T0count为每次计数超过65536时进入计数中断加1)
  185.                         for(i=0;i<6;i++)                           //for循环将暂存数组内数据清零
  186.                         {
  187.                                 temp[i]=0;
  188.                         }           
  189.                         i=0;                                                   //i清零
  190.                         while(x/10)                                   //将x拆分为6个一位数
  191.                         {
  192.                                 temp[i]=x%10;                           //如果x/10不为0,将x除以10的余数赋值temp【i】
  193.                                 x=x/10;                                   //然后将x/10的商赋值给x
  194.                                 i++;                                           //i++
  195.                         }
  196.                         temp[i]=x;                                           //最高位直接赋值给temp【i】
  197.                         for(i=0;i<6;i++)                           //for循环用于将数据送入显示暂存数组
  198.                         {
  199.                                 dispbuf[i]=temp[i];           //赋值语句
  200.                         }
  201.                         T0count=0;                                           //计数器中断次数清零
  202.                         TH0=0;
  203.                         TL0=0;                                                   //计数器清零
  204.                         TR0=1;
  205.                         TR1=1;                                                  //重新打开定时计数器
  206.                 }
  207.         }
  208. }

  209. void t0() interrupt 1                                          //计数器中断函数
  210. {
  211.   T0count++;                                                           //计数超过65536,就产生一次中断
  212. }

  213. void t1() interrupt 3                                          //定时器中断函数
  214. {
  215.   TH1=0x3c;
  216.   TL1=0xb0;                                                           //50ms进入一次中断,进入中断后要重新赋初值
  217.   timecount++;                                                           //每进一次中断就是50ms,该变量加一
  218.   if(timecount==20)                                           //该变量加到20次时,代表1秒到了
  219.     {
  220.       TR0=0;                                                          //关闭计数器
  221.             TR1=0;                                                           //关闭定时器
  222.       timecount=0;                                                   //计时变量清零,准备下次定时
  223.       flag=1;                                                           //一秒时间到,该标志位置1,主函数中执行脉冲数运算与显示函数
复制代码

全部资料51hei下载地址:
频率计 - LCD1602.7z (1.6 MB, 下载次数: 163)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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