久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6876|回復: 7
打印 上一主題 下一主題
收起左側

代碼調試高手進!LCD1602液晶屏無顯示

[復制鏈接]
跳轉到指定樓層
樓主
10黑幣
做的關于LCD1602仿手機顯示字符的實驗。
步驟:1、在keil里編譯無誤代碼生成hex文件  2、將hex文件導入proteus原理圖中
原理圖如下:

正常的情況是下圖這種,LCD屏有顯示且按鍵有輸入:


下面是我的代碼(為圖方便,把代碼一股腦寫在一塊了),編譯是沒問題的,但導出的hex導入proteus里,LCD液晶屏不顯示,檢查不出程序哪里出了問題,請各位大佬幫忙看一看:

  1. //-----------------------------------------------------------------
  2. //  名稱: 鍵盤矩陣掃描程序(4*3)
  3. //-----------------------------------------------------------------
  4. #include <reg51.h>
  5. #include <intrins.h>
  6. #define INT8U   unsigned char
  7. #define INT16U  unsigned int
  8. #define KEY_PORT P1        //鍵盤端口定義
  9. INT8U KeyNo = 0xFF;        //當前按鍵序號,有效范圍為0-15,0xFF表示無按鍵
  10. extern void delay_ms(INT16U);
  11. //-----------------------------------------------------------------
  12. // 判斷鍵盤矩陣是否有鍵按下
  13. //-----------------------------------------------------------------
  14. INT8U KeyMatrix_Down()
  15. {
  16.         //高4位輸出,低4位輸入,高4位先置零,放入4行
  17.         KEY_PORT = 0x0F; delay_ms(1); //高4位置零,放入4行
  18.         return KEY_PORT != 0x0F ? 1:0;
  19. }

  20. //-----------------------------------------------------------------
  21. // 4*3鍵盤矩陣掃描
  22. //-----------------------------------------------------------------
  23. void Keys_Scan()
  24. {
  25.         //按鍵后00001111將變成0000XXXX,X中1個位0,3個仍為1
  26.         //判斷按鍵發生于0~3列中的哪一列
  27.         switch (KEY_PORT)
  28.         {        case 0x0E: KeyNo = 0; break;
  29.                 case 0x0D: KeyNo = 1; break;
  30.                 case 0x0B: KeyNo = 2; break;
  31.         }
  32.         KEY_PORT=0xF0; delay_ms(1); //
  33.         //按鍵后11110000將變成XXXX0000,X中1個位0,3個仍為1
  34.         //對0~3行分別附加起始值0,4,8,12
  35.         switch (KEY_PORT)
  36.         {        //下面第一行可省略
  37.         case 0xE0: KeyNo += 0; break;
  38.         case 0xD0: KeyNo += 3; break;
  39.         case 0xB0: KeyNo += 6; break;
  40.         case 0x70: KeyNo += 9;
  41.         }
  42. }
  43. //-----------------------------------------------------------------
  44. //  名稱: 1602LCD顯示仿手機鍵盤按鍵字符
  45. //-----------------------------------------------------------------
  46. //  說明: 按下仿手機矩陣鍵盤按鍵時,對應按鍵字符顯示在1602LCD上
  47. //
  48. //-----------------------------------------------------------------
  49. //#include "LCD1602-4bit.h"

  50. #include <reg51.h>
  51. #include <intrins.h>
  52. #include <string.h>
  53. #define INT8U  unsigned char
  54. #define INT16U unsigned int

  55. sbit SPK = P3^7;
  56. //12個鍵盤按鍵字符總表
  57. //注意串空間應設為6字節,因為最長串為5,設為5時會使部分長串無法附帶串結束標志'\0'
  58. INT8U code Keypad_Chars[12][6] =
  59. {        "1 ",        "2ABC",        "3DEF",
  60.         "4GHI",        "5JKL",        "6MNO",
  61.         "7PQRS","8TUV",        "9WXYZ",
  62.         "*",        "0+",        "#"
  63. };
  64. extern INT8U KeyNo;                //鍵值
  65. INT8U Inner_Idx=0;        //同一按鍵的內部字符索引
  66. INT8U tSpan=0;                //同鍵位連續按鍵的時間間隔
  67. INT8U Buffer_Index=0; //英文/數字輸入緩沖索引
  68. char  Input_Buffer[16]; //輸入緩沖空間
  69. INT8U ENG_TEL=1;                //輸入內容切換標識(ENG:英文輸入,TEL:電話輸入)
  70. extern void delay_ms(INT16U ms);
  71. extern INT8U KeyMatrix_Down();
  72. extern void Keys_Scan();

  73. extern          void Initialize_LCD();                                        //LCD初始化
  74. extern void LCD_ShowString(INT8U r, INT8U c,char *str);//在LCD上顯示字符串*/


  75. #define LCD_PORT P2                //液晶端口(P2高4位)
  76. //LCD引腳定義
  77. sbit RS = P2^0;                        //LCD寄存器選擇
  78. sbit RW = P2^1;                        //LCD讀寫控制
  79. sbit EN = P2^2;                        //LCD使能控制
  80. /*//LCD相關函數
  81. void delay_ms(INT16U x);                                //延時函數
  82. void LCD_Busy_Wait();                                        //忙等待
  83. void Write_LCD_Data(INT8U dat);                        //向LCD寫數據
  84. void Write_LCD_Command(INT8U cmd);                //寫LCD指令
  85. void Initialize_LCD();                                        //LCD初始化
  86. void LCD_ShowString(INT8U r, INT8U c,char *str);//在LCD上顯示字符串*/  
  87. //-----------------------------------------------------------------
  88. //        名稱: LCD1602液晶驅動程序
  89. //-----------------------------------------------------------------
  90. //#include "LCD1602-4bit.h"          
  91. #define delay5us() {_nop_();_nop_();_nop_();_nop_();_nop_();}
  92. //-----------------------------------------------------------------
  93. // 延時函數
  94. //-----------------------------------------------------------------
  95. void delay_ms(INT16U x)
  96. {
  97.         INT8U t; while(x--) for(t = 0; t < 120; t++);
  98. }

  99. //-----------------------------------------------------------------
  100. // 液晶忙等待
  101. //-----------------------------------------------------------------
  102. void LCD_Busy_Wait()
  103. {
  104.         INT8U  LCD_Status;                //液晶狀態字節變量
  105.         do
  106.         {
  107.         LCD_PORT=0xFF;
  108.         RS=0; RW=1;
  109.         EN=1; delay5us(); LCD_Status=P2; EN=0;
  110.         }while (LCD_Status & 0x80);                        //液晶忙繼續循環
  111. }
  112. //-----------------------------------------------------------------
  113. // 寫液晶命令
  114. //-----------------------------------------------------------------
  115. void Write_LCD_Command(INT8U cmd)
  116. {        LCD_Busy_Wait();
  117.         RS=0; RW=0;                                                           //選擇命令寄存器,準備寫
  118.         EN=0; _nop_(); _nop_(); LCD_PORT=cmd; //數據送到液晶屏端口
  119.         delay5us(); EN=1; delay5us(); EN=0;           //寫入后禁止液晶屏
  120. }

  121. //-----------------------------------------------------------------
  122. // 向液晶寫數據
  123. //-----------------------------------------------------------------
  124. void Write_LCD_Data(INT8U dat)
  125. {        LCD_Busy_Wait();
  126.         RS=1; RW=0;
  127.         EN=0; LCD_PORT=dat; delay5us();
  128.         EN=1; delay5us(); EN=0;
  129. }
  130. //-----------------------------------------------------------------
  131. // 液晶初始化
  132. //-----------------------------------------------------------------
  133. void Initialize_LCD()
  134. {        Write_LCD_Command(0x38); delay_ms(1);        //置功能,8位,雙行,5*7
  135.         Write_LCD_Command(0x06); delay_ms(1);        //字符進入模式:屏幕不動,字符后移
  136.         Write_LCD_Command(0x0C); delay_ms(1);        //顯示開,關光標
  137.         Write_LCD_Command(0x01); delay_ms(1);        //清屏
  138. }

  139. //-----------------------------------------------------------------
  140. // 在指定位置顯示字符串
  141. //-----------------------------------------------------------------
  142. void LCD_ShowString(INT8U r, INT8U c,char *str)
  143. {
  144.         INT8U i=0;
  145.     INT8U code DDRAM[] = {0x80,0xC0};         //液晶屏上下兩行的DDRAM首地址
  146.         Write_LCD_Command(DDRAM[r] |c);         //設置顯示起始位置
  147.         while (str[i] && i < 16) Write_LCD_Data(str[i++]);//輸出顯示字符
  148. }
  149. //-----------------------------------------------------------------
  150. // 蜂鳴器
  151. //-----------------------------------------------------------------
  152. void Beep()
  153. {
  154.         INT8U i; for(i=0;i<60;i++){SPK=!SPK; delay_ms(1);}
  155.         SPK=1;delay_ms(100);
  156. }

  157. //-----------------------------------------------------------------
  158. // 定時器0跟蹤同位按鍵的時間間隔
  159. //-----------------------------------------------------------------
  160. void T0_INT() interrupt 1
  161. {
  162.         //重新設置50ms定時初值
  163.         TH0=-50000>>8; TL0=-50000&0xFF;
  164.         //tSpan最大值限制在41及以上即可
  165.         //不加限制時會使某次較長的延時累加超過255后,
  166.         //累加又從0開始,而程序判斷時它可能剛好還在40以內,
  167.         //從而導致較長的延時卻被誤斷為較短的延時
  168.         if(tSpan<50) tSpan++;else TR0=0;
  169. }

  170. //-----------------------------------------------------------------
  171. // 功能鍵處理 *(9):切換輸入,#(11)鍵清除內容
  172. //-----------------------------------------------------------------
  173. void Function_Key_Process()
  174. {
  175.         if(KeyNo==9)                                //輸入內容標識切換
  176.         {        ENG_TEL=!ENG_TEL;
  177.                 Inner_Idx=ENG_TEL?1:0;  //如果是輸入英文,內部索引為1,否則設為0               
  178.         }
  179.         Buffer_Index=0;                                //輸入緩沖索引歸0
  180.         Input_Buffer[0]='\0';                //將輸入緩沖設為空串
  181.         if(ENG_TEL)                LCD_ShowString(1,0,"ENG>        ");          //顯示輸入英文
  182.         else            LCD_ShowString(1,0,"TEL>        ");          //顯示輸入電話
  183.         while(KeyMatrix_Down());                                                  //等待釋放按鍵
  184. }

  185. //-----------------------------------------------------------------
  186. // 主程序
  187. //-----------------------------------------------------------------
  188. void main()
  189. {
  190.         INT8U Pre_KeyNo=-1;
  191.         IE=0x82;                                 //使能T0中斷
  192.         TMOD=0x01;                                 //T0工作于模式1(16位模式)
  193.         TH0=-50000>>8;                         //定時50ms
  194.         TL0=-50000&0xFF;
  195.         Initialize_LCD();        //液晶初始化
  196.         //顯示固定信息部分(初始顯示ENG>表示輸入英文字符序列)
  197.         LCD_ShowString(0,0," Mobile KeyPad ");
  198.         LCD_ShowString(1,0,"ENG>                ");
  199.         while(1)
  200.         {        //有鍵按下則掃描,否則不進行任何處理
  201.                 if(KeyMatrix_Down()) Keys_Scan();else continue;
  202.                 if(KeyNo==0xFF) continue;
  203.                 //功能鍵處理(9[*]:切換英文/數字,11[#]:清除所有輸入)
  204.                 if(KeyNo==9 || KeyNo == 11)
  205.                 {        Function_Key_Process(); Beep(); continue; }
  206.                 //如果是輸入數字則直接顯示
  207.                 if(!ENG_TEL) goto SHOW_MOBILE_KEY;
  208.                 //如果輸入的不是英文字母則繼續(英文字符在0~8號鍵,包括空格)
  209.                 if(KeyNo<0 || KeyNo>8) continue;
  210.                 //否則輸入的是英文字符序列,以下代碼將根據是否為同位按鍵進行相應處理
  211.                 if(Pre_KeyNo != KeyNo)         //按下新按鍵
  212.                 {        Pre_KeyNo = KeyNo;         //保存當前按鍵
  213.                         Inner_Idx = 1;                 //輸入英文時內部索引起點為1
  214.                 }
  215.                 else //否則按下的時相同位置按鍵
  216.                 {        //同位按鍵時間間隔在50ms*30=1.5s內則認為是連續按鍵
  217.                         if(tSpan<31)
  218.                         {        //連續按鍵時在鍵內循環遞增字符索引
  219.                                 if (++Inner_Idx == strlen(Keypad_Chars[KeyNo]))
  220.                                 Inner_Idx=1;
  221.                                 //因為是連續短按,故將每次顯示后遞增的輸入緩沖索引后退一格,
  222.                                 //以便替換此前輸入的字符
  223.                                 --Buffer_Index;
  224.                         } else Inner_Idx = 1; //否則按鍵內英文字符索引回歸起點索引1
  225.                 }
  226.                 tSpan=0; TR0=1;                         //時間間隔歸零,計時開始
  227.                 SHOW_MOBILE_KEY:                 //顯示按鍵字符
  228.                 if(Buffer_Index >= 12) continue; //輸入緩沖限制在12個字符以內
  229.                 //更新輸入緩沖字符串并送LCD顯示
  230.                 Input_Buffer[Buffer_Index++] = Keypad_Chars[KeyNo][Inner_Idx];
  231.                 Input_Buffer[Buffer_Index] = '\0';
  232.                 LCD_ShowString(1,4,Input_Buffer);
  233.                 Beep();                                         //輸出提示音
  234.                 while(KeyMatrix_Down()); //等待釋放按鍵
  235.         }
  236. }
復制代碼
附上原理圖,可在proteus中打開
1602LCD顯示仿手機鍵盤按鍵字符.zip (16.37 KB, 下載次數: 15)


最佳答案

查看完整內容

給你改了,對比一下就知道哪里錯了。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:155507 發表于 2019-5-13 20:49 | 只看該作者
給你改了,對比一下就知道哪里錯了。



  1. //-----------------------------------------------------------------
  2. //  名稱: 鍵盤矩陣掃描程序(4*3)
  3. //-----------------------------------------------------------------
  4. #include <reg51.h>
  5. #include <intrins.h>
  6. #define INT8U   unsigned char
  7. #define INT16U  unsigned int
  8. #define KEY_PORT P1        //鍵盤端口定義
  9. INT8U KeyNo = 0xFF;        //當前按鍵序號,有效范圍為0-15,0xFF表示無按鍵
  10. extern void delay_ms(INT16U);
  11. //-----------------------------------------------------------------
  12. // 判斷鍵盤矩陣是否有鍵按下
  13. //-----------------------------------------------------------------
  14. INT8U KeyMatrix_Down()
  15. {
  16.         //高4位輸出,低4位輸入,高4位先置零,放入4行
  17.         KEY_PORT = 0x0F; delay_ms(1); //高4位置零,放入4行
  18.         return KEY_PORT != 0x0F ? 1:0;
  19. }

  20. //-----------------------------------------------------------------
  21. // 4*3鍵盤矩陣掃描
  22. //-----------------------------------------------------------------
  23. void Keys_Scan()
  24. {
  25.         //按鍵后00001111將變成0000XXXX,X中1個位0,3個仍為1
  26.         //判斷按鍵發生于0~3列中的哪一列
  27.         switch (KEY_PORT)
  28.         {
  29.         case 0x0E: KeyNo = 0; break;
  30.         case 0x0D: KeyNo = 1; break;
  31.         case 0x0B: KeyNo = 2; break;
  32.         }
  33.         KEY_PORT=0xF0; delay_ms(1); //
  34.         //按鍵后11110000將變成XXXX0000,X中1個位0,3個仍為1
  35.         //對0~3行分別附加起始值0,4,8,12
  36.         switch (KEY_PORT)
  37.         {        //下面第一行可省略
  38.         case 0xE0: KeyNo += 0; break;
  39.         case 0xD0: KeyNo += 3; break;
  40.         case 0xB0: KeyNo += 6; break;
  41.         case 0x70: KeyNo += 9;
  42.         }
  43. }
  44. //-----------------------------------------------------------------
  45. //  名稱: 1602LCD顯示仿手機鍵盤按鍵字符
  46. //-----------------------------------------------------------------
  47. //  說明: 按下仿手機矩陣鍵盤按鍵時,對應按鍵字符顯示在1602LCD上
  48. //
  49. //-----------------------------------------------------------------
  50. //#include "LCD1602-4bit.h"

  51. #include <reg51.h>
  52. #include <intrins.h>
  53. #include <string.h>
  54. #define INT8U  unsigned char
  55. #define INT16U unsigned int

  56. sbit SPK = P3^7;
  57. //12個鍵盤按鍵字符總表
  58. //注意串空間應設為6字節,因為最長串為5,設為5時會使部分長串無法附帶串結束標志'\0'
  59. INT8U code Keypad_Chars[12][6] =
  60. {
  61.         "1 ",        "2ABC",        "3DEF",
  62.         "4GHI",        "5JKL",        "6MNO",
  63.         "7PQRS","8TUV",        "9WXYZ",
  64.         "*",        "0+",        "#"
  65. };
  66. extern INT8U KeyNo;       //鍵值
  67. INT8U Inner_Idx=0;        //同一按鍵的內部字符索引
  68. INT8U tSpan=0;            //同鍵位連續按鍵的時間間隔
  69. INT8U Buffer_Index=0;     //英文/數字輸入緩沖索引
  70. char  Input_Buffer[16];   //輸入緩沖空間
  71. INT8U ENG_TEL=1;          //輸入內容切換標識(ENG:英文輸入,TEL:電話輸入)
  72. extern void delay_ms(INT16U ms);
  73. extern INT8U KeyMatrix_Down();
  74. extern void Keys_Scan();

  75. extern void Initialize_LCD();                                        //LCD初始化
  76. extern void LCD_ShowString(INT8U r, INT8U c,char *str);  //在LCD上顯示字符串*/


  77. #define LCD_PORT P2                //液晶端口(P2高4位)
  78. //LCD引腳定義
  79. sbit RS = P3^2;                        //LCD寄存器選擇
  80. sbit RW = P3^3;                        //LCD讀寫控制
  81. sbit EN = P3^4;                        //LCD使能控制
  82. /*//LCD相關函數
  83. void delay_ms(INT16U x);                          //延時函數
  84. void LCD_Busy_Wait();                             //忙等待
  85. void Write_LCD_Data(INT8U dat);                   //向LCD寫數據
  86. void Write_LCD_Command(INT8U cmd);                //寫LCD指令
  87. void Initialize_LCD();                            //LCD初始化
  88. void LCD_ShowString(INT8U r, INT8U c,char *str);  //在LCD上顯示字符串*/  
  89. //-----------------------------------------------------------------
  90. //        名稱: LCD1602液晶驅動程序
  91. //-----------------------------------------------------------------
  92. //#include "LCD1602-4bit.h"         
  93. #define delay5us() {_nop_();_nop_();_nop_();_nop_();_nop_();}
  94. //-----------------------------------------------------------------
  95. // 延時函數
  96. //-----------------------------------------------------------------
  97. void delay_ms(INT16U x)
  98. {
  99.         INT8U t;  while(x--) for(t = 0; t < 120; t++);
  100. }

  101. //-----------------------------------------------------------------
  102. // 液晶忙等待
  103. //-----------------------------------------------------------------
  104. /*
  105. void LCD_Busy_Wait()
  106. {
  107.         INT8U  LCD_Status;                //液晶狀態字節變量
  108.         do
  109.         {
  110.                 LCD_PORT=0xFF;
  111.                 RS=0; RW=1;
  112.                 EN=1; delay5us(); LCD_Status=P2; EN=0;
  113.         }while (LCD_Status & 0x80);               //液晶忙繼續循環
  114. } */
  115. //-----------------------------------------------------------------
  116. // 寫液晶命令
  117. //-----------------------------------------------------------------
  118. void Write_LCD_Command(INT8U cmd)
  119. {
  120.         //LCD_Busy_Wait();
  121.         EN = 0;          //使能清零       
  122.         RS=0; RW=0;                                                           //選擇命令寄存器,準備寫
  123.         EN=0; _nop_(); _nop_();
  124.     //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
  125.         LCD_PORT=cmd;      //數據送到液晶屏端口
  126.         delay_ms(1);
  127.         EN=1;   //寫入時序
  128.         delay_ms(1); EN=0;        //寫入后禁止液晶屏
  129.         LCD_PORT= cmd << 4; //寫入低四位
  130.         EN=1;   //寫入時序
  131.         delay_ms(1); EN=0;
  132.        
  133. }

  134. //-----------------------------------------------------------------
  135. // 向液晶寫數據
  136. //-----------------------------------------------------------------
  137. void Write_LCD_Data(INT8U dat)
  138. {
  139.         //LCD_Busy_Wait();
  140.         EN = 0;          //使能清零
  141.         RS=1; RW=0;
  142.         EN=0;
  143.         LCD_PORT=dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
  144.         delay_ms(1);
  145.         EN=1;   //寫入時序
  146.         delay_ms(1); EN=0;
  147.         LCD_PORT= dat << 4; //寫入低四位
  148.         EN=1;   //寫入時序
  149.         delay_ms(1); EN=0;

  150. }
  151. //-----------------------------------------------------------------
  152. // 液晶初始化
  153. //-----------------------------------------------------------------
  154. void Initialize_LCD()
  155. {
  156.         //Write_LCD_Command(0x38); delay_ms(1);        //置功能,8位,雙行,5*7
  157.         Write_LCD_Command(0x32); delay_ms(1);        //將8位總線轉為4位總線
  158.         Write_LCD_Command(0x28); delay_ms(1);        // 在四位線下的初始化
  159.         Write_LCD_Command(0x06); delay_ms(1);        //字符進入模式:屏幕不動,字符后移
  160.         Write_LCD_Command(0x0C); delay_ms(1);        //顯示開,關光標
  161.         Write_LCD_Command(0x01); delay_ms(1);        //清屏
  162. }

  163. //-----------------------------------------------------------------
  164. // 在指定位置顯示字符串
  165. //-----------------------------------------------------------------
  166. void LCD_ShowString(INT8U r, INT8U c,char *str)
  167. {
  168.         INT8U i=0;
  169.         INT8U code DDRAM[] = {0x80,0xC0};         //液晶屏上下兩行的DDRAM首地址
  170.         Write_LCD_Command(DDRAM[r] |c);         //設置顯示起始位置
  171.         while (str[i] && i < 16) Write_LCD_Data(str[i++]);//輸出顯示字符
  172. }
  173. //-----------------------------------------------------------------
  174. // 蜂鳴器
  175. //-----------------------------------------------------------------
  176. void Beep()
  177. {
  178.         INT8U i; for(i=0;i<60;i++){SPK=!SPK; delay_ms(1);}
  179.         SPK=1;delay_ms(100);
  180. }

  181. //-----------------------------------------------------------------
  182. // 定時器0跟蹤同位按鍵的時間間隔
  183. //-----------------------------------------------------------------
  184. void T0_INT() interrupt 1
  185. {
  186.         //重新設置50ms定時初值
  187.         TH0=-50000>>8; TL0=-50000&0xFF;
  188.         //tSpan最大值限制在41及以上即可
  189.         //不加限制時會使某次較長的延時累加超過255后,
  190.         //累加又從0開始,而程序判斷時它可能剛好還在40以內,
  191.         //從而導致較長的延時卻被誤斷為較短的延時
  192.         if(tSpan<50) tSpan++;else TR0=0;
  193. }

  194. //-----------------------------------------------------------------
  195. // 功能鍵處理 *(9):切換輸入,#(11)鍵清除內容
  196. //-----------------------------------------------------------------
  197. void Function_Key_Process()
  198. {
  199.         if(KeyNo==9)                         //輸入內容標識切換
  200.         {        ENG_TEL=!ENG_TEL;
  201.                 Inner_Idx=ENG_TEL?1:0;  //如果是輸入英文,內部索引為1,否則設為0               
  202.         }
  203.         Buffer_Index=0;                      //輸入緩沖索引歸0
  204.         Input_Buffer[0]='\0';                //將輸入緩沖設為空串
  205.         if(ENG_TEL)     LCD_ShowString(1,0,"ENG>        ");          //顯示輸入英文
  206.         else            LCD_ShowString(1,0,"TEL>        ");          //顯示輸入電話
  207.         while(KeyMatrix_Down());                                     //等待釋放按鍵
  208. }

  209. //-----------------------------------------------------------------
  210. // 主程序
  211. //-----------------------------------------------------------------
  212. void main()
  213. {
  214.         INT8U Pre_KeyNo=-1;
  215.         IE=0x82;                               //使能T0中斷
  216.         TMOD=0x01;                             //T0工作于模式1(16位模式)
  217.         TH0=-50000>>8;                         //定時50ms
  218.         TL0=-50000&0xFF;
  219.         Initialize_LCD();        //液晶初始化
  220.         //顯示固定信息部分(初始顯示ENG>表示輸入英文字符序列)
  221.         LCD_ShowString(0,0," Mobile KeyPad ");
  222.         LCD_ShowString(1,0,"ENG>                ");
  223.         while(1)
  224.         {        //有鍵按下則掃描,否則不進行任何處理
  225.                 if(KeyMatrix_Down()) Keys_Scan();else continue;
  226.                 if(KeyNo==0xFF) continue;
  227.                 //功能鍵處理(9[*]:切換英文/數字,11[#]:清除所有輸入)
  228.                 if(KeyNo==9 || KeyNo == 11)
  229.                 {        Function_Key_Process(); Beep(); continue; }
  230.                 //如果是輸入數字則直接顯示
  231.                 if(!ENG_TEL) goto SHOW_MOBILE_KEY;
  232.                 //如果輸入的不是英文字母則繼續(英文字符在0~8號鍵,包括空格)
  233.                 if(KeyNo<0 || KeyNo>8) continue;
  234.                 //否則輸入的是英文字符序列,以下代碼將根據是否為同位按鍵進行相應處理
  235.                 if(Pre_KeyNo != KeyNo)         //按下新按鍵
  236.                 {        Pre_KeyNo = KeyNo;         //保存當前按鍵
  237.                         Inner_Idx = 1;                 //輸入英文時內部索引起點為1
  238.                 }
  239.                 else //否則按下的時相同位置按鍵
  240.                 {        //同位按鍵時間間隔在50ms*30=1.5s內則認為是連續按鍵
  241.                         if(tSpan<31)
  242.                         {        //連續按鍵時在鍵內循環遞增字符索引
  243.                                 if (++Inner_Idx == strlen(Keypad_Chars[KeyNo]))
  244.                                 Inner_Idx=1;
  245.                                 //因為是連續短按,故將每次顯示后遞增的輸入緩沖索引后退一格,
  246.                                 //以便替換此前輸入的字符
  247.                                 --Buffer_Index;
  248.                         } else Inner_Idx = 1; //否則按鍵內英文字符索引回歸起點索引1
  249.                 }
  250.                 tSpan=0; TR0=1;                         //時間間隔歸零,計時開始
  251.                 SHOW_MOBILE_KEY:                 //顯示按鍵字符
  252.                 if(Buffer_Index >= 12) continue; //輸入緩沖限制在12個字符以內
  253.                 //更新輸入緩沖字符串并送LCD顯示
  254.                 Input_Buffer[Buffer_Index++] = Keypad_Chars[KeyNo][Inner_Idx];
  255.                 Input_Buffer[Buffer_Index] = '\0';
  256.                 LCD_ShowString(1,4,Input_Buffer);
  257.                 Beep();                                         //輸出提示音
  258.                 while(KeyMatrix_Down()); //等待釋放按鍵
  259.         }
  260. }

復制代碼

評分

參與人數 1黑幣 +8 收起 理由
劃船須劃水 + 8 很給力!

查看全部評分

回復

使用道具 舉報

板凳
ID:149451 發表于 2019-5-14 07:24 | 只看該作者
大致看了下,你的lcd1602驅動貌似是并口的,但proteus圖示是4線式(穿行數據輸入)程序同時控制端也用的是P2口,有點亂

評分

參與人數 1黑幣 +2 收起 理由
劃船須劃水 + 2 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

地板
ID:536476 發表于 2019-5-14 09:07 | 只看該作者
w1179benp 發表于 2019-5-14 07:24
大致看了下,你的lcd1602驅動貌似是并口的,但proteus圖示是4線式(穿行數據輸入)程序同時控制端也用的是P ...

大佬,所以說有什么解決辦法么
回復

使用道具 舉報

5#
ID:514919 發表于 2019-5-14 14:52 | 只看該作者
#include "STC15.H" #include "lcd1602.h" #include "ds1302.h" //#include"clock.h" SYSTEMTIME timer; /*************************************** main() ***************************************/ void main() {         P0M1=0;P0M0=0;         P1M1=0;P1M0=0;         P2M1=0;P2M0=0;         P3M1=0;P3M0=0;         lcd_initial();         ds1302_init();         while(1)         {                                     Ds1302_Read_Time(&timer);                    LCD_Write_Char(5,1,timer.Hour/10 + '0');        //ê±                         LCD_Write_Char(6,1,timer.Hour%10 + '0');                          LCD_Write_Char(8,1,timer.Minute/10 + '0');        //·Ö                         LCD_Write_Char(9,1,timer.Minute%10 + '0');                          LCD_Write_Char(11,1,timer.Second/10 + '0');        //Ãë                         LCD_Write_Char(12,1,timer.Second%10 + '0');                                    LCD_Write_Char(7,0,timer.Year/10  + '0');        //Äê                         LCD_Write_Char(8,0,timer.Year%10 + '0');                          LCD_Write_Char(10,0,timer.Month/10 + '0');        //ÔÂ                         LCD_Write_Char(11,0,timer.Month%10 + '0');                          LCD_Write_Char(13,0,timer.Day /10 + '0');        //èÕ                         LCD_Write_Char(14,0,timer.Day %10 + '0');         } },有個類似的程序,可以看看
回復

使用道具 舉報

6#
ID:155507 發表于 2019-5-15 23:52 | 只看該作者
4線式LCD程序同時控制端也用的是P2口

  1. //-----------------------------------------------------------------
  2. //  名稱: 鍵盤矩陣掃描程序(4*3)
  3. //-----------------------------------------------------------------
  4. #include <reg51.h>
  5. #include <intrins.h>
  6. #define INT8U   unsigned char
  7. #define INT16U  unsigned int
  8. #define KEY_PORT P1        //鍵盤端口定義
  9. INT8U KeyNo = 0xFF;        //當前按鍵序號,有效范圍為0-15,0xFF表示無按鍵
  10. extern void delay_ms(INT16U);
  11. //-----------------------------------------------------------------
  12. // 判斷鍵盤矩陣是否有鍵按下
  13. //-----------------------------------------------------------------
  14. INT8U KeyMatrix_Down()
  15. {
  16.         //高4位輸出,低4位輸入,高4位先置零,放入4行
  17.         KEY_PORT = 0x0F; delay_ms(1); //高4位置零,放入4行
  18.         return KEY_PORT != 0x0F ? 1:0;
  19. }

  20. //-----------------------------------------------------------------
  21. // 4*3鍵盤矩陣掃描
  22. //-----------------------------------------------------------------
  23. void Keys_Scan()
  24. {
  25.         //按鍵后00001111將變成0000XXXX,X中1個位0,3個仍為1
  26.         //判斷按鍵發生于0~3列中的哪一列
  27.         switch (KEY_PORT)
  28.         {
  29.         case 0x0E: KeyNo = 0; break;
  30.         case 0x0D: KeyNo = 1; break;
  31.         case 0x0B: KeyNo = 2; break;
  32.         }
  33.         KEY_PORT=0xF0; delay_ms(1); //
  34.         //按鍵后11110000將變成XXXX0000,X中1個位0,3個仍為1
  35.         //對0~3行分別附加起始值0,4,8,12
  36.         switch (KEY_PORT)
  37.         {        //下面第一行可省略
  38.         case 0xE0: KeyNo += 0; break;
  39.         case 0xD0: KeyNo += 3; break;
  40.         case 0xB0: KeyNo += 6; break;
  41.         case 0x70: KeyNo += 9;
  42.         }
  43. }
  44. //-----------------------------------------------------------------
  45. //  名稱: 1602LCD顯示仿手機鍵盤按鍵字符
  46. //-----------------------------------------------------------------
  47. //  說明: 按下仿手機矩陣鍵盤按鍵時,對應按鍵字符顯示在1602LCD上
  48. //
  49. //-----------------------------------------------------------------
  50. //#include "LCD1602-4bit.h"

  51. #include <reg51.h>
  52. #include <intrins.h>
  53. #include <string.h>
  54. #define INT8U  unsigned char
  55. #define INT16U unsigned int

  56. sbit SPK = P3^7;
  57. //12個鍵盤按鍵字符總表
  58. //注意串空間應設為6字節,因為最長串為5,設為5時會使部分長串無法附帶串結束標志'\0'
  59. INT8U code Keypad_Chars[12][6] =
  60. {
  61.         "1 ",        "2ABC",        "3DEF",
  62.         "4GHI",        "5JKL",        "6MNO",
  63.         "7PQRS","8TUV",        "9WXYZ",
  64.         "*",        "0+",        "#"
  65. };
  66. extern INT8U KeyNo;       //鍵值
  67. INT8U Inner_Idx=0;        //同一按鍵的內部字符索引
  68. INT8U tSpan=0;            //同鍵位連續按鍵的時間間隔
  69. INT8U Buffer_Index=0;     //英文/數字輸入緩沖索引
  70. char  Input_Buffer[16];   //輸入緩沖空間
  71. INT8U ENG_TEL=1;          //輸入內容切換標識(ENG:英文輸入,TEL:電話輸入)
  72. extern void delay_ms(INT16U ms);
  73. extern INT8U KeyMatrix_Down();
  74. extern void Keys_Scan();

  75. extern void Initialize_LCD();                                        //LCD初始化
  76. extern void LCD_ShowString(INT8U r, INT8U c,char *str);  //在LCD上顯示字符串*/
  77. //是4線式(穿行數據輸入)程序
  78. //程序同時控制端也用的是P2口
  79. #define LCD_PORT P2                //液晶端口(P2高4位)
  80. //LCD引腳定義
  81. sbit RS = P2^0;                        //LCD寄存器選擇
  82. sbit RW = P2^1;                        //LCD讀寫控制
  83. sbit EN = P2^2;                        //LCD使能控制
  84. //sbit RS = P3^2;                        //LCD寄存器選擇
  85. //sbit RW = P3^3;                        //LCD讀寫控制
  86. //sbit EN = P3^4;                        //LCD使能控制
  87. /*//LCD相關函數
  88. void delay_ms(INT16U x);                          //延時函數
  89. void LCD_Busy_Wait();                             //忙等待
  90. void Write_LCD_Data(INT8U dat);                   //向LCD寫數據
  91. void Write_LCD_Command(INT8U cmd);                //寫LCD指令
  92. void Initialize_LCD();                            //LCD初始化
  93. void LCD_ShowString(INT8U r, INT8U c,char *str);  //在LCD上顯示字符串*/  
  94. //-----------------------------------------------------------------
  95. //        名稱: LCD1602液晶驅動程序
  96. //-----------------------------------------------------------------
  97. //#include "LCD1602-4bit.h"         
  98. #define delay5us() {_nop_();_nop_();_nop_();_nop_();_nop_();}
  99. //-----------------------------------------------------------------
  100. // 延時函數
  101. //-----------------------------------------------------------------
  102. void delay_ms(INT16U x)
  103. {
  104.         INT8U t;  while(x--) for(t = 0; t < 120; t++);
  105. }

  106. //-----------------------------------------------------------------
  107. // 液晶忙等待
  108. //-----------------------------------------------------------------
  109. /*
  110. void LCD_Busy_Wait()
  111. {
  112.         INT8U  LCD_Status;                //液晶狀態字節變量
  113.         do
  114.         {
  115.                 LCD_PORT=0xFF;
  116.                 RS=0; RW=1;
  117.                 EN=1; delay5us(); LCD_Status=P2; EN=0;
  118.         }while (LCD_Status & 0x80);               //液晶忙繼續循環
  119. } */
  120. //-----------------------------------------------------------------
  121. // 寫液晶命令
  122. //-----------------------------------------------------------------
  123. void Write_LCD_Command(INT8U cmd)
  124. {
  125.         INT8U  Temp1, Temp2;
  126.         //LCD_Busy_Wait();
  127.         EN = 0;          //使能清零       
  128.         RS=0; RW=0;                                                           //選擇命令寄存器,準備寫
  129.         EN=0; _nop_(); _nop_();
  130.         //由于4位的接線是接到LCD_PORT口的高四位,所以傳送高四位不用改
  131.         Temp1 = LCD_PORT&0x0f;
  132.         Temp2= (cmd&0xf0);
  133.         LCD_PORT= (Temp2|Temp1);      //數據送到液晶屏端口
  134.         delay_ms(1);
  135.         EN=1;   //寫入時序
  136.         delay_ms(1); EN=0;        //寫入后禁止液晶屏
  137.         Temp2= (cmd << 4);
  138.         Temp2&=0xf0;
  139.         LCD_PORT= (Temp2|Temp1); //寫入低四位
  140.         EN=1;   //寫入時序
  141.         delay_ms(1); EN=0;

  142.        
  143. }

  144. //-----------------------------------------------------------------
  145. // 向液晶寫數據
  146. //-----------------------------------------------------------------
  147. void Write_LCD_Data(INT8U dat)
  148. {
  149.         INT8U  Temp1, Temp2;
  150.         //LCD_Busy_Wait();
  151.         EN = 0;          //使能清零
  152.         RS=1; RW=0;
  153.         EN=0;
  154.         Temp1 = LCD_PORT&0x0f;
  155.         Temp2= (dat&0xf0);  //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
  156.         LCD_PORT=(Temp2|Temp1);    //數據送到液晶屏端口
  157.         delay_ms(1);
  158.         EN=1;   //寫入時序
  159.         delay_ms(1); EN=0;
  160.         Temp2= (dat << 4);
  161.         Temp2&=0xf0;
  162.         LCD_PORT = (Temp2|Temp1); //寫入低四位
  163.         EN=1;   //寫入時序
  164.         delay_ms(1); EN=0;

  165.        
  166. }
  167. //-----------------------------------------------------------------
  168. // 液晶初始化
  169. //-----------------------------------------------------------------
  170. void Initialize_LCD()
  171. {
  172.         //Write_LCD_Command(0x38); delay_ms(1);        //置功能,8位,雙行,5*7
  173.         Write_LCD_Command(0x32); delay_ms(1);        //將8位總線轉為4位總線
  174.         Write_LCD_Command(0x28); delay_ms(1);        // 在四位線下的初始化
  175.         Write_LCD_Command(0x06); delay_ms(1);        //字符進入模式:屏幕不動,字符后移
  176.         Write_LCD_Command(0x0C); delay_ms(1);        //顯示開,關光標
  177.         Write_LCD_Command(0x01); delay_ms(1);        //清屏
  178. }

  179. //-----------------------------------------------------------------
  180. // 在指定位置顯示字符串
  181. //-----------------------------------------------------------------
  182. void LCD_ShowString(INT8U r, INT8U c,char *str)
  183. {
  184.         INT8U i=0;
  185.         INT8U code DDRAM[] = {0x80,0xC0};         //液晶屏上下兩行的DDRAM首地址
  186.         Write_LCD_Command(DDRAM[r] |c);         //設置顯示起始位置
  187.         while (str[i] && i < 16) Write_LCD_Data(str[i++]);//輸出顯示字符
  188. }
  189. //-----------------------------------------------------------------
  190. // 蜂鳴器
  191. //-----------------------------------------------------------------
  192. void Beep()
  193. {
  194.         INT8U i; for(i=0;i<60;i++){SPK=!SPK; delay_ms(1);}
  195.         SPK=1;delay_ms(100);
  196. }

  197. //-----------------------------------------------------------------
  198. // 定時器0跟蹤同位按鍵的時間間隔
  199. //-----------------------------------------------------------------
  200. void T0_INT() interrupt 1
  201. {
  202.         //重新設置50ms定時初值
  203.         TH0=-50000>>8; TL0=-50000&0xFF;
  204.         //tSpan最大值限制在41及以上即可
  205.         //不加限制時會使某次較長的延時累加超過255后,
  206.         //累加又從0開始,而程序判斷時它可能剛好還在40以內,
  207.         //從而導致較長的延時卻被誤斷為較短的延時
  208.         if(tSpan<50) tSpan++;else TR0=0;
  209. }

  210. //-----------------------------------------------------------------
  211. // 功能鍵處理 *(9):切換輸入,#(11)鍵清除內容
  212. //-----------------------------------------------------------------
  213. void Function_Key_Process()
  214. {
  215.         if(KeyNo==9)                         //輸入內容標識切換
  216.         {        ENG_TEL=!ENG_TEL;
  217.                 Inner_Idx=ENG_TEL?1:0;  //如果是輸入英文,內部索引為1,否則設為0               
  218.         }
  219.         Buffer_Index=0;                      //輸入緩沖索引歸0
  220.         Input_Buffer[0]='\0';                //將輸入緩沖設為空串
  221.         if(ENG_TEL)     LCD_ShowString(1,0,"ENG>        ");          //顯示輸入英文
  222.         else            LCD_ShowString(1,0,"TEL>        ");          //顯示輸入電話
  223.         while(KeyMatrix_Down());                                     //等待釋放按鍵
  224. }

  225. //-----------------------------------------------------------------
  226. // 主程序
  227. //-----------------------------------------------------------------
  228. void main()
  229. {
  230.         INT8U Pre_KeyNo=-1;
  231.         IE=0x82;                               //使能T0中斷
  232.         TMOD=0x01;                             //T0工作于模式1(16位模式)
  233.         TH0=-50000>>8;                         //定時50ms
  234.         TL0=-50000&0xFF;
  235.         Initialize_LCD();        //液晶初始化
  236.         //顯示固定信息部分(初始顯示ENG>表示輸入英文字符序列)
  237.         LCD_ShowString(0,0," Mobile KeyPad ");
  238.         LCD_ShowString(1,0,"ENG>                ");
  239.         while(1)
  240.         {        //有鍵按下則掃描,否則不進行任何處理
  241.                 if(KeyMatrix_Down()) Keys_Scan();else continue;
  242.                 if(KeyNo==0xFF) continue;
  243.                 //功能鍵處理(9[*]:切換英文/數字,11[#]:清除所有輸入)
  244.                 if(KeyNo==9 || KeyNo == 11)
  245.                 {        Function_Key_Process(); Beep(); continue; }
  246.                 //如果是輸入數字則直接顯示
  247.                 if(!ENG_TEL) goto SHOW_MOBILE_KEY;
  248.                 //如果輸入的不是英文字母則繼續(英文字符在0~8號鍵,包括空格)
  249.                 if(KeyNo<0 || KeyNo>8) continue;
  250.                 //否則輸入的是英文字符序列,以下代碼將根據是否為同位按鍵進行相應處理
  251.                 if(Pre_KeyNo != KeyNo)         //按下新按鍵
  252.                 {        Pre_KeyNo = KeyNo;         //保存當前按鍵
  253.                         Inner_Idx = 1;                 //輸入英文時內部索引起點為1
  254.                 }
  255.                 else //否則按下的時相同位置按鍵
  256.                 {        //同位按鍵時間間隔在50ms*30=1.5s內則認為是連續按鍵
  257.                         if(tSpan<31)
  258.                         {        //連續按鍵時在鍵內循環遞增字符索引
  259.                                 if (++Inner_Idx == strlen(Keypad_Chars[KeyNo]))
  260.                                 Inner_Idx=1;
  261.                                 //因為是連續短按,故將每次顯示后遞增的輸入緩沖索引后退一格,
  262.                                 //以便替換此前輸入的字符
  263.                                 --Buffer_Index;
  264.                         } else Inner_Idx = 1; //否則按鍵內英文字符索引回歸起點索引1
  265.                 }
  266.                 tSpan=0; TR0=1;                         //時間間隔歸零,計時開始
  267.                 SHOW_MOBILE_KEY:                 //顯示按鍵字符
  268.                 if(Buffer_Index >= 12) continue; //輸入緩沖限制在12個字符以內
  269.                 //更新輸入緩沖字符串并送LCD顯示
  270.                 Input_Buffer[Buffer_Index++] = Keypad_Chars[KeyNo][Inner_Idx];
  271.                 Input_Buffer[Buffer_Index] = '\0';
  272.                 LCD_ShowString(1,4,Input_Buffer);
  273.                 Beep();                                         //輸出提示音
  274.                 while(KeyMatrix_Down()); //等待釋放按鍵
  275.         }
  276. }

復制代碼
回復

使用道具 舉報

7#
ID:55211 發表于 2019-5-16 00:22 | 只看該作者
回復

使用道具 舉報

8#
ID:162037 發表于 2023-6-19 14:39 | 只看該作者
#define LCD_PORT P2                //液晶端口(P2高4位)這里宏定義錯了,應該是:#define LCD_PORT P0                //液晶端口(P0高4位)
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人一区在线观看 | 国产色黄 | 午夜理伦三级理论三级在线观看 | 欧美在线色视频 | 日本三级网站在线 | 久久精品无码一区二区三区 | 欧美激情精品久久久久久 | 依人成人 | 亚洲巨乳自拍在线视频 | 一区二区三区中文字幕 | 五月槐花香| 91视视频在线观看入口直接观看 | 毛片a级 | 日韩中文字幕在线观看 | 久草在线影 | 久久久久亚洲视频 | 久久久久久久一级 | 18av在线播放 | 中文字幕在线观看第一页 | 国产成人在线视频播放 | 一区欧美 | 日本免费在线 | 亚洲免费在线 | 色综合久久88色综合天天 | 欧美男人天堂 | 日韩不卡一区二区 | 亚洲免费在线视频 | 国产福利在线看 | 日韩精品一区二区三区高清免费 | 日本二区在线观看 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 国精品一区 | 99精品视频免费观看 | 久久精品性视频 | 五月天激情综合网 | 国产精品片aa在线观看 | 91av在线免费 | 欧美综合国产精品久久丁香 | 亚洲成人综合社区 | 欧美激情在线观看一区二区三区 | 欧美日韩在线观看一区二区三区 |