找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机数字电压表程序 新手遇问题求大佬指点

[复制链接]
跳转到指定楼层
楼主
整个程序是,使用ADDC0808、LCD1602实现电压的测量和显示,串口是后期加的功能,按下K3向PC机发送电压值。K1,K2开关控制电压表量程。
现在问题是当一个开关放下,LCD的D0到D7会出现间断黄信号,并且LCD1602无法正常显示。我自己找不出程序里哪里错了。希望有大佬能耐心帮忙找出问题。

LCD出现问题,信号口黄色



整体仿真图

下面是单片机程序:
  1. #include <reg51.h>
  2. #include <intrins.h>
  3. #include <stdio.h>
  4. #define uchar unsigned char
  5. #define  uint unsigned int
  6. #define  FREQ 11059200

  7. sbit OE=P1^4;                                                //AD数据输出控制端口
  8. sbit EOC=P3^3;                                        //数据转换结束由0变1
  9. sbit START=P3^4;                          //AD转换启动  ALE接口
  10. sbit CLK=P1^3;
  11. sbit  rw=P3^6;                                        //1602读写选择
  12. sbit  rs=P3^5;                                        //1602寄存器选择端
  13. sbit  en=P3^7;                                        //1602读写使能端
  14. sbit a=P1^0;                                                //a,b,c为转换器通道选择地址
  15. sbit b=P1^1;
  16. sbit c=P1^2;
  17. sbit d=P1^5;                                                //报警信号端
  18. sbit K1=P1^6;                                                //量程选择开关
  19. sbit K2=P1^7;                                                
  20. uchar dis[4]={0,0,0,0};        //缓存数据处理结果



  21. /****************************************************
  22. 延时程序
  23. *****************************************************/
  24. void delay(uchar i)                        
  25. {
  26.         uchar n;
  27.         while(i--)
  28.         {
  29.                 for(n=0;n<250;n++);
  30.         }
  31. }
  32. /****************************************************
  33. //串口初始化(Timer1定时器)
  34. *****************************************************/
  35. void Init_USART_uT1()
  36. {
  37.         SCON = 0x50;    //串口方式1
  38.         TMOD = 0x20;    //T1工作方式2(8位自动重装)
  39.         PCON = 0x80;    //波特率不倍增
  40.         TH1 = TL1 = - FREQ/384/9600;//波特率配置(TH1 = TL1 = 0xFD)
  41.         TR1 = 1;        //启动定时器T1
  42. }
  43. /****************************************************
  44. //1602状态检测是否忙碌
  45. *****************************************************/
  46. bit lcd_busy_check()                                 
  47. {
  48.         bit  result;
  49.         rs=0;
  50.         rw=1;
  51.         en=1;
  52.         delay(10);

  53.         result=(bit)(P0&0x80);
  54.         en=0;
  55.         return  result;
  56. }
  57. /****************************************************
  58. //写LCD命令
  59. *****************************************************/
  60. void w_comd(uchar command)                          
  61. {
  62.         while(lcd_busy_check());
  63.         rw=0;
  64.         rs=0;
  65.         en=0;
  66.         P0=command;
  67.         delay(10);
  68.         en=1;
  69.         delay(10);
  70.         en=0;
  71. }
  72. /****************************************************
  73. //向1602发送数据
  74. *****************************************************/
  75. void  vWriteData(uchar dat)                          
  76. {
  77.         while(lcd_busy_check());
  78.         rs=1;
  79.         rw=0;
  80.         en=0;
  81.         P0=dat;
  82.         delay(1);
  83.         en=1;
  84.         delay(1);
  85.         en=0;
  86. }
  87. /****************************************************
  88. //LCD1602初始化
  89. *****************************************************/
  90. void lcd_init()                                                         
  91. {
  92.         w_comd(0x38);
  93.         delay(5);
  94.         w_comd(0x0c);          //开显示屏,关光标
  95.         delay(5);
  96.         w_comd(0x06);   //字符进入模式:屏幕不动,字符后移
  97.         delay(5);
  98.         w_comd(0x01);   //清屏
  99. }
  100. /****************************************************
  101. //LCD1602字库表
  102. *****************************************************/
  103. void show_lcd_char(uchar ucChar)                                
  104. {
  105.         switch(ucChar)
  106.         {
  107.         case ' ': vWriteData(0x20);break;
  108.         case '!': vWriteData(0x21);break;
  109.         case '"': vWriteData(0x22);break;
  110.         case '#': vWriteData(0x23);break;
  111.         case '


  112. : vWriteData(0x24);break;
  113.         case '%': vWriteData(0x25);break;
  114.         case '&': vWriteData(0x26);break;
  115.         case '>': vWriteData(0x27);break;
  116.         case '(': vWriteData(0x28);break;
  117.         case ')': vWriteData(0x29);break;
  118.         case '.': vWriteData(0x2E);break;
  119.                
  120.         case '0': vWriteData(0x30);break;
  121.         case '1': vWriteData(0x31);break;
  122.         case '2': vWriteData(0x32);break;
  123.         case '3': vWriteData(0x33);break;
  124.         case '4': vWriteData(0x34);break;
  125.         case '5': vWriteData(0x35);break;
  126.         case '6': vWriteData(0x36);break;
  127.         case '7': vWriteData(0x37);break;
  128.         case '8': vWriteData(0x38);break;
  129.         case '9': vWriteData(0x39);break;
  130.                
  131.                
  132.         case 'V': vWriteData(0x56);break;
  133.                
  134.         case 'a': vWriteData(0x61);break;
  135.         case 'd': vWriteData(0x64);break;
  136.         case 'e': vWriteData(0x65);break;
  137.         case 'f': vWriteData(0x66);break;
  138.         case 'g': vWriteData(0x67);break;
  139.         case 'h': vWriteData(0x68);break;
  140.         case 'i': vWriteData(0x69);break;
  141.         case 'j': vWriteData(0x6A);break;
  142.         case 'k': vWriteData(0x6B);break;
  143.         case 'l': vWriteData(0x6C);break;
  144.         case 'm': vWriteData(0x6D);break;
  145.         case 'n': vWriteData(0x6E);break;
  146.         case 'o': vWriteData(0x6F);break;
  147.         case 'p': vWriteData(0x70);break;
  148.         case 'q': vWriteData(0x71);break;
  149.         case 'r': vWriteData(0x72);break;
  150.         case 's': vWriteData(0x73);break;
  151.         case 't': vWriteData(0x74);break;
  152.         case 'u': vWriteData(0x75);break;
  153.         case 'v': vWriteData(0x76);break;
  154.                
  155.                
  156.         default: break;
  157.         }
  158. }
  159. /****************************************************
  160. //显示字符
  161. *****************************************************/
  162. void show_lcd(uchar xschar[])                        
  163. {
  164.         uchar i;
  165.         for(i=0;;i++)
  166.         {
  167.                 show_lcd_char(xschar[i]);
  168.                 if(xschar[i+1]=='\0')
  169.                         break;        
  170.     }               
  171. }
  172. /****************************************************
  173. //显示数据
  174. *****************************************************/
  175. void v_display0(uint getdata)                          
  176. {
  177.         uint m,i;
  178.         m=getdata*1.0/255*500;
  179.         dis[0]=m/100;                                //把计算的数据每个位存入数组
  180.         dis[1]=m/10%10;
  181.         dis[2]=m%10;
  182.         for(i=0;i<3;i++)                //数据逐一输出
  183.         {
  184.                 show_lcd_char(dis[i]+48);
  185.                 if(i==0)
  186.                 {
  187.                         show_lcd_char('.');
  188.                 }
  189.         }
  190. }
  191. /****************************************************
  192. //显示数据
  193. *****************************************************/
  194. void v_display1(uint getdata)                          
  195. {
  196.         uint m,i;
  197.         m=getdata*1.0/255*500*3;
  198.         if(m>=1000)
  199.         {
  200.                 dis[0]=m/1000;                        //把计算的数据每个位存入数组
  201.                 dis[1]=m/100%10;
  202.                 dis[2]=m/10%10;
  203.                 dis[3]=m%10;
  204.                 for(i=0;i<4;i++)                //数据逐一输出
  205.                 {
  206.                         show_lcd_char(dis[i]+48);
  207.                         if(i==1)
  208.                                 show_lcd_char('.');
  209.                 }
  210.         }
  211.         else
  212.         {
  213.                 dis[0]=m/100;                                //把计算的数据每个位存入数组
  214.                 dis[1]=m/10%10;
  215.                 dis[2]=m%10;
  216.                 for(i=0;i<3;i++)                //数据逐一输出
  217.                 {
  218.                         show_lcd_char(dis[i]+48);
  219.                         
  220.                         if(i==0)
  221.                         {
  222.                                 show_lcd_char('.');
  223.                         }
  224.                 }
  225.         }
  226. }
  227. void main()
  228. {
  229.   Init_USART_uT1();  //串口初始化 
  230.         EX0 = 1; IT0 = 1;  //允许外部中断,下降沿触发
  231.         
  232.         TMOD=0x01;               //定时器0,模式1
  233.         TH0=0xfa;
  234.         TL0=0x00;
  235.         ES = 1;           //开串口中断
  236.         EA=1;                                            //开总中断
  237.         ET0=1;                                    //开定时中断         
  238.         ET1=1;
  239.         TR0=1;                                    //启动定时中断
  240.         d=0;
  241.         
  242.         lcd_init();       //初始化
  243.         
  244.         w_comd(0x84);     //显示起始地址
  245.         delay(10);
  246.         show_lcd("Voltage:");
  247.         
  248.         w_comd(0xc9);
  249.         delay(10);
  250.         show_lcd("(V)");
  251.         
  252.         
  253.         
  254.         while(1)
  255.         {
  256.                 w_comd(0xc4);
  257.                 d=0;
  258.                 if((K1==0)&&(K2!=0))  //测量0~5V电压
  259.                 {a=0;
  260.                 b=0;
  261.                 c=0;
  262.                 START=0;
  263.                 OE=0;         
  264.                 START=1;                                      //启动AD转换
  265.                
  266.                 START=0;
  267.                 while(EOC==0);                    //等待转换结束
  268.                 OE=1;
  269.                 v_display0(P2);
  270.                 OE=0;
  271.                 }
  272.                 if((K2==0)&&(K1!=0))  //测量5~10V电压
  273.                 {a=1;
  274.                 b=0;
  275.                 c=0;
  276.                 START=0;
  277.                 OE=0;         
  278.                 START=1;                                      //启动AD转换
  279.                
  280.                 START=0;
  281.                 while(EOC==0);                    //等待转换结束
  282.                 OE=1;
  283.                 v_display1(P2);
  284.                 OE=0;
  285.                
  286.                 }
  287.                 if((K1==0)&&(K2==0))        //若K1、K2同时摁下,LED点亮报警
  288.                         d=1;
  289.         }         
  290.         
  291. }
  292. /****************************************************
  293. //定时器0中断函数
  294. *****************************************************/
  295. void time0() interrupt 1                 
  296. {
  297.         CLK=~CLK;
  298.         TH0=0xfa;
  299.         TL0=0x00;
  300. }
  301. /****************************************************
  302. //外部中断0
  303. *****************************************************/
  304. void EX_INT0() interrupt 0
  305. {
  306.         uchar i = 0;
  307.         while(dis[i]!='\0')
  308.         {
  309.                 SBUF = dis[i++];  //发送1字节,索引递增
  310.                 while(TI == 0); //等待发送完成
  311.                 TI = 0;         //软件清零中断标志位TI
  312.         }
  313. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2022-2-28 15:33 | 只看该作者
如果你的程序中,不用DELAY()来延时,估计就可以了。
回复

使用道具 举报

板凳
ID:1006510 发表于 2022-3-25 17:39 | 只看该作者
yzwzfyz 发表于 2022-2-28 15:33
如果你的程序中,不用DELAY()来延时,估计就可以了。

谢谢回复。实物我自己搞好了,由于是小白所以制作过程有很多新手问题。
回复

使用道具 举报

地板
ID:1011897 发表于 2022-4-14 15:40 | 只看该作者
你好 我也是 这个 量程是0-200 我现在搞不明白了 看评论区 你好像明白的 可以教我一下吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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