找回密码
 立即注册

QQ登录

只需一步,快速开始

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

低频数字式相位测量仪Proteus仿真+单片机代码设计

  [复制链接]
跳转到指定楼层
楼主
基于51单片机的低频数字式相位测量仪
2019全国电子设计大赛第一阶段C题
仿真and程序文件

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



单片机源程序如下:
  1. #include <reg52.h>
  2. unsigned long int fre;
  3. unsigned long int per;
  4. unsigned char time;
  5. unsigned int count;
  6. unsigned long int count1;
  7. sbit   LCD_RS=P1^0;          //片选信号
  8. sbit   LCD_RW=P1^1;          //读写信号
  9. sbit   LCD_E=P1^2;           //使能信号
  10. sbit   P20=P2^0;
  11. #define LCD_DB  P0        //数据信号
  12. unsigned char character[10]={0};//在屏幕上显示的字符串
  13. unsigned char character_1[]={"Fre= Hz"};
  14. unsigned char percentage[10]={0};//在屏幕上显示的字符串
  15. unsigned char percentage_1[]={"Per= Deg"};
  16. void LCD_init(void);//初始化函数   
  17. void LCD_write_command(unsigned char command);//写指令函数         
  18. void LCD_write_data(unsigned char dat);//写数据函数          
  19. void LCD_disp_char(unsigned char x,unsigned char y,unsigned char dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
  20. void delay_n40us(unsigned int n);//延时函数
  21. void timer1_init();            //中断初始化函数  
  22. //-----------------------------延时函数---------------------------
  23. void delay_n40us(unsigned int n)                  //延时函数
  24. {
  25.         unsigned int i;
  26.         unsigned char j;            
  27.         for(i=n;i>0;i--)
  28.         for(j=0;j<2;j++);         
  29. }
  30. void delay_1s()
  31. {
  32.         unsigned int i,j;
  33.         for(i = 0;i<100;i++)
  34.                 for(j = 0;j<1000;j++);
  35. }
  36. //---------------------lcd1602液晶显示函数--------------------                                    
  37. void LCD_init(void)         //液晶初始化函数
  38. {
  39.         LCD_write_command(0x38);//设置8位格式,2行,5x7
  40.         LCD_write_command(0x38);//设置8位格式,2行,5x7
  41.         LCD_write_command(0x38);//设置8位格式,2行,5x7
  42.         LCD_write_command(0x0c);//整体显示,关光标,不闪烁
  43.         LCD_write_command(0x06);//设定输入方式,增量不移位
  44.         LCD_write_command(0x01);//清除屏幕显示          
  45.         delay_n40us(100);//清屏延时
  46. }
  47. void LCD_write_command(unsigned char dat)  //写命令函数
  48. {
  49.         LCD_DB=dat;
  50.         LCD_RS=0;//指令         
  51.         LCD_RW=0;//写入         
  52.         LCD_E=1; //使能          
  53.         LCD_E=0;
  54.         delay_n40us(1);//写命令延时   
  55. }         
  56. void LCD_write_data(unsigned char dat)          //写数据函数
  57. {
  58.         LCD_DB=dat;
  59.         LCD_RS=1;//数据          
  60.         LCD_RW=0;//写入          
  61.         LCD_E=1;//使能  
  62.         LCD_E=0;
  63.         delay_n40us(1);         //写数据延时
  64. }
  65. void LCD_disp_char(unsigned char x,unsigned char y,unsigned char dat)//显示一个字符
  66. {
  67.         unsigned char address;
  68.         if(y==1)
  69.                  address=0x80+x;         //显示在第一排的时候的x的地址
  70.         else
  71.                  address=0xc0+x;         //显示在第二排的时候的x的地址
  72.         LCD_write_command(address);         //输入地址
  73.         LCD_write_data(dat);                 //输入数据
  74. }
  75. void LCD_disp_num(unsigned char x,unsigned char y,unsigned char dat)//显示一个数字
  76. {
  77.         unsigned char address;
  78.         if(y==1)
  79.                  address=0x80+x;         //显示在第一排的时候的x的地址
  80.         else
  81.                  address=0xc0+x;         //显示在第二排的时候的x的地址
  82.         LCD_write_command(address);         //输入地址
  83.         LCD_write_data(dat+48);                 //输入数据
  84. }
  85. void dis_num1(void)
  86. {
  87.         unsigned char i=0,j=0,k=0;
  88.         LCD_write_command(0x01);//清除屏幕显示
  89.         character[0] = fre/10000000;
  90.         character[1] = fre/1000000%10;
  91.         character[2] = fre/100000%10;
  92.         character[3] = fre/10000%10;
  93.         character[4] = fre/1000%10;
  94.         character[5] = fre/100%10;
  95.         character[6] = fre/10%10;
  96.         character[7] = fre%10;
  97.     character[8] = 'H';
  98.         character[9] = 'z';
  99.         for(i = 0;i<4;i++)                 //显示“fre=”
  100.         {
  101.                  LCD_disp_char(i+0,1,character_1[i]);
  102.         }
  103.         for(i = 0;i<10;i++)         //判断第一个不为0的数
  104.         {
  105.                 if(character[i]!=0)
  106.                         break;
  107.         }
  108.         k = 8-i;
  109.         for(j = 0;j<k;j++)         //显示所有的数字
  110.         {
  111.                         LCD_disp_num(4+j,1,character[i++]);       
  112.         }
  113.     for(i = 5;i<7;i++)         //显示“Hz”
  114.         {
  115.                  LCD_disp_char(j+4,1,character_1[i]);
  116.                 j++;
  117.         }
  118. }
  119. void dis_num2(void)
  120. {
  121.         unsigned char i=0,j=0,k=0;
  122.         LCD_write_command(0x10);//清除屏幕显示       
  123.         percentage[0] = per/100;
  124.         percentage[1] = per/10%10;
  125.         percentage[2] = per%10;
  126.         percentage[3] = 'd';
  127.         percentage[4] = 'e';
  128.         percentage[5] = 'g';
  129.        
  130.         for(i = 0;i<4;i++)                 //显示per
  131.         {
  132.                  LCD_disp_char(i+0,1,percentage_1[i]);
  133.         }
  134.         for(i = 0;i<10;i++)         //判断第一个不为0的数
  135.         {
  136.                 if(percentage[i]!=0)
  137.                         break;
  138.         }
  139.         k = 3-i;
  140.         for(j = 0;j<k;j++)         //显示所有的数字
  141.         {
  142.                         LCD_disp_num(4+j,1,percentage[i++]);       
  143.         }
  144.        
  145.     for(i = 5;i<8;i++)         //显示%
  146.         {
  147.                  LCD_disp_char(j+4,1,percentage_1[i]);
  148.                 j++;
  149.         }
  150. }
  151. //----------------主函数--------------------
  152. void main()
  153. {  
  154.      int i;
  155.          if(P20==1)
  156.          i=1;
  157.          else
  158.          i=0;
  159.          while(1)
  160.      {
  161.            if(P20==1&&i==1)
  162.            timer1_init();
  163.            while(P20==1)
  164.        {
  165.              LCD_init();
  166.                  dis_num1();         //显示
  167.                  delay_1s();
  168.                  i=0;
  169.            }
  170.            if(P20==0&&i==0)
  171.            timer1_init();
  172.        while(P20==0)
  173.        {
  174.                  LCD_init();
  175.                  dis_num2();
  176.          delay_1s();
  177.                  i=1;
  178.        }
  179.         }
  180. }
  181. //-------------------定时/计数器初始化--------------
  182. void timer1_init(void)         //定时/计数器初始化
  183. {
  184.         TMOD=0xA6;                //计数器0和定时器1工作工作方式2,自动重装初值
  185.         TH0=0;                    //计数器初值为0
  186.         TL0=0;
  187.         TR0=1;                    //计数器开始计数
  188.         ET0=1;                    //打开计数器0中断
  189.         TH1=0;                    //定时器高位,初值设为0
  190.     TL1=0;                    //定时器低位,初值设为0
  191.         TR1=1;                    //定时器开始计数   
  192.         ET1=1;                    //打开计数器1中断   
  193.         RCAP2H=(65536-62500)/256; //在程序初始化的时候给RCAP2L和RCAP2H赋值,
  194.         RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
  195.         TH2=RCAP2H;               //12M晶振下每次中断62.5ms(1s=1000ms=62.5ms×16)
  196.         TL2=RCAP2L;
  197.         ET2=1;                    //打开定时器2中断         
  198.         TR2=1;                    //定时器2开始计时  
  199.         EA=1;                     //开总中断   
  200. }
  201. //------------------中断函数----------------------
  202. void timer2(void) interrupt 5 //定时器2中断(62.5ms)
  203. {
  204.         time++;
  205.         TF2=0;                    //定时器2的中断标志位TF2不能够由硬件清零,所以要在中断服务程序中将其清零
  206.         if (time==16)             //定时1s时间到  
  207.         {
  208.            time=0;                //计时清0
  209.            EA=0;                  //关中断                 
  210.            fre=(long)count*256+TL0;     //count*256强制转换成long型
  211.            per=(long)360-(360*(count1*256+TL1)/(16*62500)); //计算相位差
  212.            TL0=0;                 //清零计数器0计数            
  213.            TL1=0;
  214.            count=0;               //清零计数器0计数          
  215.            count1=0;
  216.            EA=1;                  //开中断            
  217.         }
  218. }
  219. //----------------------------------------------------------------
  220. void timer0(void) interrupt 1 //计数器0中断         
  221. {
  222.         count++;
  223. }               
  224. //----------------------------------------------------------------
  225. void timer1(void) interrupt 3 //定时器1中断
  226. {
  227.         count1++;
  228. }
复制代码

所有资料51hei提供下载:
低频数字式相位测量仪.zip (243.98 KB, 下载次数: 152)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:328014 发表于 2019-5-30 18:37 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:324446 发表于 2019-9-5 10:22 | 只看该作者
非常好
回复

使用道具 举报

地板
ID:208271 发表于 2019-12-2 11:19 | 只看该作者
感谢楼主分享,仿真文件是Proteus 8.0版本吗,一直找不开,能再发一下仿真原文件吗?万分感谢!
回复

使用道具 举报

5#
ID:727525 发表于 2020-4-12 14:30 | 只看该作者
好资料,谢谢楼主,帮到很多
回复

使用道具 举报

6#
ID:737014 发表于 2020-4-24 14:52 | 只看该作者
感谢楼主,很有帮助
回复

使用道具 举报

7#
ID:718181 发表于 2020-4-25 22:29 | 只看该作者
这个的测量原理是什么呢
回复

使用道具 举报

8#
ID:440960 发表于 2020-5-4 10:06 | 只看该作者
wifingtta 发表于 2019-12-2 11:19
感谢楼主分享,仿真文件是Proteus 8.0版本吗,一直找不开,能再发一下仿真原文件吗?万分感谢!

你好 请问你有仿真源文件了吗 我也打不开
回复

使用道具 举报

9#
ID:589800 发表于 2020-6-7 21:16 | 只看该作者
51hei团团 发表于 2019-5-30 18:37
好资料,51黑有你更精彩!!!

请问这哥仿真可以运行嘛
回复

使用道具 举报

10#
ID:918938 发表于 2021-5-12 12:42 来自手机 | 只看该作者
楼主能设计实现其他功能的吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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