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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 277|回復(fù): 8
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)實(shí)驗(yàn)板lcd1602無法正確顯示

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
想用過普中開發(fā)板來實(shí)現(xiàn)一個(gè)出租車計(jì)價(jià)器的方案,但是lcd1602無法正確顯示,代碼和開發(fā)板如下


單片機(jī)源程序如下:
  1. #include <reg52.h>
  2. // #include <stdio.h> // 不再需要,可以移除

  3. // -------------------- 類型定義 --------------------
  4. typedef unsigned char u8;
  5. typedef unsigned int u16;

  6. // -------------------- 引腳定義 --------------------
  7. // LCD1602
  8. sbit LCD_RS = P2^6;
  9. sbit LCD_RW = P2^5;
  10. sbit LCD_EN = P2^7;
  11. #define LCD_DataPort P0

  12. // 獨(dú)立按鍵
  13. sbit KEY_START_STOP = P3^1; // K1: 開始/停止
  14. sbit KEY_CLEAR = P3^0;      // K2: 清零 / 設(shè)置值-
  15. sbit KEY_MILEAGE = P3^2;    // K3: 里程+0.1 / 設(shè)置值+
  16. sbit KEY_SET = P3^3;        // K4: 設(shè)置

  17. // -------------------- 全局變量 --------------------
  18. // 計(jì)價(jià)器狀態(tài): 0-停止, 1-計(jì)價(jià)中, 2-設(shè)置模式
  19. u8 status = 0;
  20. // 設(shè)置模式子狀態(tài): 0-未設(shè)置, 1-設(shè)置起步價(jià), 2-設(shè)置起步里程, 3-設(shè)置單價(jià)
  21. u8 setting_mode = 0;

  22. // --- 計(jì)價(jià)參數(shù) (默認(rèn)值) ---
  23. u16 base_price = 130;  // 起步價(jià): 13.0 元
  24. u16 base_mileage = 30; // 起步里程: 3.0 公里
  25. u16 unit_price = 23;   // 單價(jià): 2.3 元/公里

  26. // --- 實(shí)時(shí)數(shù)據(jù) ---
  27. u16 mileage = 0;    // 行車?yán)锍?(x0.1 公里)
  28. u16 price = 0;      // 總價(jià) (x0.1 元)
  29. u16 time_s = 0;     // 行車時(shí)長 (秒)
  30. u16 time_m = 0;     // 分
  31. u16 time_h = 0;     // 時(shí)

  32. // 定時(shí)器中斷計(jì)數(shù)變量
  33. u16 timer_count = 0;

  34. // -------------------- 函數(shù)聲明 --------------------
  35. // 延時(shí)
  36. void DelayMs(u16 ms);

  37. // LCD驅(qū)動(dòng)
  38. void LcdWriteCmd(u8 cmd);
  39. void LcdWriteData(u8 dat);
  40. void LcdInit();
  41. void LcdSetCursor(u8 row, u8 col);
  42. void LcdShowString(u8 row, u8 col, u8 *str);
  43. void LcdShowNum(u8 row, u8 col, u16 num, u8 len); // 顯示數(shù)字
  44. void LcdShowTime(); // 單獨(dú)的時(shí)間顯示函數(shù)

  45. // 顯示界面
  46. void UpdateDisplay();
  47. void DisplaySettingMode();

  48. // 核心邏輯
  49. void CalculatePrice();
  50. void KeyAction();
  51. void ResetAll();
  52. void Timer0Init();


  53. // -------------------- 主函數(shù) --------------------
  54. void main() {
  55.     Timer0Init();
  56.     LcdInit();
  57.     ResetAll();
  58.    
  59.     while(1) {
  60.         KeyAction();
  61.         if (status == 1) { // 只有在計(jì)時(shí)狀態(tài)才需要不斷刷新時(shí)間
  62.             LcdShowTime();
  63.         }
  64.     }
  65. }

  66. // -------------------- 核心邏輯函數(shù) --------------------
  67. void CalculatePrice() {
  68.     if (mileage <= base_mileage) {
  69.         price = base_price;
  70.     } else {
  71.         unsigned long temp_price = (unsigned long)(mileage - base_mileage) * unit_price;
  72.         price = base_price + temp_price / 10;
  73.     }
  74.     // 價(jià)格計(jì)算后立即更新顯示
  75.     if (status != 2) {
  76.         UpdateDisplay();
  77.     }
  78. }

  79. void KeyAction() {
  80.     if (KEY_START_STOP == 0) {
  81.         DelayMs(20);
  82.         if (KEY_START_STOP == 0) {
  83.             if (status != 2) {
  84.                 status = !status;
  85.                 if(status == 1 && mileage == 0){
  86.                     CalculatePrice(); // 開始時(shí)就計(jì)算一次價(jià)格
  87.                 } else if (status == 0) {
  88.                     // 停止計(jì)時(shí),但顯示保持不變
  89.                 }
  90.                  UpdateDisplay(); // 更新顯示(特別是狀態(tài)字符)
  91.             }
  92.         }
  93.         while(KEY_START_STOP == 0);
  94.     }
  95.    
  96.     if (KEY_CLEAR == 0) {
  97.         DelayMs(20);
  98.         if (KEY_CLEAR == 0) {
  99.             if (status == 0) {
  100.                 ResetAll();
  101.             } else if (status == 2) {
  102.                 switch(setting_mode) {
  103.                     case 1: if(base_price > 50) base_price -= 10; break;
  104.                     case 2: if(base_mileage > 10) base_mileage -= 10; break;
  105.                     case 3: if(unit_price > 10) unit_price -= 1; break;
  106.                 }
  107.                 DisplaySettingMode();
  108.             }
  109.         }
  110.         while(KEY_CLEAR == 0);
  111.     }
  112.    
  113.     if (KEY_MILEAGE == 0) {
  114.         DelayMs(20);
  115.         if (KEY_MILEAGE == 0) {
  116.             if (status == 1) {
  117.                 mileage++;
  118.                 CalculatePrice();
  119.             } else if (status == 2) {
  120.                 switch(setting_mode) {
  121.                     case 1: base_price += 10; break;
  122.                     case 2: base_mileage += 10; break;
  123.                     case 3: unit_price += 1; break;
  124.                 }
  125.                 DisplaySettingMode();
  126.             }
  127.         }
  128.         while(KEY_MILEAGE == 0);
  129.     }
  130.    
  131.     if (KEY_SET == 0) {
  132.         DelayMs(20);
  133.         if (KEY_SET == 0) {
  134.             if(status == 1) return;

  135.             status = 2;
  136.             setting_mode++;
  137.             if (setting_mode > 3) {
  138.                 setting_mode = 0;
  139.                 status = 0;
  140.                 ResetAll();
  141.             } else {
  142.                 DisplaySettingMode();
  143.             }
  144.         }
  145.         while(KEY_SET == 0);
  146.     }
  147. }

  148. void ResetAll() {
  149.     status = 0; // 確保是停止?fàn)顟B(tài)
  150.     mileage = 0;
  151.     price = 0;
  152.     time_s = 0;
  153.     time_m = 0;
  154.     time_h = 0;
  155.     T0 = 0; // 如果有,也停止計(jì)時(shí)器
  156.     UpdateDisplay(); // 更新整個(gè)顯示
  157.     LcdShowTime();
  158. }

  159. // -------------------- 顯示相關(guān)函數(shù) (無sprintf) --------------------
  160. // 更新主顯示界面(里程和價(jià)格)
  161. void UpdateDisplay() {
  162.     // 第一行: L:XXX.XKM P:XXXX.X
  163.     LcdShowString(0, 0, "L:    KM P:     "); // 模板,用空格覆蓋舊數(shù)據(jù)
  164.     LcdShowNum(0, 2, mileage / 10, 3); // 里程整數(shù)部分,最多3位
  165.     LcdWriteData('.');
  166.     LcdShowNum(0, 6, mileage % 10, 1); // 里程小數(shù)部分
  167.    
  168.     LcdShowNum(0, 11, price / 10, 4); // 價(jià)格整數(shù)部分,最多4位
  169.     LcdWriteData('.');
  170.     LcdShowNum(0, 16, price % 10, 1); // 價(jià)格小數(shù)部分

  171.     // 在時(shí)間前面顯示狀態(tài)符號
  172.     LcdSetCursor(1, 0);
  173.     if(status == 1) LcdWriteData('T'); // Timing
  174.     else if(status == 0) LcdWriteData('S'); // Stop
  175.     else if(status == 2) LcdWriteData('C'); // Config
  176. }

  177. // 單獨(dú)更新時(shí)間顯示,減少LCD刷新
  178. void LcdShowTime() {
  179.     // 第二行: T:HH:MM:SS
  180.     LcdSetCursor(1, 1);
  181.     LcdShowString(1, 1, ":");
  182.     LcdShowNum(1, 2, time_h, 2);
  183.     LcdShowString(1, 4, ":");
  184.     LcdShowNum(1, 5, time_m, 2);
  185.     LcdShowString(1, 7, ":");
  186.     LcdShowNum(1, 8, time_s, 2);
  187. }

  188. // 顯示設(shè)置模式界面
  189. void DisplaySettingMode() {
  190.     LcdWriteCmd(0x01); // 清屏
  191.     UpdateDisplay();   // 顯示狀態(tài)'C'
  192.     switch(setting_mode) {
  193.         case 1:
  194.             LcdShowString(0, 0, "Set Base Price  ");
  195.             LcdShowNum(1, 5, base_price/10, 3);
  196.             LcdWriteData('.');
  197.             LcdShowNum(1, 9, base_price%10, 1);
  198.             LcdShowString(1, 10, " Yuan ");
  199.             break;
  200.         case 2:
  201.             LcdShowString(0, 0, "Set Base Mile   ");
  202.             LcdShowNum(1, 5, base_mileage/10, 2);
  203.             LcdWriteData('.');
  204.             LcdShowNum(1, 8, base_mileage%10, 1);
  205.             LcdShowString(1, 9, " KM   ");
  206.             break;
  207.         case 3:
  208.             LcdShowString(0, 0, "Set Unit Price  ");
  209.             LcdShowNum(1, 5, unit_price/10, 2);
  210.             LcdWriteData('.');
  211.             LcdShowNum(1, 8, unit_price%10, 1);
  212.             LcdShowString(1, 9, " Y/KM ");
  213.             break;
  214.     }
  215. }

  216. // -------------------- 定時(shí)器和中斷 --------------------
  217. void Timer0Init() {
  218.     TMOD &= 0xF0;
  219.     TMOD |= 0x01;
  220.     TH0 = (65536 - 1000) / 256;
  221.     TL0 = (65536 - 1000) % 256;
  222.     EA = 1;
  223.     ET0 = 1;
  224.     TR0 = 1;
  225. }

  226. void timer0_isr() interrupt 1 {
  227.     TH0 = (65536 - 1000) / 256;
  228.     TL0 = (65536 - 1000) % 256;

  229.     if (status == 1) {
  230.         timer_count++;
  231.         if (timer_count >= 1000) {
  232.             timer_count = 0;
  233.             time_s++;
  234.             if (time_s >= 60) {
  235.                 time_s = 0;
  236.                 time_m++;
  237.                 if (time_m >= 60) {
  238.                     time_m = 0;
  239.                     time_h++;
  240.                 }
  241.             }
  242.         }
  243.     }
  244. }

  245. // -------------------- LCD底層驅(qū)動(dòng) --------------------
  246. void DelayMs(u16 ms) {
  247.     u16 i, j;
  248.     for(i=ms; i>0; i--)
  249.         for(j=120; j>0; j--);
  250. }

  251. void LcdWriteCmd(u8 cmd) {
  252.     LCD_RS = 0;
  253.     LCD_RW = 0;
  254.     LCD_DataPort = cmd;
  255.     DelayMs(1);
  256.     LCD_EN = 1;
  257.     DelayMs(1);
  258.     LCD_EN = 0;
  259. }

  260. void LcdWriteData(u8 dat) {
  261.     LCD_RS = 1;
  262.     LCD_RW = 0;
  263.     LCD_DataPort = dat;
  264.     DelayMs(1);
  265.     LCD_EN = 1;
  266.     DelayMs(1);
  267.     LCD_EN = 0;
  268. }

  269. void LcdInit() {
  270.     LcdWriteCmd(0x38);
  271.     LcdWriteCmd(0x0C);
  272.     LcdWriteCmd(0x06);
  273.     LcdWriteCmd(0x01);
  274.     DelayMs(5);
  275. }

  276. void LcdSetCursor(u8 row, u8 col) {
  277.     u8 addr;
  278.     if (row == 0) {
  279.         addr = 0x80 + col;
  280.     } else {
  281.         addr = 0x80 + 0x40 + col;
  282.     }
  283.     LcdWriteCmd(addr);
  284. }

  285. void LcdShowString(u8 row, u8 col, u8 *str) {
  286.     LcdSetCursor(row, col);
  287.     while(*str != '\0') {
  288.         LcdWriteData(*str++);
  289.     }
  290. }

  291. // *** 新增的顯示數(shù)字的函數(shù) ***
  292. // 在(row, col)顯示數(shù)字num,共顯示len位,不足則前面補(bǔ)空格
  293. void LcdShowNum(u8 row, u8 col, u16 num, u8 len) {
  294.     u8 i;
  295.     u8 buf[5]; // 假設(shè)數(shù)字最大5位
  296.     for (i = 0; i < len; i++) {
  297.         buf[len - 1 - i] = (num % 10) + '0';
  298.         num /= 10;
  299.     }
  300.    
  301.     // 如果數(shù)字本身位數(shù)小于len,前面補(bǔ)空格
  302.     for (i = 0; i < len; i++) {
  303.         if (num == 0 && buf[i] == '0' && i < len - 1) { // 找到最高位
  304.              if(i < len - 1) buf[i] = ' '; // 將高位0轉(zhuǎn)換為空格, 但保留個(gè)位數(shù)0
  305.         } else {
  306.             break; // 找到第一個(gè)非零數(shù)字后停止
  307.         }
  308.     }
  309.     // 處理num=0的情況
  310.     if (len > 1 && buf[0] == ' ') {
  311.          // 確保個(gè)位數(shù)如果是0,能正常顯示
  312.          if(len > 1 && num == 0){
  313.              // 此處確保至少有一個(gè)'0'顯示
  314.          }
  315.     }


  316.     LcdSetCursor(row, col);
  317.     for (i = 0; i < len; i++) {
  318.         LcdWriteData(buf[i]);
  319.     }
  320. }
復(fù)制代碼
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:276663 發(fā)表于 2025-7-9 13:39 | 只看該作者
1,檢查pin腳定義,
2,檢查端口是否有輸出正確的數(shù)據(jù),
3,檢查數(shù)據(jù)的LSB還是MSB.
回復(fù)

使用道具 舉報(bào)

板凳
ID:584814 發(fā)表于 2025-7-9 15:46 | 只看該作者
學(xué)習(xí)板自帶的1602例程移植就好。
回復(fù)

使用道具 舉報(bào)

地板
ID:1152291 發(fā)表于 2025-7-9 16:28 | 只看該作者
首先你使用LCD1602的液晶屏應(yīng)該是有自帶的驅(qū)動(dòng)程序。從你需要實(shí)現(xiàn)的目的開始求我們現(xiàn)在,你的要是沒有看到的。不知道你的具體要求是什莫。你是不是覺得LCD1602比較簡單,我給你說我之前用普中科技的板子寫代碼用來寫字符的時(shí)候時(shí),我也出錯(cuò)了。所以我大概率判斷是你的LCD1602的驅(qū)動(dòng)程序有問題,是需要去查看LCD1602驅(qū)動(dòng)程序的問題。也有可能是你的端口輸出數(shù)據(jù)的問題,數(shù)據(jù)到底是LSB還是MSB呢,你是不是把數(shù)據(jù)的類型搞錯(cuò)了哦。是不是輸出的數(shù)據(jù)類型不對等的呢。
回復(fù)

使用道具 舉報(bào)

5#
ID:88256 發(fā)表于 2025-7-9 18:07 | 只看該作者
這個(gè)程序是從這塊開發(fā)板的1602移植的嗎?看照片各個(gè)模塊的引腳是固定死無法自己定義的,所以軟件得服從硬件,先把各個(gè)引腳定義為硬件的實(shí)際連接才行。
回復(fù)

使用道具 舉報(bào)

6#
ID:1156151 發(fā)表于 2025-7-9 18:30 | 只看該作者
首先你使用LCD1602的液晶屏應(yīng)該是有自帶的驅(qū)動(dòng)程序。從你需要實(shí)現(xiàn)的目的開始求我們現(xiàn)在,你的要是沒有看到的。不知道你的具體要求是什莫。你是不是覺得LCD1602比較簡單,我給你說我之前用普中科技的板子寫代碼用來寫字符的時(shí)候時(shí),我也出錯(cuò)了。所以我大概率判斷是你的LCD1602的驅(qū)動(dòng)程序有問題,是需要去查看LCD1602驅(qū)動(dòng)程序的問題。也有可能是你的端口輸出數(shù)據(jù)的問題,數(shù)據(jù)到底是LSB還是MSB呢.
回復(fù)

使用道具 舉報(bào)

7#
ID:88256 發(fā)表于 2025-7-9 22:47 | 只看該作者
地板樓的“單片機(jī)重購”和6樓的“ID:1156151”帖子怎么一模一樣?是同一個(gè)人嗎?
回復(fù)

使用道具 舉報(bào)

8#
ID:384109 發(fā)表于 2025-7-10 16:43 | 只看該作者
沒查忙
回復(fù)

使用道具 舉報(bào)

9#
ID:1064915 發(fā)表于 2025-7-11 08:49 | 只看該作者
單獨(dú)實(shí)驗(yàn)1602
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 91午夜精品亚洲一区二区三区 | 秋霞一区二区三区 | 国产成人精品毛片 | 国产精品自拍小视频 | 日本一本在线 | 在线免费观看黄 | 黄色大片一级 | 成人免费福利视频 | 精品黄色片| 午夜视频在线免费观看 | 精品免费在线 | 国产日韩在线播放 | 亚洲视频免费看 | 中文字幕在线观看免费视频 | 日韩999 | 四虎永久在线 | 国产一区二区在线观看视频 | jizz中国女人高潮 | 黑森林av | 亚洲欧美一区二区三区在线 | 久久靖品| 亚洲一区二区三区视频 | 免费网站黄色 | 国产福利视频在线观看 | 日韩一级在线观看 | 久久精品美女 | 欧美日韩视频 | av大全在线观看 | 亚洲国产精品久久久久久久 | 成年免费视频黄网站在线观看 | 黄色小视频在线播放 | 国产一区二区影院 | 国产精品自拍一区 | 亚洲69视频| 久久久三级 | 日韩中文字幕一区二区 | 国产区视频在线观看 | 91av免费观看 | 亚洲视频一区 | 久久伊人网站 | 日产久久视频 |