⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd1602.lst

📁 这是单片机实验板比较齐全的程序
💻 LST
字号:
C51 COMPILER V7.50   LCD1602                                                               05/27/2007 09:10:54 PAGE 1   


C51 COMPILER V7.50, COMPILATION OF MODULE LCD1602
OBJECT MODULE PLACED IN lcd1602.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE lcd1602.c BROWSE DEBUG OBJECTEXTEND

line level    source

   1          /*============================================================
   2          使用1602液晶显示和PS/2键盘的示例     孟猛  2006/2
   3          -------------------------------------------------
   4          Tel:010-51779043
   5          ==============================================================
   6          
   7            SMC1602A(16*2)模拟口线接线方式
   8            连接线图:     
   9            
  10                  ---------------------------------------------------
  11                  |LCM-----51   | LCM-----51   |  LCM------51      |
  12                  --------------------------------------------------|
  13                  |DB0-----P0.0 | DB4-----P0.4 |  RW-------P2.2    |
  14                  |DB1-----P0.1 | DB5-----P0.5 |  RS-------P2.1    |
  15                  |DB2-----P0.2 | DB6-----P0.6 |  E--------P2.0    |
  16                  |DB3-----P0.3 | DB7-----P0.7 |  VLCD接1K电阻到GND|
  17                  ---------------------------------------------------
  18                  
  19                    Keyboard接线
  20                    
  21                          
  22                            PS/2--------51
  23                            1 DATA------P2.7
  24                            3 GND
  25                            4 VCC
  26                            5 CLK-------P3.2 接在51的外部中断,触发方式为低电平
  27                            
  28                                  
  29                                    本程序源码只供学习参考,不得应用于商业用途,如有需要请联系作者。
  30                                    
  31                                          [注:AT89x51使用12M或11.0592M晶振,实测使用11.0592M]
  32                                          [Keil uV2 7.01编译运行通过 程序中没有做键盘数据的奇偶校验]
  33                                          
  34          =============================================================*/
  35          #include <reg51.h>
  36          #include "scancodes.h"
  37          #include "sybxt1.h"
  38          sbit LCM_RW=  P2^2; //定义LCD引脚
  39          sbit LCM_RS=  P2^1;
  40          sbit LCM_E =  P2^0;
  41          #define LCM_Data  P0
  42          sbit Key_Data= P2^7; //定义Keyboard引脚
  43          sbit Key_CLK = P3^2;
  44          #define Busy    0x80 //用于检测LCM状态字中的Busy标识
  45          void LCMInit(void);
  46          void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
  47          void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
  48          void Delay5Ms(void);
  49          void Delay400Ms(void);
  50          void Decode(unsigned char ScanCode);
  51          void WriteDataLCM(unsigned char WDLCM);
  52          void WriteCommandLCM(unsigned char WCLCM,BuysC);
  53          unsigned char ReadDataLCM(void);
  54          unsigned char ReadStatusLCM(void);
  55          unsigned char code cdle_net[] = {"--nice to you--"};
C51 COMPILER V7.50   LCD1602                                                               05/27/2007 09:10:54 PAGE 2   

  56          unsigned char code email[] = {"mengmbj@163.com"};
  57          unsigned char code Cls[] = {"                "};
  58          static unsigned char IntNum = 0; //中断次数计数
  59          static unsigned char KeyV; //键值
  60          static unsigned char DisNum = 0; //显示用指针
  61          static unsigned char Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识
  62          static unsigned char BF = 0; //标识是否有字符被收到
  63          void DisplayString ()
  64          {
  65   1              while(uiOffset!=uiRxCount)
  66   1              {
  67   2                      if (DisNum > 15)
  68   2                      {
  69   3                              DisplayListChar(0, 1, Cls);//清LCD第二行
  70   3                              DisNum = 0; 
  71   3                      }
  72   2                      DisplayOneChar(DisNum, 1,ucRxBuf[uiOffset]);
  73   2                      DisNum++;
  74   2                      
  75   2                      uiOffset++;
  76   2                      uiOffset%=RXBUFSIZE;
  77   2              }
  78   1      }
  79          void sysinit()
  80          {
  81   1              unsigned char TempCyc;
  82   1              Delay400Ms(); //启动等待,等LCM讲入工作状态
  83   1              LCMInit(); //LCM初始化
  84   1              Delay5Ms(); //延时片刻(可不要)
  85   1              DisplayListChar(0, 0, cdle_net);
  86   1              DisplayListChar(0, 1, email);
  87   1              ReadDataLCM();//测试用句无意义
  88   1              for (TempCyc=0; TempCyc<10; TempCyc++)
  89   1                      Delay400Ms(); //延时
  90   1              DisplayListChar(0, 1, Cls);     
  91   1              IT0 = 0; //设外部中断0为低电平触发
  92   1              EA = 1;
  93   1              EX0 = 1; //开中断
  94   1      }
  95          void GetPs2Key(void)
  96          { 
  97   1              if (BF)
  98   1                      Decode(KeyV);
  99   1              else
 100   1                      EA = 1; //开中断
 101   1      }
 102          
 103          //写数据
 104          void WriteDataLCM(unsigned char WDLCM) 
 105          {
 106   1              ReadStatusLCM(); //检测忙
 107   1              LCM_Data = WDLCM;
 108   1              LCM_RS = 1;
 109   1              LCM_RW = 0;
 110   1              LCM_E = 0; //若晶振速度太高可以在这后加小的延时
 111   1              LCM_E = 0; //延时
 112   1              LCM_E = 1;
 113   1      }
 114          //写指令
 115          void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
 116          {
 117   1              if (BuysC) ReadStatusLCM(); //根据需要检测忙
C51 COMPILER V7.50   LCD1602                                                               05/27/2007 09:10:54 PAGE 3   

 118   1              LCM_Data = WCLCM;
 119   1              LCM_RS = 0;
 120   1              LCM_RW = 0;     
 121   1              LCM_E = 0;
 122   1              LCM_E = 0;
 123   1              LCM_E = 1;      
 124   1      }
 125          
 126          //读数据
 127          unsigned char ReadDataLCM(void)
 128          {
 129   1              LCM_RS = 1; 
 130   1              LCM_RW = 1;
 131   1              LCM_E = 0;
 132   1              LCM_E = 0;
 133   1              LCM_E = 1;
 134   1              return(LCM_Data);
 135   1      }
 136          //读状态
 137          unsigned char ReadStatusLCM(void)
 138          {
 139   1              LCM_Data = 0xFF; 
 140   1              LCM_RS = 0;
 141   1              LCM_RW = 1;
 142   1              LCM_E = 0;
 143   1              LCM_E = 0;
 144   1              LCM_E = 1;
 145   1              while (LCM_Data & Busy); //检测忙信号
 146   1              return(LCM_Data);
 147   1      }
 148          void LCMInit(void) //LCM初始化
 149          {
 150   1              LCM_Data = 0;
 151   1              WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
 152   1              Delay5Ms(); 
 153   1              WriteCommandLCM(0x38,0);
 154   1              Delay5Ms(); 
 155   1              WriteCommandLCM(0x38,0);
 156   1              Delay5Ms(); 
 157   1              WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
 158   1              WriteCommandLCM(0x08,1); //关闭显示
 159   1              WriteCommandLCM(0x01,1); //显示清屏
 160   1              WriteCommandLCM(0x06,1); // 显示光标移动设置
 161   1              WriteCommandLCM(0x0F,1); // 显示开及光标设置
 162   1      }
 163          //按指定位置显示一个字符
 164          void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
 165          {
 166   1              Y &= 0x1;
 167   1              X &= 0xF; //限制X不能大于15,Y不能大于1
 168   1              if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
 169   1              X |= 0x80; //算出指令码
 170   1              WriteCommandLCM(X, 1); //发命令字
 171   1              WriteDataLCM(DData); //发数据
 172   1      }
 173          //按指定位置显示一串字符
 174          void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
 175          {
 176   1              unsigned char ListLength;
 177   1              ListLength = 0;
 178   1              Y &= 0x1;
 179   1              X &= 0xF; //限制X不能大于15,Y不能大于1
C51 COMPILER V7.50   LCD1602                                                               05/27/2007 09:10:54 PAGE 4   

 180   1              while (DData[ListLength]>0x19) //若到达字串尾则退出
 181   1              {
 182   2                      if (X <= 0xF) //X坐标应小于0xF
 183   2                      {
 184   3                              DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
 185   3                              
 186   3                              ListLength++;
 187   3                              X++;
 188   3                      }
 189   2              }
 190   1      }
 191          //5ms延时
 192          void Delay5Ms(void)
 193          {
 194   1              unsigned int TempCyc = 5552;
 195   1              while(TempCyc--);
 196   1      }
 197          //400ms延时
 198          void Delay400Ms(void)
 199          {
 200   1              unsigned char TempCycA = 5;
 201   1              unsigned int TempCycB;
 202   1              while(TempCycA--)
 203   1              {
 204   2                      TempCycB=7269;
 205   2                      while(TempCycB--);
 206   2              };
 207   1      }
 208          
 209          void Keyboard_out(void) interrupt 0
 210          {
 211   1              if ((IntNum > 0) && (IntNum < 9))
 212   1              {                       
 213   2                      KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
 214   2                      if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位
 215   2              }
 216   1              IntNum++;
 217   1              while (!Key_CLK); //等待PS/2CLK拉高
 218   1              
 219   1              if (IntNum > 10)
 220   1              {
 221   2                      IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
 222   2                      BF = 1; //标识有字符输入完了
 223   2                      EA = 0; //关中断等显示完后再开中断 (注:如这里不用BF和关中断直接调Decode()则所Decode中所调用的所有函数要
             -声明为再入函数)
 224   2              }
 225   1      }
 226          
 227          void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码
             -+shift的断码+G的断码
 228          {
 229   1              unsigned char TempCyc;  
 230   1              
 231   1              if (!Key_UP)                //当键盘松开时
 232   1              {
 233   2                      switch (ScanCode)
 234   2                      {
 235   3                      case 0xF0 :     // 当收到0xF0,Key_UP置1表示断码开始
 236   3                              Key_UP = 1;
 237   3                              break;
 238   3                              
 239   3                      case 0x12 :     // 左 SHIFT
C51 COMPILER V7.50   LCD1602                                                               05/27/2007 09:10:54 PAGE 5   

 240   3                              Shift = 1;
 241   3                              break;
 242   3                              
 243   3                      case 0x59 :     // 右 SHIFT
 244   3                              Shift = 1;
 245   3                              break;
 246   3                              
 247   3                      default:                                                
 248   3                              if (DisNum > 15)
 249   3                              {
 250   4                                      DisplayListChar(0, 1, Cls);//清LCD第二行
 251   4                                      DisNum = 0; 
 252   4                              }
 253   3                              if(!Shift)      //如果SHIFT没按下
 254   3                              {
 255   4                                      for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
 256   4                                      if (UnShifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, UnShifted[TempCyc][1]);
 257   4                                      DisNum++;
 258   4                              } 
 259   3                              else  //按下SHIFT
 260   3                              {
 261   4                                      for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
 262   4                                      if (Shifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, Shifted[TempCyc][1]);
 263   4                                      DisNum++;
 264   4                              }
 265   3                              break;
 266   3                      }
 267   2              }
 268   1              else
 269   1              {       
 270   2                      Key_UP = 0;
 271   2                      switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
 272   2                      {
 273   3                      case 0x12 :     // 左 SHIFT
 274   3                              Shift = 0;
 275   3                              break;
 276   3                      case 0x59 :     // 右 SHIFT
 277   3                              Shift = 0;
 278   3                              break;
 279   3                      }
 280   2              }
 281   1              BF = 0; //标识字符处理完了
 282   1      } 


MODULE INFORMATION:   STATIC OVERLAYABLE
   CODE SIZE        =    663    ----
   CONSTANT SIZE    =    285    ----
   XDATA SIZE       =   ----    ----
   PDATA SIZE       =   ----    ----
   DATA SIZE        =      6      11
   IDATA SIZE       =   ----    ----
   BIT SIZE         =   ----    ----
END OF MODULE INFORMATION.


C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -