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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機+74HC595驅動8位數碼管顯示異常

[復制鏈接]
跳轉到指定樓層
樓主
74HC595驅動8位數碼管顯示異常問題:
1. 用定時器0計時模擬時鐘顯示正常;
2. 讀取DS3231時鐘芯片的數據就顯示異常,前面7位亮度低,第8位亮度高,數字變化看不清楚,具體見異常顯示圖片。
壓縮包里面有所有的工程資料
請論壇大師看看怎么解決這個問題,謝謝。

單片機源程序如下:
  1. //74HC595驅動8位數碼管
  2. //#include <reg52.h>
  3. #include <STC8G.h>

  4. #include <intrins.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int


  7. uchar code Table[] =
  8. { // 0         1          2           3        4         5          6           7        8         9          A           b        C    d          E    不顯    -
  9.         0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0xFF,0xbf
  10. };        //共陽段碼表
  11. //-----------------------------------------------------------------------------

  12. sbit SER = P3^7;        //串行數據輸入端
  13. sbit STCP = P3^6;        //時鐘脈沖信號——上升沿有效 存儲寄存器時鐘輸入端,并行輸出
  14. sbit SHCP = P3^5;        //輸入信號————上升沿有效 移位寄存器時鐘輸入端

  15. sbit key1 = P3^0;        //選擇鍵
  16. sbit key2 = P3^1;        //加鍵
  17. sbit key3 = P3^2;        //減鍵

  18. char shi=12,fen=59,miao=30;
  19. //char shi,fen,miao;

  20. uchar shan,shan1,A,K,C,D,E,F;
  21. uchar knum;                //選擇鍵計數變量
  22. uint keycont1,keycont2,keycont3;//消抖計時變量
  23. bit lock1,lock2,lock3;//按鍵自鎖標志

  24. bit key3_shotr_flag;
  25. bit        ack;                //應答標志位
  26. uchar key3_cnt;//按鍵3按下次數記錄
  27. uint key3_sj_time;//按鍵3雙擊時間變量

  28. uchar key_num;//按鍵觸發編號變量
  29. uchar hour,minute,second,year,month,day,date,week;
  30. #define const_key_time  20    //按鍵去抖動延時的時間
  31. //#define const_key_time2  20    //按鍵去抖動延時的時間
  32. //#define const_key_time3  20    //按鍵去抖動延時的時間

  33. #define const_key_long_time  500    //按鍵去抖動延時的時間
  34. #define const_key_lj_time  400    //按鍵去抖動延時的時間
  35. #define key3_sj_cnt  250    //按鍵去抖動延時的時間


  36. void TimerInit();
  37. void KeyScan();        //按鍵掃描
  38. void key_service();//按鍵服務程序
  39. void Display (uchar shi10,uchar shi,uchar fen10,uchar fen,uchar miao10,uchar miao);        // 數碼管顯示
  40. void SMG_Int(uchar Dat);                // 數碼管單字節串行移位函數
  41. ///////////////////////////////////

  42. // ------------------------------------------------------------
  43. // IO口模擬I2C通信

  44. // ------------------------------------------------------------
  45. sbit SCL=P3^4; //串行時鐘
  46. sbit SDA=P3^3; //串行數據

  47. /********************************************************************************************************
  48. **         DS3231常數定義
  49. ********************************************************************************************************/

  50. #define DS3231_WriteAddress 0xD0    //器件寫地址
  51. #define DS3231_ReadAddress  0xD1    //器件讀地址
  52. #define DS3231_SECOND       0x00    //秒
  53. #define DS3231_MINUTE       0x01    //分
  54. #define DS3231_HOUR         0x02    //時
  55. #define DS3231_WEEK         0x03    //星期
  56. #define DS3231_DAY          0x04    //日
  57. #define DS3231_MONTH        0x05    //月
  58. #define DS3231_YEAR         0x06    //年

  59. #define DS3231_TEMPERATUREH 0x11    //溫度寄存器高字節(8位)        整數部分
  60. #define DS3231_TEMPERATUREL 0x12    //溫度寄存器低字節(低2位) 小數部分



  61. #define NACK    1
  62. #define ACK     0         
  63. //////////////////

  64. void Delay5US()                //@11.0592MHz         STC Y6指令
  65. {
  66.         unsigned char i;

  67.         _nop_();
  68.         i = 16;
  69.         while (--i);
  70. }

  71. void delay(uint x)
  72. {
  73.         uint y,z;
  74.         for(y=0; y<x; y--)
  75.                 for(z=0; z<930; z--);

  76. }

  77. /**********************************************
  78. //IIC Start
  79. **********************************************/

  80. void IIC_Start()
  81. {
  82.    SCL = 1;               
  83.    SDA = 1;
  84.    SDA = 0;
  85.    SCL = 0;
  86. }

  87. /**********************************************
  88. //IIC Stop
  89. **********************************************/

  90. void IIC_Stop()
  91. {
  92.    SCL = 0;
  93.    SDA = 0;
  94.    SCL = 1;
  95.    SDA = 1;
  96. }

  97. /********************************************************************************************************
  98. **         3231
  99. ********************************************************************************************************/


  100. uchar        BCD2HEX(uchar val)//轉10進制
  101. {
  102.         return        ((val>>4)*10)+(val&0x0f);
  103. }

  104. uchar        HEX2BCD(uchar val) //轉16進制
  105. {
  106.         return        (((val%100)/10)<<4)|(val%10);
  107. }


  108. void SendByte(uchar c)
  109. {
  110.     uchar BitCnt;
  111.    
  112.     for(BitCnt=0;BitCnt<8;BitCnt++)         //要傳送的數據長度為8位
  113.     {
  114.         if((c<<BitCnt)&0x80)
  115.             SDA=1;                          //判斷發送位
  116.         else
  117.             SDA=0;     
  118.         SCL=1;                            //置時鐘線為高,通知被控器開始接收數據位
  119.         Delay5US();                       //保證時鐘高電平周期大于4μs   
  120.         SCL=0;
  121.     }
  122.     SDA=1;                                  //8位發送完后釋放數據線,準備接收應答位
  123.     SCL=1;
  124.     Delay5US();
  125.     if(SDA==1)
  126.         ack=0;   
  127.     else
  128.         ack=1;                              //判斷是否接收到應答信號
  129.     SCL=0;
  130.     Delay5US();
  131. }           

  132. uchar RcvByte()
  133. {
  134.    uchar retc;
  135.    uchar BitCnt;

  136.    retc=0;
  137.    SDA=1;                           //置數據線為輸入方式
  138.    for(BitCnt=0;BitCnt<8;BitCnt++)
  139.    {
  140.         SCL=0;                      //置時鐘線為低,準備接收數據位      
  141.         Delay5US();                 //時鐘低電平周期大于4.7μs                       
  142.         SCL=1;                      //置時鐘線為高使數據線上數據有效
  143.         Delay5US();
  144.         retc=retc<<1;
  145.         if(SDA==1)
  146.             retc=retc+1;            //讀數據位,接收的數據位放入retc中
  147.         Delay5US();
  148.    }
  149.    SCL=0;
  150.    return(retc);
  151. }                           

  152. void Ack_I2C(bit a)
  153. {
  154.         SDA        =        a;  
  155.     SCL=1;                     
  156.     Delay5US();             //時鐘低電平周期大于4us   
  157.     SCL=0;                  //清時鐘線,鉗住I2C總線以便繼續接收
  158.     Delay5US();   
  159. }                                            

  160. uchar write_byte(uchar addr, uchar write_data)
  161. {
  162.     IIC_Start();
  163.     SendByte(DS3231_WriteAddress);
  164.     if (ack == 0)
  165.         return 0;
  166.    
  167.     SendByte(addr);   
  168.     if (ack == 0)
  169.         return 0;
  170.    
  171.     SendByte(write_data);
  172.     if (ack == 0)
  173.         return 0;
  174.    
  175.     IIC_Stop();
  176.     Delay5US();      
  177.     Delay5US();      
  178.     return 1;
  179. }                                          

  180. uchar read_current()
  181. {
  182.     uchar read_data;
  183.     IIC_Start();
  184.     SendByte(DS3231_ReadAddress);
  185.     if(ack==0)
  186.         return(0);              
  187.     read_data = RcvByte();
  188.     Ack_I2C(1);
  189.     IIC_Stop();
  190.     return read_data;
  191. }                                                

  192. uchar read_random(uchar random_addr)
  193. {
  194.     uchar Tmp;
  195.         IIC_Start();
  196.     SendByte(DS3231_WriteAddress);
  197.     if(ack==0)
  198.         return(0);            
  199.     SendByte(random_addr);
  200.     if(ack==0)
  201.         return(0);
  202.         Tmp=read_current();
  203.         if(random_addr==DS3231_HOUR)
  204.                 Tmp&=0x3f;
  205.                                             
  206.     return(BCD2HEX(Tmp));//都轉10進制輸出
  207. }


  208. void KeyScan()           //按鍵程序放在2ms定時器中斷里面掃描
  209. {
  210.         if(key1)
  211.         {
  212.                 keycont1=0;
  213.                 lock1=0;        
  214.         }
  215.         else if(lock1==0)//按鍵按下
  216.         {
  217.                 keycont1++;
  218.                 if(keycont1>const_key_time)
  219.                 {
  220.                         keycont1=0;
  221.                         lock1=1;  //按鍵鎖置1,避免一直觸發
  222.                         key_num=1; //觸發1號鍵
  223.                 }        
  224.         }
  225. /////////////////////////
  226.         if(key2)
  227.         {
  228.                 keycont2=0;
  229.                 lock2=0;        
  230.         }
  231.         else if(lock2==0)
  232.         {
  233.                 keycont2++;
  234.                 if(keycont2>const_key_time)
  235.                 {
  236.                         keycont2=0;
  237.                         lock2=1;
  238.                         key_num=2; //觸發2號鍵
  239.                 }        
  240.         }
  241.         else if(keycont2<const_key_long_time)//長按 連減
  242.         {
  243.                 keycont2++;
  244.                 if(keycont2==const_key_long_time)
  245.                 {
  246.                         keycont2=const_key_lj_time;//連加速度設置
  247.                         key_num=2;         //觸發2號鍵
  248.                 }        
  249.          }
  250. /////////////////////////
  251.         if(key3)        //按鍵沒有按下
  252.         {
  253.                 keycont3=0;
  254.                 lock3=0;
  255.                 if(key3_cnt>0) //按鍵按下次數key3_cnt>0說明按鍵按下過
  256.                 {
  257.                         key3_sj_time++;// 計時變量自加
  258.                         if(key3_sj_time>key3_sj_cnt)//計時大于500ms            2ms中斷
  259.                         {
  260.                                 key3_sj_time=0;//雙擊計時變量清零
  261.                                 key3_cnt=0;//按鍵按下次數清零
  262.                         }                                       
  263.                 }
  264.                
  265.                 if(key3_shotr_flag)        //松手后觸發3號按鍵的單擊短按
  266.                 {
  267.                         key_num=3; //觸發3號鍵
  268.                         key3_shotr_flag=0;               
  269.                 }        
  270.         }
  271.         else if(lock3==0) //按鍵按下
  272.         {
  273.                 keycont3++;
  274.                 if(keycont3>const_key_time)
  275.                 {
  276.                         keycont3=0;
  277.                         key3_cnt++;//k3按鍵次數
  278.                         lock3=1;
  279.                         if(key3_cnt==1)//單擊
  280.                         {
  281.                         //        key_num=3; //觸發3號鍵
  282.                                 key3_shotr_flag=1;
  283.                         }

  284.                         if(key3_cnt==2 && knum==0) //雙擊
  285.                         {
  286.                                 miao = 30;//把秒寫30                        
  287.                         }
  288.                         if(key3_cnt==3 && knum==0) //三擊
  289.                         {
  290.                                 fen = 30;//把分寫30                        
  291.                         }

  292.                 }
  293.         }
  294.         else if(keycont3<const_key_long_time)//長按 連減
  295.         {
  296.                 keycont3++;
  297.                 if(keycont3==const_key_long_time)
  298.                 {
  299.                         keycont3=const_key_lj_time;//連減速度設置
  300.                         key_num=3; //觸發3號鍵
  301.                 }               
  302.         }
  303. }

  304. void key_service() // 按鍵服務的應用程序
  305. {
  306.         switch(key_num)
  307.         {
  308.                 case 1:        knum++;
  309.                                 if(knum==4)
  310.                                         knum=0;
  311.                             key_num=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發。!
  312.                                 break;

  313.                 case 2: if(knum==1){shi++; if(shi>23)shi=0;}
  314.                             else if (knum==2){fen++; if(fen>59)fen=0;}
  315.                             else if (knum==3){miao++; if(miao>59)miao=0;}
  316.                             key_num=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發。!
  317.                                 break;
  318.                         
  319.                 case 3: if(knum==1){shi--; if(shi<0)shi=23;}
  320.                                 else if (knum==2){fen--; if(fen<0)fen=59;}
  321.                                 else if (knum==3){miao--; if(miao<0)miao=59;}
  322.                                 key_num=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發。!
  323.                                 break;

  324.                 default: break;
  325.         }
  326. }

  327. void out595()
  328. {
  329.         STCP = 0;         //數據并行輸出,(借助上升沿)
  330.         _nop_();
  331.         _nop_();
  332.         STCP = 1;
  333. }


  334. void Display (uchar shi10,uchar shi,uchar fen10,uchar fen,uchar miao10,uchar miao)
  335. {
  336.         uchar i;

  337.         //顯示第1位        小時10位
  338.         if(knum==1)                //
  339.         {
  340.                 if(shan>125)         //        調時數碼管閃爍
  341.                 i = Table[15];
  342.                 else
  343.                 i = Table[shi10];
  344.         
  345.                 SMG_Int(i);        //段碼               
  346.                 SMG_Int(0x01);//位碼               
  347.         
  348.                 out595();        
  349.                 //顯示第2位        小時個位
  350.                 if(shan>125)         //
  351.                 i = Table[15];          //黑屏
  352.                 else
  353.                 i = Table[shi];
  354.         
  355.                 SMG_Int(i);               
  356.                 SMG_Int(0x02);               
  357.         
  358.                 out595();        
  359.         }
  360.         else
  361.         {
  362.                 i = Table[shi10];
  363.         
  364.                 SMG_Int(i);                        
  365.                 SMG_Int(0x01);               
  366.         
  367.                 out595();        
  368.         
  369.                 //顯示第2位        小時個位
  370.                 i = Table[shi];
  371.         
  372.                 SMG_Int(i);               
  373.                 SMG_Int(0x02);               
  374.         
  375.                 out595();        
  376.         }
  377.         //顯示第3位        -
  378. //        if(shan<125)         
  379. //        i = Table[15];
  380. //        else
  381.         i = Table[16];         //"-" 閃爍
  382.         SMG_Int(i);                        
  383.         SMG_Int(0x04);        

  384.         out595();        

  385.         //顯示第4位        分鐘10位
  386.         if(knum==2)
  387.         {
  388.                 if(shan>125)         //
  389.                 i = Table[15];
  390.                 else
  391.                 i = Table[fen10];        
  392.                 SMG_Int(i);                        
  393.                 SMG_Int(0x08);               
  394.         
  395.                 out595();        
  396.         
  397.                 //顯示第5位        分鐘個位
  398.                 if(shan>125)         //
  399.                 i = Table[15];
  400.                 else
  401.                 i = Table[fen];
  402.         
  403.                 SMG_Int(i);                        
  404.                 SMG_Int(0x10);        
  405.         
  406.                 out595();        
  407.         }
  408.         else
  409.         {
  410.                 i = Table[fen10];
  411.         
  412.                 SMG_Int(i);                        
  413.                 SMG_Int(0x08);               
  414.         
  415.                 out595();        
  416.         
  417.                 //顯示第5位        分鐘個位
  418.                 i = Table[fen];
  419.         
  420.                 SMG_Int(i);                        
  421.                 SMG_Int(0x10);        
  422.         
  423.                 out595();        
  424.         }
  425.         //顯示第6位        -
  426. //        if(shan<125)           //"-" 閃爍
  427. //        i = Table[15];
  428. //        else
  429.         i = Table[16];         //"-"

  430.         SMG_Int(i);                        
  431.         SMG_Int(0x20);        

  432.         out595();        

  433.         if(knum==3)
  434.         {
  435.                 //顯示第7位        秒10位
  436.                 if(shan>125)         //
  437.                 i = Table[15];
  438.                 else
  439.                 i = Table[miao10];
  440.         
  441.                 SMG_Int(i);                        
  442.                 SMG_Int(0x40);        
  443.         
  444.                 out595();        
  445.         
  446.                 //顯示第8位        秒個位
  447.                 if(shan>125)         //
  448.                 i = Table[15];
  449.                 else
  450.                 i = Table[miao];
  451.         
  452.                 SMG_Int(i);               
  453.                 SMG_Int(0x80);        
  454.         
  455.                 out595();        
  456.         }
  457.         else
  458.         {
  459.                 //顯示第7位        秒10位
  460.                 i = Table[miao10];
  461.         
  462.                 SMG_Int(i);                        
  463.                 SMG_Int(0x40);        
  464.         
  465.                 out595();        
  466.         
  467.                 //顯示第8位        秒個位
  468.                 i = Table[miao];
  469.         
  470.                 SMG_Int(i);               
  471.                 SMG_Int(0x80);        
  472.         
  473.                 out595();        
  474.         }
  475. }

  476. void SMG_Int(uchar Dat)         //通過8次循環將8位數據移入74HC595
  477. {
  478.         uchar i;
  479.         for(i=8;i>=1;i--)
  480.         {
  481.                 if (Dat & 0x80) //如果數據的最高位是1
  482.                 {
  483.                         SER = 1;        //串行數據輸入端置1
  484.                 }
  485.                
  486.                 else
  487.                 {
  488.                         SER = 0;  //否則串行數據輸入端清零
  489.                 }
  490.                 Dat <<= 1;          //數據左移1位,分8次把8位數據移入74HC595
  491.                 SHCP = 0;  //SH引腳的上升沿把數據送入寄存器
  492.                 _nop_();
  493.                 _nop_();
  494.                 SHCP = 1;
  495.         }
  496. }

  497. void TimerInit()         //定時器0初始化
  498. {
  499.         TMOD = 0x01;
  500.         TH0 = (65536-2000)/256;        //2ms初值
  501.         TL0 = (65536-2000)%256;
  502.         EA = 1;
  503.         ET0 = 1;
  504.         TR0 = 1;

  505. }

  506. void main ()
  507. {
  508.         TimerInit();
  509. //        PWM_Init();
  510.         P0M0 = 0x00;
  511.     P0M1 = 0x00;
  512.     P1M0 = 0x00;
  513.     P1M1 = 0x00;//
  514.     P2M0 = 0x00;
  515.     P2M1 = 0x00;
  516.     P3M0 = 0x00;
  517.     P3M1 = 0x00;
  518.     P4M0 = 0x00;
  519.     P4M1 = 0x00;
  520.     P5M0 = 0x00;
  521.     P5M1 = 0x00;
  522.         while(1)
  523.         {
  524. //                shi = read_random(DS3231_HOUR);
  525. //                fen = read_random(DS3231_MINUTE) ;
  526. //                miao = read_random(DS3231_SECOND);
  527. //                A=shi/10;
  528. //                K=shi%10;
  529. //                C=fen/10;
  530. //                D=fen%10;
  531. //                E=miao/10;
  532. //                F=miao%10;

  533.                 Display (A,K,C,D,E,F);
  534.                 key_service();// 按鍵服務的應用程序
  535.         }
  536. }

  537. void Timer0() interrupt 1
  538. {
  539.         static uint cnt;
  540.         
  541.         TH0 = (65536-2000)/256;
  542.         TL0 = (65536-2000)%256;
  543. //        shan1++;
  544. //        if(shan1==250)
  545. //                shan1=0;
  546.         

  547.         shan++;
  548.         if(shan==250)
  549.                 shan=0;

  550.         if(knum==0)
  551.         {
  552.                 cnt++;
  553.                 if(cnt==500)
  554.                 {
  555.                         cnt = 0;
  556.                         miao++;
  557.                         if(miao == 60)
  558.                         {
  559.                                 miao = 0;
  560.                                 fen++;
  561.                                 if(fen==60)
  562.                                 {
  563.                                         fen = 0;
  564.                                         shi++;
  565.                                         if(shi==24)
  566.                                         {
  567.                                                 shi=0;
  568.                                         }
  569.                                 }
  570.                         }
  571.                 }
  572.         }
  573.         A=shi/10;
  574.         K=shi%10;
  575.         C=fen/10;
  576.         D=fen%10;
  577.         E=miao/10;
  578.         F=miao%10;
  579.         
  580.         KeyScan();
  581. }
復制代碼

595數碼管時鐘資料.zip

250.9 KB, 下載次數: 7

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:69038 發表于 2024-4-19 11:46 | 只看該作者

很懷疑你中斷程序會忙的過來不?定時器中斷里,要完成的工作是不是有點多,又是計時又是分配緩存又是調用萬里長城般的鍵掃的代碼?中斷不要放太多代碼,最完美的就是進中斷后處理一些標志位就退出來,那些冗長的代碼讓主程序去完成。
595的顯示代碼再簡單不過了,咋就寫成這樣亂了?不如開個2ms的中斷,每進中斷,位選+1,8位數碼管16ms一輪顯,視覺上完全不會閃的。用595驅動LED出現亮度不均,無非兩種情況,其一是電流不足,其二是顯示時長不相等。。
顯示代要改改,值未改,就沒必要重新加載一次到緩存。
.
.
.
個人意見,僅供參考。。。
回復

使用道具 舉報

板凳
ID:1109793 發表于 2024-4-19 12:50 | 只看該作者
立創EDA的這些零件都是自帶的還是你畫 的?
回復

使用道具 舉報

地板
ID:140489 發表于 2024-4-19 16:23 | 只看該作者
xiaobendan001 發表于 2024-4-19 12:50
立創EDA的這些零件都是自帶的還是你畫 的?

自己畫的有一些,系統里面有的就不要自己畫
回復

使用道具 舉報

5#
ID:1099129 發表于 2024-4-19 17:08 | 只看該作者
第一檢查電流
第二顯示延時 驅動595彈數據時可以彈兩次或者三次,或者加延時2~5us加強顯示時間
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲国产中文字幕 | 欧美自拍第一页 | 免费看黄视频网站 | 男人的天堂亚洲 | 久草免费在线视频 | 亚洲狠狠爱 | 成人高清网站 | 久久精彩视频 | 日韩成人免费av | 亚洲国产区| 91精品久久久久久久久中文字幕 | 精品视频在线免费观看 | 亚洲精品在线91 | 精品综合网 | 一区二区免费 | 日本精品视频在线观看 | 久久国产麻豆 | 亚洲精品电影网在线观看 | 中文字幕一区二区在线观看 | 久久久久亚洲av毛片大全 | 成人在线免费视频 | 免费午夜电影 | 国产日韩久久 | av福利网站 | 欧美日韩一区二区在线播放 | 久干网| 欧美亚洲在线视频 | 午夜在线观看免费 | 国产精品黄色 | 欧美日一区 | 久久精品国产亚洲 | 看片91 | 毛片链接 | 免费亚洲一区二区 | 国产综合视频 | 国产一区二区成人 | 人人射人人 | 精品国产乱码久久久久久丨区2区 | 一区二区在线不卡 | a欧美| 久久精品中文字幕 |