微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > lcd的串口问题

lcd的串口问题

时间:10-02 整理:3721RD 点击:
问题:
在串口数据接收中,如果SUBF,接收1,在LCD1602上显示 :TURN ON ,如果是0 ,显示TRUN OFF, 其他的话显示ERROR.
但实际运行中,能显示接受到的数据,但是显示TURN ON ,和TURN OFF时,只会显示ERROR.求高手解答。
程序如下:
/*******************************
*从串口中得到数据。
如果得到01,显示TURN ON
如果得到00,显示TRUN OFF
如果是其他,显示ERROR
在lcd1602上显示出来、
*********************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned  int
#define nop _nop_()
#define NOP _nop_()
sbit RS = P2^6; //LCD1602  数据命令选择
sbit RW = P2^5;//LCD1602 读写选择
sbit EP = P2^7; //使能端
typedef bit BOOL;
uchar flag,  a, i; //flag为串口接收标志位。 a接受SBUF
uchar code table[] = {"I GET "};
uchar code ON[]={"TURN ON"};
uchar code OFF[] = {"TURN OFF"};
uchar code OTHER[] = {"ERROR"};
void delay(uchar ms)
{
    uchar i;
    while(ms--)
    {
        for(i=0; i<250; i++)
        {
            nop;
            nop;
            nop;
            nop;
        }
   
    }
}
/*测试LCD1602是否忙*/
BOOL lcd_bz(void)
{
    BOOL result;
    RS = 0;
    RW = 1;
    EP = 1;
    NOP;
    NOP;
    NOP;
    NOP;
    result = (BOOL)(P0 &0X80);
    EP = 0;
    return result;
   
}
/*lcd1602写命令*/
void lcd_wcmd(uchar cmd)
{
   
    while(lcd_bz());
    RS = 0;
    RW = 0;
    EP = 0;
   
    P0= cmd;
    nop;
    nop;
    nop;
    nop;
    EP = 1;
    nop;
    nop;
    nop;
    nop;
    EP = 0;   
}
/*LCD1602写数据*/
void lcd_wdat(uchar dat)
{
    while(lcd_bz());
    RS = 1;
    RW = 0;
    EP = 0;
    nop;
    nop;
    P0 = dat;
    nop;
    nop;
    nop;
    nop;
    EP = 1;
    nop;
    nop;
    nop;
    nop;
    EP = 0;
}
/*清屏*/
void lcd_clr(void)
{
    lcd_wcmd(0x01);
    delay(5);
}
/*LCD1602初始化*/
void lcd_init(void)
{
    delay(30);
    lcd_wcmd(0X38);
    delay(5);
    lcd_wcmd(0X0C);
    delay(5);
    lcd_wcmd(0X06);
    delay(5);
    lcd_wcmd(0X01);
    delay(5);
}
/*串口初始化*/
void serial_init(void)
{
    TMOD = 0X20;
    TH1 = 0XFD;
    TL1 = 0XFD;
    TR1 = 1;
    REN = 1;
    SM0 = 0;
    SM1 = 1;
    EA = 1;
    ES = 1;
}
/*主函数*/
void main(void)
{
    lcd_init();
    serial_init();
   
    while(1)
    {
       lcd_wcmd(0x01);//清屏指令
        i = 0;
        lcd_wcmd(0x80);
        lcd_wdat(SBUF);
  if(SBUF == 1)
   {
   
                i = 0;
                lcd_wcmd(0x80 + 0X40);
                while(ON[i] != '\0')
                {
                    lcd_wdat(ON[i]);
                    i++;
                }
   }
    else if(SBUF == 0)
   {
    i = 0;
                lcd_wcmd(0x80 + 0x40);
                while(OFF[i] != '\0')
                {
                    lcd_wdat(OFF[i]);
                    i++;
                }
   }
   else
   {
    i = 0;
    lcd_wcmd(0x80 + 0x40);
    while(OTHER[i] != '\0')
    {
     lcd_wdat(OTHER[i]);
     i++;
    }
   }
        if(flag)
        {
            ES = 0;
            for(i=0; i<6; i++)
            {
                SBUF = table[i];
                while(TI == 0);
                TI = 0;
            }
            SBUF = a;
            while(!TI);
            TI = 0;
   
            ES = 1;
            flag = 0;
        }
    }
}
void serial() interrupt 4
{
    RI = 0;
    a = SBUF;
    flag = 1;
}

在大多情况下SBUF不等于1,或者是0,所以只能显示ERROR 可以在每个显示on和off后面加一段很长的延时时间来观察

因为你不断刷新显示,因此接收到0和1是,液晶屏显示on和off很快被刷新覆盖了,看不出来。
我改了一下程序你参考一下。单片机接收到数据才改变现状的显示状态。不接收到数据一直保持显示。

  1. /*******************************
  2. *从串口中得到数据。
  3. 如果得到01,显示TURN ON
  4. 如果得到00,显示TRUN OFF
  5. 如果是其他,显示ERROR
  6. 在lcd1602上显示出来、
  7. *********************************/
  8. #include <reg52.h>
  9. #include <intrins.h>
  10. #define uchar unsigned char
  11. #define uint  unsigned  int
  12. #define nop _nop_()
  13. #define NOP _nop_()
  14. sbit RS = P2^0; //LCD1602  数据命令选择
  15. sbit RW = P2^1;//LCD1602 读写选择
  16. sbit EP = P2^2; //使能端
  17. typedef bit BOOL;
  18. uchar flag,  a, i; //flag为串口接收标志位。 a接受SBUF
  19. uchar code table[] = {"I GET "};
  20. uchar code ON[]={"TURN ON"};
  21. uchar code OFF[] = {"TURN OFF"};
  22. uchar code OTHER[] = {"ERROR"};

  23. void delay(uchar ms)
  24. {
  25.     uchar i;
  26.     while(ms--)
  27.     {
  28.         for(i=0; i<250; i++)
  29.         {
  30.             nop;
  31.             nop;
  32.             nop;
  33.             nop;
  34.         }
  35.    
  36.     }
  37. }

  38. /*测试LCD1602是否忙*/
  39. BOOL lcd_bz(void)
  40. {
  41.     BOOL result;
  42.     RS = 0;
  43.     RW = 1;
  44.     EP = 1;
  45.     NOP;
  46.     NOP;
  47.     NOP;
  48.     NOP;
  49.     result = (BOOL)(P0 &0X80);
  50.     EP = 0;
  51.     return result;
  52.    
  53. }

  54. /*lcd1602写命令*/
  55. void lcd_wcmd(uchar cmd)
  56. {
  57.    
  58.     while(lcd_bz());
  59.     RS = 0;
  60.     RW = 0;
  61.     EP = 0;
  62.    
  63.     P0= cmd;
  64.     nop;
  65.     nop;
  66.     nop;
  67.     nop;
  68.     EP = 1;
  69.     nop;
  70.     nop;
  71.     nop;
  72.     nop;
  73.     EP = 0;   
  74. }

  75. /*LCD1602写数据*/
  76. void lcd_wdat(uchar dat)
  77. {
  78.     while(lcd_bz());
  79.     RS = 1;
  80.     RW = 0;
  81.     EP = 0;
  82.     nop;
  83.     nop;
  84.     P0 = dat;
  85.     nop;
  86.     nop;
  87.     nop;
  88.     nop;
  89.     EP = 1;
  90.     nop;
  91.     nop;
  92.     nop;
  93.     nop;
  94.     EP = 0;
  95. }

  96. /*清屏*/
  97. void lcd_clr(void)
  98. {
  99.     lcd_wcmd(0x01);
  100.     delay(5);
  101. }

  102. /*LCD1602初始化*/
  103. void lcd_init(void)
  104. {
  105.     delay(30);
  106.     lcd_wcmd(0X38);
  107.     delay(5);
  108.     lcd_wcmd(0X0C);
  109.     delay(5);
  110.     lcd_wcmd(0X06);
  111.     delay(5);
  112.     lcd_wcmd(0X01);
  113.     delay(5);
  114. }

  115. /*串口初始化*/
  116. void serial_init(void)
  117. {
  118.     TMOD = 0X20;
  119.     TH1 = 0XFD;
  120.     TL1 = 0XFD;
  121.     TR1 = 1;
  122.     REN = 1;
  123.     SM0 = 0;
  124.     SM1 = 1;
  125.     EA = 1;
  126.     ES = 1;
  127. }

  128. /*主函数*/
  129. void main(void)
  130. {
  131.     lcd_init();
  132.     serial_init();
  133.    
  134.     while(1)
  135.     {        
  136.        if(flag)
  137.        {
  138.                         ES = 0;
  139.             for(i=0; i<6; i++)
  140.             {
  141.                 SBUF = table[i];
  142.                 while(TI == 0);
  143.                 TI = 0;
  144.             }
  145.             SBUF = a;
  146.             while(!TI);
  147.             TI = 0;
  148.    
  149.             ES = 1;

  150.                         lcd_wcmd(0x80);
  151.                 lcd_wdat(a);
  152.                           if(a == 1)
  153.                            {
  154.    
  155.                 i = 0;
  156.                 lcd_wcmd(0x80 + 0X40);
  157.                 while(ON[i] != '\0')
  158.                 {
  159.                     lcd_wdat(ON[i]);
  160.                     i++;
  161.                 }
  162.                            }
  163.                     else if(a == 0)
  164.                            {
  165.                             i = 0;
  166.                 lcd_wcmd(0x80 + 0x40);
  167.                 while(OFF[i] != '\0')
  168.                 {
  169.                     lcd_wdat(OFF[i]);
  170.                     i++;
  171.                 }
  172.                            }
  173.                            else
  174.                            {
  175.                             i = 0;
  176.                             lcd_wcmd(0x80 + 0x40);
  177.                             while(OTHER[i] != '\0')
  178.                             {
  179.                              lcd_wdat(OTHER[i]);
  180.                              i++;
  181.                             }
  182.                            }
  183.             flag = 0;
  184.         }
  185.     }
  186. }

  187. void serial() interrupt 4
  188. {
  189.         RI = 0;
  190.         a = SBUF;
  191.     flag = 1;
  192. }

复制代码

哇,楼上真好功夫

你没有判断是否接收到数据就使用SBUF的数据输出,当然会有0和1之外的结果了;
同样原因,你是使用死循环输出数据,结果就如 依然落叶飘零 所说一样;
调试的话可以让发送端只发送0和1,你就能看到效果了

多谢,受教了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top