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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2991|回復: 9
收起左側

關于單片機+LCD602頻閃問題求分析

[復制鏈接]
ID:531175 發表于 2019-5-17 00:39 | 顯示全部樓層 |閱讀模式
同志們,我遇到了一些困難,我在做掉電走時的時鐘,一塊LCD1602,一塊ds1302,當我燒進程序后,lcd可以實現掉電走時,但是會頻閃,導致lcd顯示的模糊,老師說是程序問題,不要一直判忙,不斷清屏,說只要一秒傳一次數據,并且lcd不清屏,只讓數增加即可,但我還是有點不明白,希望大家可以指點迷津,下面的程序是lcd.c的,大家可以幫我改改嗎

單片機源程序如下:
#include <reg52.h>
#define LCD1602_DB  P0
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_E  = P2^7;


void LcdWaitReady()
{
    unsigned char sta;
   
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
    delay(500);
        LCD1602_E = 1;
        sta = LCD1602_DB;
        LCD1602_E = 0;
   } while (sta & 0x80); //我覺得這個do while 可能要改
}

void LcdWriteCmd(unsigned char cmd)
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}

void LcdWriteDat(unsigned char dat)
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
   
    if (y == 0)  
        addr = 0x00 + x;
    else
        addr = 0x40 + x;  
    LcdWriteCmd(addr | 0x80);
}
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    LcdSetCursor(x, y);
    while (*str != '\0')
    {
        LcdWriteDat(*str++);
    }
}
void InitLcd1602()
{
    LcdWriteCmd(0x38);  
    LcdWriteCmd(0x0C);  
    LcdWriteCmd(0x06);  //文字不動,地址自動+1
    LcdWriteCmd(0x01);  //清屏
}



回復

使用道具 舉報

ID:155507 發表于 2019-5-17 06:12 | 顯示全部樓層
主程序呢?
你這個程序不完整,沒法給你看是哪里出問題了!
回復

使用道具 舉報

ID:149451 發表于 2019-5-17 06:50 | 顯示全部樓層
把main.c放上來看看,如果沒其它功能僅是時鐘,建議不去判忙,適當引進延時,把程序處理”干凈”
回復

使用道具 舉報

ID:123289 發表于 2019-5-17 08:46 | 顯示全部樓層
做個掉電標記,掉電后只走時,不做顯示不就OK了嗎。
回復

使用道具 舉報

ID:7485 發表于 2019-5-17 09:18 | 顯示全部樓層
看不見你的主函數。
回復

使用道具 舉報

ID:531175 發表于 2019-5-17 13:53 | 顯示全部樓層
這是main.c函數,我把1302函數寫到了里面,大家幫我看看吧,非常感謝你們



  1. #include <reg52.h>

  2. sbit DS1302_CE = P1^7;
  3. sbit DS1302_CK = P3^5;
  4. sbit DS1302_IO = P3^4;

  5. bit flag200ms = 0;       //200ms定時標志
  6. unsigned char T0RH = 0;  //T0重載值的高字節
  7. unsigned char T0RL = 0;  //T0重載的低字節

  8. void ConfigTimer0(unsigned int ms);
  9. void InitDS1302();
  10. void DS1302BurstRead(unsigned char *dat);
  11. extern void InitLcd1602();
  12. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

  13. void main()
  14. {
  15.     unsigned char psec=0xAA;//秒備份,初值AA確保首次讀取時間后會刷新顯示
  16.     unsigned char time[8];    //當前時間數組
  17.     unsigned char str[12];    //字符串轉換緩沖區

  18.     EA = 1;           //開總中斷
  19.     ConfigTimer0(1);  //T0定時1ms
  20.     InitDS1302();     //初始化實時時鐘
  21.     InitLcd1602();    //初始化液晶
  22.    
  23.     while (1)
  24.     {
  25.         if (flag200ms)  //每200ms讀取依次時間
  26.         {
  27.             flag200ms = 0;
  28.             DS1302BurstRead(time); //
  29. 讀取DS1302當前時間
  30.             if (psec != time[0])   //檢測到時間有變化時刷新顯示
  31.             {
  32.                 str[0] = '2';  
  33.                 str[1] = '0';
  34.                 str[2] = (time[6] >> 4) + '0';  
  35.                 str[3] = (time[6]&0x0F) + '0';  
  36.                 str[4] = '-';
  37.                 str[5] = (time[4] >> 4) + '0';  
  38.                 str[6] = (time[4]&0x0F) + '0';
  39.                 str[7] = '-';
  40.                 str[8] = (time[3] >> 4) + '0';  
  41.                 str[9] = (time[3]&0x0F) + '0';
  42.                 str[10] = '\0';
  43.                 LcdShowStr(0, 0, str);
  44.                 //顯示到液晶的第一行

  45.                 str[0] = (time[5]&0x0F) + '0';  
  46.                 str[1] = '\0';
  47.                 LcdShowStr(11, 0, "week");
  48.                 LcdShowStr(15, 0, str); //顯示到液晶的第一行
  49.          
  50.                 str[0] = (time[2] >> 4) + '0';  
  51.                 str[1] = (time[2]&0x0F) + '0';
  52.                 str[2] = ':';
  53.                 str[3] = (time[1] >> 4) + '0';  
  54.                 str[4] = (time[1]&0x0F) + '0';
  55.                 str[5] = ':';
  56.                 str[6] = (time[0] >> 4) + '0';  
  57.                 str[7] = (time[0]&0x0F) + '0';
  58.                 str[8] = '\0';
  59.                 LcdShowStr(4, 1, str);  //顯示到第二行
  60.                
  61.                 psec = time[0];  //用當前值更新上次秒數
  62.             }
  63.         }
  64.     }
  65. }

  66. /* 發送一個字節到DS1302通信總線上 */
  67. void DS1302ByteWrite(unsigned char dat)
  68. {
  69.     unsigned char mask;
  70.    
  71.     for (mask=0x01; mask!=0; mask<<=1)  //低位在前,逐位輸出
  72.     {
  73.         if ((mask&dat) != 0) //首先輸出該位數據
  74.             DS1302_IO = 1;
  75.         else
  76.             DS1302_IO = 0;
  77.         DS1302_CK = 1;       //拉高時鐘
  78.         DS1302_CK = 0;       //拉低時鐘,
  79.     }
  80.     DS1302_IO = 1;           //確保釋放IO
  81. }
  82. /* 由DS1302讀取一個字節*/
  83. unsigned char DS1302ByteRead()
  84. {
  85.     unsigned char mask;
  86.     unsigned char dat = 0;
  87.    
  88.     for (mask=0x01; mask!=0; mask<<=1) //低位在前,逐位輸出
  89.     {
  90.         if (DS1302_IO != 0)  //讀取IO引腳,并設置對應位
  91.         {
  92.             dat |= mask;
  93.         }
  94.         DS1302_CK = 1;       //拉高時鐘
  95.         DS1302_CK = 0;       //拉低時鐘,完成一個位
  96.     }
  97.     return dat;      
  98. }
  99. /* reg-寄存器地址,dat-待寫入字節 */
  100. void DS1302SingleWrite(unsigned char reg, unsigned char dat)
  101. {
  102.     DS1302_CE = 1;                  
  103.     DS1302ByteWrite((reg<<1)|0x80);  
  104.     DS1302ByteWrite(dat);      
  105.     DS1302_CE = 0;           
  106. }
  107. /* reg-寄存器地址,返回值-讀到的字節 */
  108. unsigned char DS1302SingleRead(unsigned char reg)
  109. {
  110.     unsigned char dat;
  111.    
  112.     DS1302_CE = 1;  
  113.     DS1302ByteWrite((reg<<1)|0x81);  
  114.     dat = DS1302ByteRead();   
  115.     DS1302_CE = 0;   
  116.     return dat;
  117. }
  118. void  DS1302BurstWrite(unsigned char *dat)
  119. {
  120.         unsigned char i;

  121.         DS1302_CE = 1;
  122.         DS1302ByteWrite(0xBE);
  123.         for(i=0; i<8; i++)
  124.         {
  125.                 DS1302ByteWrite(dat[i]);
  126.         }
  127.         DS1302_CE = 0;
  128. }

  129. void  DS1302BurstRead(unsigned char *dat)
  130. {
  131.         unsigned char i;

  132.         DS1302_CE = 1;
  133.         DS1302ByteWrite(0xBF);
  134.         for(i=0; i<8; i++)
  135.         {
  136.                 dat[i] = DS1302ByteRead();
  137.         }
  138.         DS1302_CE = 0;
  139. }
  140. /* DS1302初始化,掉電則重新設置初試時間*/
  141. void InitDS1302()
  142. {
  143.     unsigned char dat;
  144.     unsigned char code InitTime[] = {0x00,0x30,0x00, 0x16, 0x05, 0x04, 0x19};        //2019年5月16日 星期四12:30:00
  145.    
  146.     DS1302_CE = 0;
  147.     DS1302_CK = 0;
  148.     dat = DS1302SingleRead(0);
  149.     if ((dat & 0x80) != 0)      //秒寄存器最高位CH值判斷DS1302是否已停止
  150.     {
  151.         DS1302SingleWrite(7, 0x00);  //撤銷寫保護以允許寫入數據
  152.         DS1302BurstWrite(InitTime);  //設置DS1302為默認的初始時間
  153.     }
  154. }
  155. /* 配置并啟動T0,ms-T0定時時間 */
  156. void ConfigTimer0(unsigned int ms)
  157. {
  158.     unsigned long tmp;  //臨時變量
  159.    
  160.     tmp = 11059200 / 12;
  161.     tmp = (tmp * ms) /1000;
  162.     tmp = 65536 - tmp;
  163.     tmp = tmp + 12;           //補償中斷響應延時造成的誤差
  164.     T0RH = (unsigned char)(tmp>>8);
  165.     T0RL = (unsigned char)tmp;
  166.     TMOD &= 0xF0;   //清零T0的控制位
  167.     TMOD |= 0x01;   
  168.     TH0 = T0RH;
  169.     TL0 = T0RL;
  170.     ET0 = 1;
  171.     TR0 = 1;   
  172. }
  173. /* T0中斷服務函數,200ms定時*/
  174. void InterruptTimer0() interrupt 1
  175. {
  176.     static unsigned char tmr200ms = 0;
  177.    
  178.     TH0 = T0RH;  //重新加載重載值
  179.     TL0 = T0RL;
  180.     tmr200ms++;
  181.     if (tmr200ms >= 200)  //定時200ms
  182.     {
  183.         tmr200ms = 0;
  184.         flag200ms = 1;
  185.     }
  186. }
復制代碼
回復

使用道具 舉報

ID:531175 發表于 2019-5-18 13:57 | 顯示全部樓層
w1179benp 發表于 2019-5-17 06:50
把main.c放上來看看,如果沒其它功能僅是時鐘,建議不去判忙,適當引進延時,把程序處理”干凈”

您好,我把主函數放上來了,您幫我看看吧,非常感謝
回復

使用道具 舉報

ID:531175 發表于 2019-5-18 13:58 | 顯示全部樓層
angmall 發表于 2019-5-17 06:12
主程序呢?
你這個程序不完整,沒法給你看是哪里出問題了!

您好,我把主函數放上來了,您幫我看看吧,非常感謝
回復

使用道具 舉報

ID:213173 發表于 2019-5-18 18:52 | 顯示全部樓層
迷迷惘惘 發表于 2019-5-17 13:53
這是main.c函數,我把1302函數寫到了里面,大家幫我看看吧,非常感謝你們

樓主這個程序不完整,缺少按鍵調整程序。把一些抄寫錯誤糾正后通過編譯,仿真時沒有發現樓主所言的頻閃問題。 無標題.jpg


  1. #include <reg52.h>
  2. #define LCD1602_DB  P0
  3. sbit LCD1602_RS = P2^6;
  4. sbit LCD1602_RW = P2^5;
  5. sbit LCD1602_E  = P2^7;

  6. sbit DS1302_CE = P1^7;
  7. sbit DS1302_CK = P3^5;
  8. sbit DS1302_IO = P3^4;

  9. bit flag200ms = 0;       //200ms定時標志
  10. unsigned char T0RH = 0;  //T0重載值的高字節
  11. unsigned char T0RL = 0;  //T0重載的低字節

  12. void ConfigTimer0(unsigned int ms);
  13. void InitDS1302();
  14. void DS1302BurstRead(unsigned char *dat);
  15. void InitLcd1602();
  16. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

  17. void delay(unsigned int t)
  18. {
  19.         while(--t);
  20. }

  21. void LcdWaitReady()
  22. {
  23.     unsigned char sta;
  24.    
  25.     LCD1602_DB = 0xFF;
  26.     LCD1602_RS = 0;
  27.     LCD1602_RW = 1;
  28.     do {
  29.     delay(500);
  30.         LCD1602_E = 1;
  31.         sta = LCD1602_DB;
  32.         LCD1602_E = 0;
  33.    } while (sta & 0x80); //我覺得這個do while 可能要改
  34. }

  35. void LcdWriteCmd(unsigned char cmd)
  36. {
  37.     LcdWaitReady();
  38.     LCD1602_RS = 0;
  39.     LCD1602_RW = 0;
  40.     LCD1602_DB = cmd;
  41.     LCD1602_E  = 1;
  42.     LCD1602_E  = 0;
  43. }

  44. void LcdWriteDat(unsigned char dat)
  45. {
  46.     LcdWaitReady();
  47.     LCD1602_RS = 1;
  48.     LCD1602_RW = 0;
  49.     LCD1602_DB = dat;
  50.     LCD1602_E  = 1;
  51.     LCD1602_E  = 0;
  52. }
  53. void LcdSetCursor(unsigned char x, unsigned char y)
  54. {
  55.     unsigned char addr;
  56.    
  57.     if (y == 0)  
  58.         addr = 0x00 + x;
  59.     else
  60.         addr = 0x40 + x;  
  61.     LcdWriteCmd(addr | 0x80);
  62. }
  63. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  64. {
  65.     LcdSetCursor(x, y);
  66.     while (*str != '\0')
  67.     {
  68.         LcdWriteDat(*str++);
  69.     }
  70. }
  71. void InitLcd1602()
  72. {
  73.     LcdWriteCmd(0x38);  
  74.     LcdWriteCmd(0x0C);  
  75.     LcdWriteCmd(0x06);  //文字不動,地址自動+1
  76.     LcdWriteCmd(0x01);  //清屏
  77. }


  78. void main()
  79. {
  80.         unsigned char psec=0xAA;//秒備份,初值AA確保首次讀取時間后會刷新顯示
  81.         unsigned char time[8];    //當前時間數組
  82.         unsigned char str[12];    //字符串轉換緩沖區

  83.     EA = 1;           //開總中斷
  84.     ConfigTimer0(1);  //T0定時1ms
  85.     InitDS1302();     //初始化實時時鐘
  86.     InitLcd1602();    //初始化液晶
  87.    
  88.     while (1)
  89.     {
  90.         if (flag200ms)  //每200ms讀取依次時間
  91.         {
  92.             flag200ms = 0;
  93.             DS1302BurstRead(time); //讀取DS1302當前時間
  94.             if (psec != time[0])   //檢測到時間有變化時刷新顯示
  95.             {
  96.                 str[0] = '2';  
  97.                 str[1] = '0';
  98.                 str[2] = (time[6] >> 4) + '0';  
  99.                 str[3] = (time[6]&0x0F) + '0';  
  100.                 str[4] = '-';
  101.                 str[5] = (time[4] >> 4) + '0';  
  102.                 str[6] = (time[4]&0x0F) + '0';
  103.                 str[7] = '-';
  104.                 str[8] = (time[3] >> 4) + '0';  
  105.                 str[9] = (time[3]&0x0F) + '0';
  106.                 str[10] = '\0';
  107.                 LcdShowStr(0, 0, str);
  108.                 //顯示到液晶的第一行

  109.                 str[0] = (time[5]&0x0F) + '0';  
  110.                 str[1] = '\0';
  111.                 LcdShowStr(11, 0, "week");
  112.                 LcdShowStr(15, 0, str); //顯示到液晶的第一行
  113.          
  114.                 str[0] = (time[2] >> 4) + '0';  
  115.                 str[1] = (time[2]&0x0F) + '0';
  116.                 str[2] = ':';
  117.                 str[3] = (time[1] >> 4) + '0';  
  118.                 str[4] = (time[1]&0x0F) + '0';
  119.                 str[5] = ':';
  120.                 str[6] = (time[0] >> 4) + '0';  
  121.                 str[7] = (time[0]&0x0F) + '0';
  122.                 str[8] = '\0';
  123.                 LcdShowStr(4, 1, str);  //顯示到第二行
  124.                
  125.                 psec = time[0];  //用當前值更新上次秒數
  126.             }
  127.         }
  128.     }
  129. }

  130. /* 發送一個字節到DS1302通信總線上 */
  131. void DS1302ByteWrite(unsigned char dat)
  132. {
  133.     unsigned char mask;
  134.    
  135.     for (mask=0x01; mask!=0; mask<<=1)  //低位在前,逐位輸出
  136.     {
  137.         if ((mask&dat) != 0) //首先輸出該位數據
  138.             DS1302_IO = 1;
  139.         else
  140.             DS1302_IO = 0;
  141.         DS1302_CK = 1;       //拉高時鐘
  142.         DS1302_CK = 0;       //拉低時鐘,
  143.     }
  144.     DS1302_IO = 1;           //確保釋放IO
  145. }
  146. /* 由DS1302讀取一個字節*/
  147. unsigned char DS1302ByteRead()
  148. {
  149.     unsigned char mask;
  150.     unsigned char dat = 0;
  151.    
  152.     for (mask=0x01; mask!=0; mask<<=1) //低位在前,逐位輸出
  153.     {
  154.         if (DS1302_IO != 0)  //讀取IO引腳,并設置對應位
  155.         {
  156.             dat |= mask;
  157.         }
  158.         DS1302_CK = 1;       //拉高時鐘
  159.         DS1302_CK = 0;       //拉低時鐘,完成一個位
  160.     }
  161.     return dat;      
  162. }
  163. /* reg-寄存器地址,dat-待寫入字節 */
  164. void DS1302SingleWrite(unsigned char reg, unsigned char dat)
  165. {
  166.     DS1302_CE = 1;                  
  167.     DS1302ByteWrite((reg<<1)|0x80);  
  168.     DS1302ByteWrite(dat);      
  169.     DS1302_CE = 0;           
  170. }
  171. /* reg-寄存器地址,返回值-讀到的字節 */
  172. unsigned char DS1302SingleRead(unsigned char reg)
  173. {
  174.     unsigned char dat;
  175.    
  176.     DS1302_CE = 1;  
  177.     DS1302ByteWrite((reg<<1)|0x81);  
  178.     dat = DS1302ByteRead();   
  179.     DS1302_CE = 0;   
  180.     return dat;
  181. }
  182. void  DS1302BurstWrite(unsigned char *dat)
  183. {
  184.         unsigned char i;

  185.         DS1302_CE = 1;
  186.         DS1302ByteWrite(0xBE);
  187.         for(i=0; i<8; i++)
  188.         {
  189.                 DS1302ByteWrite(dat[i]);
  190.         }
  191.         DS1302_CE = 0;
  192. }

  193. void  DS1302BurstRead(unsigned char *dat)
  194. {
  195.         unsigned char i;

  196.         DS1302_CE = 1;
  197.         DS1302ByteWrite(0xBF);
  198.         for(i=0; i<8; i++)
  199.         {
  200.                 dat[i] = DS1302ByteRead();
  201.         }
  202.         DS1302_CE = 0;
  203. }
  204. /* DS1302初始化,掉電則重新設置初試時間*/
  205. void InitDS1302()
  206. {
  207.     unsigned char dat;
  208.     unsigned char code InitTime[] = {0x00,0x30,0x00, 0x16, 0x05, 0x04, 0x19};        //2019年5月16日 星期四12:30:00
  209.    
  210.     DS1302_CE = 0;
  211.     DS1302_CK = 0;
  212.     dat = DS1302SingleRead(0);
  213.     if ((dat & 0x80) != 0)      //秒寄存器最高位CH值判斷DS1302是否已停止
  214.     {
  215.         DS1302SingleWrite(7, 0x00);  //撤銷寫保護以允許寫入數據
  216.         DS1302BurstWrite(InitTime);  //設置DS1302為默認的初始時間
  217.     }
  218. }
  219. /* 配置并啟動T0,ms-T0定時時間 */
  220. void ConfigTimer0(unsigned int ms)
  221. {
  222.     unsigned long tmp;  //臨時變量
  223.    
  224.     tmp = 11059200 / 12;
  225.     tmp = (tmp * ms) /1000;
  226.     tmp = 65536 - tmp;
  227.     tmp = tmp + 12;           //補償中斷響應延時造成的誤差
  228.     T0RH = (unsigned char)(tmp>>8);
  229.     T0RL = (unsigned char)tmp;
  230.     TMOD &= 0xF0;   //清零T0的控制位
  231.     TMOD |= 0x01;   
  232.     TH0 = T0RH;
  233.     TL0 = T0RL;
  234.     ET0 = 1;
  235.     TR0 = 1;   
  236. }
  237. /* T0中斷服務函數,200ms定時*/
  238. void InterruptTimer0() interrupt 1
  239. {
  240.     static unsigned char tmr200ms = 0;
  241.    
  242.     TH0 = T0RH;  //重新加載重載值
  243.     TL0 = T0RL;
  244.     tmr200ms++;
  245.     if (tmr200ms >= 200)  //定時200ms
  246.     {
  247.         tmr200ms = 0;
  248.         flag200ms = 1;
  249.     }
  250. }
復制代碼



回復

使用道具 舉報

ID:149451 發表于 2019-5-18 23:21 | 顯示全部樓層
仿真了下,挺好的,不閃呀。掉電閃頻檢查下硬件、電源
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩一区欧美一区 | 毛片免费在线 | 欧美综合一区二区三区 | 亚洲国产精品久久久久 | 黄频免费 | 最新日韩在线视频 | 日韩一区二区av | 欧美亚洲另类在线 | 国产精品久久久久久亚洲调教 | av片网| 日本精a在线观看 | 日韩成人在线视频 | 免费精品| 日韩在线欧美 | 亚洲成人国产精品 | 特黄av| 国产99视频精品免视看9 | www.788.com色淫免费| 91亚洲一区 | 日韩欧美一二三区 | 中文字幕av一区二区三区 | 99久久精品国产一区二区三区 | 玩丰满女领导对白露脸hd | 色资源在线| av片在线观看网站 | 国产精品电影在线观看 | 99精品一区二区三区 | 国产精品爱久久久久久久 | 91在线视频免费观看 | 成人动漫视频网站 | 亚洲一区二区免费视频 | 亚洲精品自在在线观看 | 国产97碰免费视频 | 成人在线免费网站 | av在线免费网 | 91大神在线资源观看无广告 | 久久国产亚洲 | 日韩蜜桃视频 | 日韩欧美在 | 午夜在线 | 久久网国产 |