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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機0.8寸數碼管時鐘完整資料 程序+Gerber PCB文件

  [復制鏈接]
跳轉到指定樓層
樓主
/*
項目名稱:0.8寸4位共陽數碼管時鐘
1.5個PNP三極管接在共陽極驅動數碼管,這個數碼管小數點都有,冒號是單獨兩個LED
2.設置方法:按k1鍵設置狀態(小時位數碼管閃爍),按K2鍵++,按K3鍵--,長按連加連減;
按K1鍵第二次,分鐘位數碼管閃爍,按K2鍵++,按K3鍵--,長按連加連減;
按K1鍵第三次,退出設置狀態,回到正常走時界面。
3. P2.0-P2.4位驅動口,P1口為段驅動口;

4. 單片機=STC8H1K16(LQFP32封裝) @11.0592MHz   時鐘芯片=DS3231MZ(SOP-8封裝)
2023/12/7 測試通過

測試中的問題:開始數碼管有鬼影,以為程序有問題(這個程序以前驅動0.56寸數碼管是沒問題的),
單片機內部4.1K上拉打開不行,位驅動口設置成推挽都不行;單獨驅動一個LED燈,LED只有亮暗變化,
不能完全關斷;后來在PNP三極管基極加5.1K上拉電阻,三極管才能完全關斷;上拉電阻加在單片機的IO端
都不行;
以前同型號的單片機不加這個上拉電阻是可以的;

單片機都是在某一個寶買的(兩次不是在一家買的),這次買的有這個問題,以前的沒有。
*/
程序只寫了時鐘的,溫度,蜂鳴器沒寫;
附件里面有嘉立創EDA軟件畫的板子的gerber文件,可以直接在嘉立創免費打板,有興趣的可以制作看看有沒有我制作中出現的問題,制作時,Q1不用,R5用跳線短接。

制作出來的實物圖如下:


電路原理圖如下:

附件是完整資料
  1. /*
  2. 項目名稱:0.8寸4位共陽數碼管時鐘
  3. 1.5個PNP三極管接在共陽極驅動數碼管,這個數碼管小數點都有,冒號是單獨兩個LED
  4. 2.設置方法:按k1鍵設置狀態(小時位數碼管閃爍),按K2鍵++,按K3鍵--,長按連加連減;
  5. 按K1鍵第二次,分鐘位數碼管閃爍,按K2鍵++,按K3鍵--,長按連加連減;
  6. 按K1鍵第三次,退出設置狀態,回到正常走時界面。
  7. 3. P2.0-P2.4位驅動口,P1口為段驅動口;

  8. 4. 單片機=STC8H1K16(LQFP32封裝) @11.0592MHz   時鐘芯片=DS3231MZ(SOP-8封裝)
  9. 2023/12/7 測試通過

  10. 測試中的問題:開始數碼管有鬼影,以為程序有問題(這個程序以前驅動0.56寸數碼管是沒問題的),
  11. 單片機內部4.1K上拉打開不行,位驅動口設置成推挽都不行;單獨驅動一個LED燈,LED只有亮暗變化,
  12. 不能完全關斷;后來在PNP三極管基極加5.1K上拉電阻,三極管才能完全關斷;上拉電阻加在單片機的IO端
  13. 都不行;
  14. 以前同型號的單片機不加這個上拉電阻是可以的;

  15. 單片機都是在某一個寶買的(兩次不是在一家買的),這次買的有這個問題,以前的沒有。
  16. */
  17. #include <STC8H.H>
  18. #include <intrins.h>

  19. #define uchar unsigned char
  20. #define uint unsigned int


  21. //typedef     unsigned char   u8;
  22. //typedef     unsigned int    u16;
  23. //typedef     unsigned long   u32;

  24. sbit k1=P0^0;//        按鍵1 設置 +
  25. sbit k2=P2^7;//        按鍵2  -
  26. sbit k3=P3^7;//        
  27. sbit k4=P2^5;
  28. sbit out = P3^2;          //輸出端口
  29. sbit w1 = P2^0;          //設置位驅動口
  30. sbit w2 = P2^1;
  31. sbit w3 = P2^2;
  32. sbit w4 = P2^3;

  33. sbit w5 = P2^4;        //冒號控制

  34. sbit BZ = P0^3;//蜂鳴器控制口
  35. uint count,cont1,cont2,cont3;
  36. uint fen,fen_temp;
  37. uchar fen_L,fen_M,miao,num,num2;
  38. uchar Ledcount;
  39. uchar num;
  40. uchar k1_lock,k2_lock,k3_lock;//按鍵鎖
  41. uchar knum;
  42. uint shan;//秒點閃爍 計時變量

  43. uint k1_time_count;          //K1消抖計數
  44. uint k2_time_count;          //K2消抖計數
  45. uint k3_time_count;          //K2消抖計數

  46. bit flag;        //計時啟動標志
  47. bit flag1;        //按鍵消抖計數標志
  48. bit flag2;        //按鍵消抖計數標志
  49. bit save_flag;//數據保存標志
  50. bit save_flag1;//數據保存標志
  51. bit set_flag=0; //設置標志
  52. bit fm_flag;//蜂鳴器

  53. bit flag3;

  54. uchar hour,minute,second,year,month,day,date,week;
  55. uint TH3231;
  56. bit        ack;                //應答標志位

  57. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x46,0xbf,0x8e};//共陽段碼 (0--9、黑屏,C,-,F)
  58. uchar LedBuff[]={0xff,0xff,0xff,0xff};

  59. // ------------------------------------------------------------
  60. // IO口模擬I2C通信

  61. // ------------------------------------------------------------
  62. sbit SCL=P3^5; //串行時鐘
  63. sbit SDA=P3^4; //串行數據

  64. /********************************************************************************************************
  65. **         DS3231常數定義
  66. ********************************************************************************************************/
  67. #define DS3231_WriteAddress 0xD0    //器件寫地址
  68. #define DS3231_ReadAddress  0xD1    //器件讀地址
  69. #define DS3231_SECOND       0x00    //秒
  70. #define DS3231_MINUTE       0x01    //分
  71. #define DS3231_HOUR         0x02    //時
  72. #define DS3231_WEEK         0x03    //星期
  73. #define DS3231_DAY          0x04    //日
  74. #define DS3231_MONTH        0x05    //月
  75. #define DS3231_YEAR         0x06    //年

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



  78. #define NACK    1
  79. #define ACK     0
  80. /////////////////

  81. void        Delay5US()           //@12.000MHz           延時5us
  82. {
  83.    _nop_(); _nop_();        _nop_();_nop_();         _nop_();_nop_();//STC Y6指令 1T單片機用6個nop,12T用1個nop
  84. }

  85. void delay(uint x)
  86. {
  87.         uint y,z;
  88.         for(y=0; y<x; y--)
  89.                 for(z=0; z<1200; z--);

  90. }


  91. /**********************************************
  92. //IIC Start
  93. **********************************************/
  94. void IIC_Start()
  95. {
  96.    SCL = 1;               
  97.    SDA = 1;
  98.    SDA = 0;
  99.    SCL = 0;
  100. }

  101. /**********************************************
  102. //IIC Stop
  103. **********************************************/
  104. void IIC_Stop()
  105. {
  106.    SCL = 0;
  107.    SDA = 0;
  108.    SCL = 1;
  109.    SDA = 1;
  110. }

  111. /********************************************************************************************************
  112. **         3231
  113. ********************************************************************************************************/


  114. uchar        BCD2HEX(uchar val)//轉10進制
  115. {
  116.         return        ((val>>4)*10)+(val&0x0f);
  117. }

  118. uchar        HEX2BCD(uchar val) //轉16進制
  119. {
  120.         return        (((val%100)/10)<<4)|(val%10);
  121. }


  122. void SendByte(uchar c)
  123. {
  124.     uchar BitCnt;
  125.    
  126.     for(BitCnt=0;BitCnt<8;BitCnt++)         //要傳送的數據長度為8位
  127.     {
  128.         if((c<<BitCnt)&0x80)
  129.             SDA=1;                          //判斷發送位
  130.         else
  131.             SDA=0;     
  132.         SCL=1;                            //置時鐘線為高,通知被控器開始接收數據位
  133.         Delay5US();                       //保證時鐘高電平周期大于4μs   
  134.         SCL=0;
  135.     }
  136.     SDA=1;                                  //8位發送完后釋放數據線,準備接收應答位
  137.     SCL=1;
  138.     Delay5US();
  139.     if(SDA==1)
  140.         ack=0;   
  141.     else
  142.         ack=1;                              //判斷是否接收到應答信號
  143.     SCL=0;
  144.     Delay5US();
  145. }           

  146. uchar RcvByte()
  147. {
  148.    uchar retc;
  149.    uchar BitCnt;

  150.    retc=0;
  151.    SDA=1;                           //置數據線為輸入方式
  152.    for(BitCnt=0;BitCnt<8;BitCnt++)
  153.    {
  154.         SCL=0;                      //置時鐘線為低,準備接收數據位      
  155.         Delay5US();                 //時鐘低電平周期大于4.7μs                       
  156.         SCL=1;                      //置時鐘線為高使數據線上數據有效
  157.         Delay5US();
  158.         retc=retc<<1;
  159.         if(SDA==1)
  160.             retc=retc+1;            //讀數據位,接收的數據位放入retc中
  161.         Delay5US();
  162.    }
  163.    SCL=0;
  164.    return(retc);
  165. }                           

  166. void Ack_I2C(bit a)
  167. {
  168.         SDA        =        a;  
  169.     SCL=1;                     
  170.     Delay5US();             //時鐘低電平周期大于4us   
  171.     SCL=0;                  //清時鐘線,鉗住I2C總線以便繼續接收
  172.     Delay5US();   
  173. }                                            

  174. uchar write_byte(uchar addr, uchar write_data)
  175. {
  176.     IIC_Start();
  177.     SendByte(DS3231_WriteAddress);
  178.     if (ack == 0)
  179.         return 0;
  180.    
  181.     SendByte(addr);   
  182.     if (ack == 0)
  183.         return 0;
  184.    
  185.     SendByte(write_data);
  186.     if (ack == 0)
  187.         return 0;
  188.    
  189.     IIC_Stop();
  190.     Delay5US();      
  191.     Delay5US();      
  192.     return 1;
  193. }                                          

  194. uchar read_current()
  195. {
  196.     uchar read_data;
  197.     IIC_Start();
  198.     SendByte(DS3231_ReadAddress);
  199.     if(ack==0)
  200.         return(0);              
  201.     read_data = RcvByte();
  202.     Ack_I2C(1);
  203.     IIC_Stop();
  204.     return read_data;
  205. }                                                

  206. uchar read_random(uchar random_addr)
  207. {
  208.     uchar Tmp;
  209.         IIC_Start();
  210.     SendByte(DS3231_WriteAddress);
  211.     if(ack==0)
  212.         return(0);            
  213.     SendByte(random_addr);
  214.     if(ack==0)
  215.         return(0);
  216.         Tmp=read_current();
  217.         if(random_addr==DS3231_HOUR)
  218.                 Tmp&=0x3f;
  219.                                             
  220.     return(BCD2HEX(Tmp));//都轉10進制輸出
  221. }

  222. /***********************/
  223. uchar read_random1(uchar random_addr)  //這個是讀溫度函數
  224. {
  225.     uchar Tmp;
  226. //        write_byte(0x0e,0x20);//0x0e寄存器的CONV位置1開啟溫度轉換,要這句,溫度實時刷新,這句不要,溫度要64s才刷新1次
  227.                                                   //數碼管顯示不能要這句,否則溫度值小數部分亂跳
  228.         IIC_Start();
  229.     SendByte(DS3231_WriteAddress);
  230.     if(ack==0)
  231.         return(0);            
  232.     SendByte(random_addr);
  233.     if(ack==0)
  234.         return(0);
  235.         Tmp=read_current();
  236.         return Tmp;
  237. }                                 

  238. void ModifyTime(uchar address,uchar num)
  239. {
  240.     uchar temp=0;
  241.            if(address>6 && address <0) return;
  242.     temp=HEX2BCD(num);
  243.         write_byte(address,temp);
  244. }



  245. ////////////////

  246. void IapIdle()
  247. {
  248.     IAP_CONTR = 0;                              //關閉IAP功能
  249.     IAP_CMD = 0;                                //清除命令寄存器
  250.     IAP_TRIG = 0;                               //清除觸發寄存器
  251.     IAP_ADDRH = 0x80;                           //將地址設置到非IAP區域
  252.     IAP_ADDRL = 0;
  253. }

  254. char IapRead(int addr)
  255. {
  256.     char dat;

  257.     IAP_CONTR = 0x80;                           //使能IAP
  258.     IAP_TPS = 12;                               //設置等待參數12MHz
  259.     IAP_CMD = 1;                                //設置IAP讀命令
  260.     IAP_ADDRL = addr;                           //設置IAP低地址
  261.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  262.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  263.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  264.     _nop_();
  265.     dat = IAP_DATA;                             //讀IAP數據
  266.     IapIdle();                                  //關閉IAP功能

  267.     return dat;
  268. }

  269. void IapProgram(int addr, char dat)
  270. {
  271.     IAP_CONTR = 0x80;                           //使能IAP
  272.     IAP_TPS = 12;                               //設置等待參數12MHz
  273.     IAP_CMD = 2;                                //設置IAP寫命令
  274.     IAP_ADDRL = addr;                           //設置IAP低地址
  275.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  276.     IAP_DATA = dat;                             //寫IAP數據
  277.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  278.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  279.     _nop_();
  280.     IapIdle();                                  //關閉IAP功能
  281. }

  282. void IapErase(int addr)
  283. {
  284.     IAP_CONTR = 0x80;                           //使能IAP
  285.     IAP_TPS = 12;                               //設置等待參數12MHz
  286.     IAP_CMD = 3;                                //設置IAP擦除命令
  287.     IAP_ADDRL = addr;                           //設置IAP低地址
  288.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  289.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  290.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  291.     _nop_();                                    //
  292.     IapIdle();                                  //關閉IAP功能
  293. }
  294. ////////////////////
  295. void Timer0Init(void)                //2毫秒@11.0592MHz
  296. {
  297.         AUXR |= 0x80;                //定時器時鐘1T模式
  298.         TMOD &= 0xF0;                //設置定時器模式  16位自動重載
  299.         TL0 = 0x9A;                //設置定時初始值
  300.         TH0 = 0xA9;                //設置定時初始值
  301.         TF0 = 0;                //清除TF0標志
  302.         TR0 = 1;                //定時器0開始計時
  303.         EA = 1;                        //開總中斷
  304.         ET0 = 1;                //開T0中斷
  305. }


  306. //void Timer0Init(void)                //5毫秒@11.0592MHz
  307. //{
  308. //        AUXR |= 0x80;                //定時器時鐘1T模式
  309. //        TMOD &= 0xF0;                //設置定時器模式
  310. //        TL0 = 0x00;                //設置定時初始值
  311. //        TH0 = 0x28;                //設置定時初始值
  312. //        TF0 = 0;                //清除TF0標志
  313. //        TR0 = 1;                //定時器0開始計時
  314. //        EA = 1;                        //開總中斷
  315. //        ET0 = 1;                //開T0中斷
  316. //}
  317. /////////////////////////////
  318. void keyscan()
  319. {
  320.         uchar temp;
  321.         hour = read_random(DS3231_HOUR);
  322.         minute = read_random(DS3231_MINUTE) ;
  323.         second = read_random(DS3231_SECOND);

  324.         
  325.                 if(k1)        //
  326.                 {                                                //
  327.                         k1_time_count=0;
  328.                         k1_lock=0;
  329.                         flag1 = 0;
  330.                 }
  331.                 else if((k1_lock==0))
  332.                 {
  333.                         flag1 = 1; //按鍵按下 消抖計時標志置1 開始消抖計時
  334.                         if((k1_time_count==10))  //20微秒
  335.                         {
  336.                                 k1_time_count=0;
  337.                                 k1_lock=1;
  338.                                 knum++;
  339.                                 if(knum==3)
  340.                                 {
  341.                                         knum=0;
  342.                                         second=0;
  343.                                         write_byte(DS3231_SECOND, second); //秒寫0
  344.                                 }
  345.                         }
  346.                 }

  347. /////////////////////////////
  348.         if(knum==1)  //設置 狀態
  349.         {
  350.                 if(k2 ==1)                                   //++
  351.                 {
  352.                         k2_time_count=0;
  353.                         k2_lock=0;
  354.                         flag2 = 0;
  355.                 }
  356.                 else if(k2_lock==0)
  357.                 {
  358.                 //        flag = 0;
  359.                         flag2 = 1;
  360.                 //        save_flag = 1;
  361.                         if(k2_time_count==10)                //短按
  362.                         {
  363.                                 k2_time_count=0;
  364.                                 k2_lock=1;
  365.                                 hour++;
  366.                                 if(hour>23)
  367.                                         hour=0;
  368.                                 temp=HEX2BCD(hour);
  369.                                 write_byte(DS3231_HOUR, temp);
  370.                         }        
  371.                 }
  372.                 else if(k2_time_count==500)                 //長按
  373.                 {
  374.                    cont1=0; num=0;
  375.                    k1_time_count=450;
  376.                         hour++;
  377.                         if(hour>23)
  378.                                 hour=0;
  379.                         temp=HEX2BCD(hour);        //10進制轉16進制
  380.                         write_byte(DS3231_HOUR, temp);

  381.                 }
  382. //////////////////////////
  383.                 if(k3 == 1)                                   //--
  384.                 {
  385.                         k3_time_count=0;
  386.                         k3_lock=0;
  387.                         flag3 = 0;
  388.                 }
  389.                 else if(k3_lock==0)
  390.                 {
  391.                
  392.                         flag3 = 1;
  393.                         save_flag1 = 1;
  394.                         if(k3_time_count==10)                //短按
  395.                         {
  396.                                 cont1=0; num=0;
  397.                                 k3_time_count=0;
  398.                                 k3_lock=1;
  399.                                 hour--;
  400.                                 if(hour==255)
  401.                                         hour=23;
  402.                                 temp=HEX2BCD(hour);
  403.                                 write_byte(DS3231_HOUR, temp);

  404.                         }
  405.                                 
  406.                 }
  407.                 else if(k3_time_count==500)                 //長按
  408.                 {
  409.                    cont1=0; num=0;  
  410.                    k3_time_count=450;
  411.                                 hour--;
  412.                         if(hour==255)
  413.                                 hour=23;
  414.                         temp=HEX2BCD(hour);
  415.                         write_byte(DS3231_HOUR, temp);

  416.                 }
  417.         }
  418.   ////////////////////////////////
  419.         if(knum==2)
  420.         {
  421.                 if(k2 ==1)                                   //++
  422.                 {
  423.                         k2_time_count=0;
  424.                         k2_lock=0;
  425.                         flag2 = 0;
  426.                 }
  427.                 else if(k2_lock==0)
  428.                 {
  429.                 //        flag = 0;
  430.                         flag2 = 1;
  431.                 //        save_flag = 1;
  432.                         if(k2_time_count==10)                //短按
  433.                         {
  434.                                 k2_time_count=0;
  435.                                 k2_lock=1;
  436.                                 minute++;
  437.                                 if(minute>59)
  438.                                         minute=0;
  439.                                 temp=HEX2BCD(minute);
  440.                                 write_byte(DS3231_MINUTE, temp);
  441.                         }        
  442.                 }
  443.                 else if(k2_time_count==500)                 //長按
  444.                 {
  445.                    cont1=0; num=0;
  446.                    k1_time_count=450;
  447.                         minute++;
  448.                         if(minute>59)
  449.                                 minute=0;
  450.                         temp=HEX2BCD(minute);
  451.                         write_byte(DS3231_MINUTE, temp);

  452.                 }
  453. //////////////////////////
  454.                 if(k3 == 1)                                   //--
  455.                 {
  456.                         k3_time_count=0;
  457.                         k3_lock=0;
  458.                         flag3 = 0;
  459.                 }
  460.                 else if(k3_lock==0)
  461.                 {
  462.                
  463.                         flag3 = 1;
  464.                         save_flag1 = 1;
  465.                         if(k3_time_count==10)                //短按
  466.                         {
  467.                                 cont1=0; num=0;
  468.                                 k3_time_count=0;
  469.                                 k3_lock=1;
  470.                                 minute--;
  471.                                 if(minute==255)
  472.                                         minute=59;
  473.                                 temp=HEX2BCD(minute);
  474.                                 write_byte(DS3231_MINUTE, temp);
  475.                         }
  476.                                 
  477.                 }
  478.                 else if(k3_time_count==500)                 //長按
  479.                 {
  480.                    cont1=0; num=0;  
  481.                    k3_time_count=450;
  482.                                 minute--;
  483.                                 if(minute==255)
  484.                                         minute=59;
  485.                                 temp=HEX2BCD(minute);
  486.                                 write_byte(DS3231_MINUTE, temp);
  487.                 }
  488.         }
  489. }

  490. ///////////////////////////////
  491. void display_sf() //顯示 時分
  492. {
  493. //                        year = read_random(DS3231_YEAR);               
  494. //                    month = read_random(DS3231_MONTH);        
  495. //                    day = read_random(DS3231_DAY);        
  496. //                    week = read_random(DS3231_WEEK);
  497.         hour = read_random(DS3231_HOUR);
  498.         minute = read_random(DS3231_MINUTE) ;
  499.         second = read_random(DS3231_SECOND);
  500.         if(knum==0)
  501.         {
  502.                 LedBuff[0]= table[hour/10];
  503.                 LedBuff[1]= table[hour%10];
  504.                 LedBuff[2]= table[minute/10];
  505.                 LedBuff[3]= table[minute%10];
  506.         }
  507.         if(knum==1)
  508.         {
  509.                 if(shan>250)
  510.                 {
  511.                         LedBuff[0]= table[hour/10];
  512.                         LedBuff[1]= table[hour%10];
  513.                 }
  514.                 else
  515.                 {
  516.                         LedBuff[0]= table[10];
  517.                         LedBuff[1]= table[10];
  518.                
  519.                 }
  520.                 LedBuff[2]= table[minute/10];
  521.                 LedBuff[3]= table[minute%10];
  522.         }
  523.         if(knum==2)
  524.         {
  525.                
  526.                 LedBuff[0]= table[hour/10];
  527.                 LedBuff[1]= table[hour%10];
  528.                
  529.                 if(shan>250)
  530.                 {
  531.                         LedBuff[2]= table[minute/10];
  532.                         LedBuff[3]= table[minute%10];
  533.                 }
  534.                 else
  535.                 {
  536.                         LedBuff[2]= table[10];
  537.                         LedBuff[3]= table[10];               
  538.                 }
  539.         }
  540. }


  541. /*************數碼管顯示函數1***************/
  542. /*
  543. void Display1(uint num)   //顯示時間程序
  544. {
  545.         uchar A1,A2,A3,A4;
  546.         A1 = num/1000;    //千位
  547.         A2 = num%1000/100;   //百位
  548.         A3 = num%100/10;    //十位
  549.         A4 = num%10;    //個位
  550.                 if(A1==0)
  551.                 LedBuff[0]= table[10];    //千位為0不顯示
  552. //                else
  553. //                LedBuff[0]= table[A1];

  554.                 if((A2==0) && (A1==0))          //千位百位都為0百位不顯示
  555.                 LedBuff[1]= table[10];    //
  556.                 else
  557.                 LedBuff[1]= table[A2];                //

  558.                 if((A2==0) && (A1==0) && (A3==0))          //千位百位十位都為0十位不顯示
  559.                 LedBuff[2]= table[10];
  560.                 else
  561.                 LedBuff[2]= table[A3];

  562.                 if((shan>250) && (set_flag==0) && (flag==1))//非設置狀態+計時狀態,第4位數碼管的小數點閃爍
  563.                 LedBuff[3]= table[A4]&0x7f;      //顯示分個位
  564.                 else
  565.                 LedBuff[3]= table[A4];
  566. } */
  567. ////////////////////////
  568. //void Display() //顯示off
  569. //{
  570. //        LedBuff[0]= table[10];
  571. //        LedBuff[1]= table[0];
  572. //        LedBuff[2]= table[13];
  573. //        LedBuff[3]= table[13];
  574. //}

  575. /////////////////////

  576. void main()
  577. {
  578.         Timer0Init();
  579.         P0M0 = 0x0f;   //
  580.     P0M1 = 0x00;   //
  581.     P1M0 = 0x00;   //
  582.         P1M1 = 0x00;
  583.     P2M0 = 0x1f;   //p2.0-p2.4 設為推挽輸出
  584.     P2M1 = 0x00;
  585.     P3M0 = 0x04;  //P3.2設為推挽輸出才能驅動繼電器
  586.     P3M1 = 0x00;
  587.     P4M0 = 0x00;
  588.     P4M1 = 0x00;
  589.     P5M0 = 0x00;
  590.     P5M1 = 0x00;

  591. //        P2PU=0x10;
  592. //        P2DR=0X00;
  593. //        out = 0;

  594. //        fen_L = IapRead(0x0001);
  595. //        fen_M = IapRead(0x0002);
  596. //        if(fen_L==255)
  597. //                fen_L = 254;
  598. //        if(fen_M==255)
  599. //                fen_M = 0;
  600. //        fen = fen_M*256 + fen_L;
  601. //        fen_temp=fen;
  602. //
  603. //        w5=1;
  604.         while(1)
  605.         {
  606.                 display_sf();
  607.                 keyscan();

  608.                 if(shan>250)
  609.                 {w5=1;  BZ=1;}
  610.                 else {w5=0; BZ=0;}
  611.         }
  612. }

  613. void timer0() interrupt 1
  614. {
  615. //        if(flag3==0)
  616. //        {
  617. //                cont2++;
  618. //                if(cont2==500) //1秒
  619. //                {
  620. //                        cont2=0;
  621. //                        num2++;
  622. //                        if(num2==3)//開機延時3秒啟動輸出
  623. //                        {
  624. //                                num2=0;
  625. //                                flag=1;        //計時標志置1
  626. ////                                out = 1;//打開輸出
  627. //                                fm_flag=1;//啟動蜂鳴器
  628. //                                flag3=1;
  629. //                        }
  630. //                }
  631. //        }

  632.         if(fm_flag)
  633.         {
  634.                 BZ = 0;        //蜂鳴器開
  635.                 cont3++;
  636.                 if(cont3==100)//0.2秒
  637.                 {
  638.                         cont3=0;
  639.                         BZ = 1;         //蜂鳴器關
  640.                         fm_flag=0;        
  641.                 }        
  642.         }
  643.                                                                                                                                                                  
  644.         shan++;
  645.         if(shan==500)
  646.         {
  647.                 shan=0;
  648.         }

  649.         Ledcount++;
  650.         P1=0xff;   //消影
  651.         if(Ledcount==4)
  652.         {
  653.                 Ledcount=0;
  654.         }
  655.         switch(Ledcount)
  656.         {
  657.                 case 0: w2 = 1; w3 = 1; w4 = 1;w1 = 0; P1 = LedBuff[0];  break;
  658.                 case 1: w1 = 1; w3 = 1; w4 = 1;w2 = 0; P1 = LedBuff[1];  break;
  659.                 case 2: w1 = 1; w2 = 1; w4 = 1;w3 = 0; P1 = LedBuff[2];  break;
  660.                 case 3: w1 = 1; w2 = 1; w3 = 1;w4 = 0; P1 = LedBuff[3];  break;
  661.                 default: break;
  662.         }
  663.         


  664.         if(flag1) //按鍵消抖計時
  665.         {k1_time_count++;}

  666.         if(flag2) //按鍵消抖計時
  667.         {k2_time_count++;}

  668.         if(flag3) //按鍵消抖計時
  669.         {k3_time_count++;}


  670.    /*     if(set_flag) //無按鍵 3秒退出設置狀態
  671.         {
  672.                 cont1++;
  673.                 if(cont1==500) //1秒到
  674.                 {
  675.                         cont1=0;
  676.                         num++;
  677.                         if(num==3)
  678.                         {
  679.                                 num=0;
  680.                                 set_flag=0;//設置標志清零,退出設置狀態
  681.                                 flag=1;         //計時標志置1,開始計時
  682.                                 fm_flag=1;//啟動蜂鳴器,響一下
  683.                         }               
  684.                 }
  685.         }*/
  686. }

復制代碼

程序和Gerber格式的PCB文件下載: 0.8寸數碼管時鐘.zip (542.14 KB, 下載次數: 44)

評分

參與人數 1黑幣 +90 收起 理由
admin + 90 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發
ID:1085081 發表于 2023-12-9 21:20 | 只看該作者
這個資料好啊,多謝
回復

使用道具 舉報

板凳
ID:140489 發表于 2023-12-11 12:55 | 只看該作者
重新做了一個,沒有第一個的問題,看來的是第一個單片機有問題
回復

使用道具 舉報

地板
ID:140489 發表于 2023-12-11 15:50 | 只看該作者
這次制作有點不順,ds3231(8腳封裝)的,加0.22F的法拉電容,開始兩天測試掉電能繼續走時,過了兩天再來測試,掉電重新上電,時間就亂了。手上有一個DS3231模塊,把模塊接在板上,掉電繼續走時正常;看來ds3231(8腳封裝)的這個時鐘芯片也有問題
回復

使用道具 舉報

5#
ID:140489 發表于 2023-12-12 09:09 | 只看該作者
這是時間和溫度輪流顯示的程序
  1. /*
  2. 項目名稱:0.8寸4位共陽數碼管時鐘
  3. 1.5個PNP三極管接在共陽極驅動數碼管,這個數碼管小數點都有,冒號是單獨兩個LED
  4. 2.設置方法:按k1鍵設置狀態(小時位數碼管閃爍),按K2鍵++,按K3鍵--,長按連加連減;
  5. 按K1鍵第二次,分鐘位數碼管閃爍,按K2鍵++,按K3鍵--,長按連加連減;
  6. 按K1鍵第三次,退出設置狀態,回到正常走時界面。
  7. 3. P2.0-P2.4位驅動口,P1口為段驅動口;

  8. 4. 單片機=STC8H1K16(LQFP32封裝) @11.0592MHz   時鐘芯片=DS3231MZ(SOP-8封裝)
  9. 測試通過
  10. 第一次發的程序按鍵長按有bug,也改好了。


  11. */
  12. #include <STC8H.H>
  13. #include <intrins.h>
  14. #include "ds18b20.h"
  15. //#include "delay.h"
  16. #define uchar unsigned char
  17. #define uint unsigned int


  18. //typedef     unsigned char   u8;
  19. //typedef     unsigned int    u16;
  20. //typedef     unsigned long   u32;

  21. sbit k1=P0^0;//        按鍵1 設置 +
  22. sbit k2=P2^7;//        按鍵2  -
  23. sbit k3=P3^7;//        
  24. sbit k4=P2^5;
  25. sbit out = P3^2;          //輸出端口
  26. sbit w1 = P2^0;          //設置位驅動口
  27. sbit w2 = P2^1;
  28. sbit w3 = P2^2;
  29. sbit w4 = P2^3;

  30. sbit w5 = P2^4;        //冒號控制

  31. sbit BZ = P0^3;//蜂鳴器控制口
  32. uint count,cont1,cont2,cont3;
  33. uint fen,fen_temp;
  34. uchar fen_L,fen_M,miao,num,num2;
  35. uchar Ledcount;
  36. uchar num;
  37. uchar k1_lock,k2_lock,k3_lock;//按鍵鎖
  38. uchar knum;
  39. uint shan,shan1;//秒點閃爍 計時變量

  40. uint k1_time_count;          //K1消抖計數
  41. uint k2_time_count;          //K2消抖計數
  42. uint k3_time_count;          //K3消抖計數

  43. bit flag;        //計時啟動標志
  44. bit flag1;        //按鍵消抖計數標志
  45. bit flag2;        //按鍵消抖計數標志
  46. bit save_flag;//數據保存標志
  47. bit save_flag1;//數據保存標志
  48. bit set_flag=0; //設置標志
  49. bit fm_flag;//蜂鳴器

  50. bit flag3;
  51. bit qh_flag,qh_flag1;
  52. uchar hour,minute,second,year,month,day,date,week;
  53. uint TH3231;
  54. bit        ack;                //應答標志位

  55. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xC6,0xbf,0x8e};//共陽段碼 (0--9、黑屏,C,-,F)0X46 C帶點,0xc6C不帶點
  56. uchar LedBuff[]={0xff,0xff,0xff,0xff};

  57. // ------------------------------------------------------------
  58. // IO口模擬I2C通信

  59. // ------------------------------------------------------------
  60. sbit SCL=P3^5; //串行時鐘
  61. sbit SDA=P3^4; //串行數據

  62. /********************************************************************************************************
  63. **         DS3231常數定義
  64. ********************************************************************************************************/
  65. #define DS3231_WriteAddress 0xD0    //器件寫地址
  66. #define DS3231_ReadAddress  0xD1    //器件讀地址
  67. #define DS3231_SECOND       0x00    //秒
  68. #define DS3231_MINUTE       0x01    //分
  69. #define DS3231_HOUR         0x02    //時
  70. #define DS3231_WEEK         0x03    //星期
  71. #define DS3231_DAY          0x04    //日
  72. #define DS3231_MONTH        0x05    //月
  73. #define DS3231_YEAR         0x06    //年

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



  76. #define NACK    1
  77. #define ACK     0
  78. /////////////////

  79. //void        Delay5US()           //@12.000MHz           延時5us
  80. //{
  81. //   _nop_(); _nop_();        _nop_();_nop_();         _nop_();_nop_();//STC Y6指令 1T單片機用6個nop,12T用1個nop
  82. //}

  83. void Delay5US()                //@11.0592MHz         STC Y6指令
  84. {
  85.         unsigned char i;

  86.         _nop_();
  87.         i = 16;
  88.         while (--i);
  89. }


  90. void delay(uint x)
  91. {
  92.         uint y,z;
  93.         for(y=0; y<x; y--)
  94.                 for(z=0; z<1200; z--);

  95. }


  96. /**********************************************
  97. //IIC Start
  98. **********************************************/
  99. void IIC_Start()
  100. {
  101.    SCL = 1;               
  102.    SDA = 1;
  103.    SDA = 0;
  104.    SCL = 0;
  105. }

  106. /**********************************************
  107. //IIC Stop
  108. **********************************************/
  109. void IIC_Stop()
  110. {
  111.    SCL = 0;
  112.    SDA = 0;
  113.    SCL = 1;
  114.    SDA = 1;
  115. }

  116. /********************************************************************************************************
  117. **         3231
  118. ********************************************************************************************************/


  119. uchar        BCD2HEX(uchar val)//轉10進制
  120. {
  121.         return        ((val>>4)*10)+(val&0x0f);
  122. }

  123. uchar        HEX2BCD(uchar val) //轉16進制
  124. {
  125.         return        (((val%100)/10)<<4)|(val%10);
  126. }


  127. void SendByte(uchar c)
  128. {
  129.     uchar BitCnt;
  130.    
  131.     for(BitCnt=0;BitCnt<8;BitCnt++)         //要傳送的數據長度為8位
  132.     {
  133.         if((c<<BitCnt)&0x80)
  134.             SDA=1;                          //判斷發送位
  135.         else
  136.             SDA=0;     
  137.         SCL=1;                            //置時鐘線為高,通知被控器開始接收數據位
  138.         Delay5US();                       //保證時鐘高電平周期大于4μs   
  139.         SCL=0;
  140.     }
  141.     SDA=1;                                  //8位發送完后釋放數據線,準備接收應答位
  142.     SCL=1;
  143.     Delay5US();
  144.     if(SDA==1)
  145.         ack=0;   
  146.     else
  147.         ack=1;                              //判斷是否接收到應答信號
  148.     SCL=0;
  149.     Delay5US();
  150. }           

  151. uchar RcvByte()
  152. {
  153.    uchar retc;
  154.    uchar BitCnt;

  155.    retc=0;
  156.    SDA=1;                           //置數據線為輸入方式
  157.    for(BitCnt=0;BitCnt<8;BitCnt++)
  158.    {
  159.         SCL=0;                      //置時鐘線為低,準備接收數據位      
  160.         Delay5US();                 //時鐘低電平周期大于4.7μs                       
  161.         SCL=1;                      //置時鐘線為高使數據線上數據有效
  162.         Delay5US();
  163.         retc=retc<<1;
  164.         if(SDA==1)
  165.             retc=retc+1;            //讀數據位,接收的數據位放入retc中
  166.         Delay5US();
  167.    }
  168.    SCL=0;
  169.    return(retc);
  170. }                           

  171. void Ack_I2C(bit a)
  172. {
  173.         SDA        =        a;  
  174.     SCL=1;                     
  175.     Delay5US();             //時鐘低電平周期大于4us   
  176.     SCL=0;                  //清時鐘線,鉗住I2C總線以便繼續接收
  177.     Delay5US();   
  178. }                                            

  179. uchar write_byte(uchar addr, uchar write_data)
  180. {
  181.     IIC_Start();
  182.     SendByte(DS3231_WriteAddress);
  183.     if (ack == 0)
  184.         return 0;
  185.    
  186.     SendByte(addr);   
  187.     if (ack == 0)
  188.         return 0;
  189.    
  190.     SendByte(write_data);
  191.     if (ack == 0)
  192.         return 0;
  193.    
  194.     IIC_Stop();
  195.     Delay5US();      
  196.     Delay5US();      
  197.     return 1;
  198. }                                          

  199. uchar read_current()
  200. {
  201.     uchar read_data;
  202.     IIC_Start();
  203.     SendByte(DS3231_ReadAddress);
  204.     if(ack==0)
  205.         return(0);              
  206.     read_data = RcvByte();
  207.     Ack_I2C(1);
  208.     IIC_Stop();
  209.     return read_data;
  210. }                                                

  211. uchar read_random(uchar random_addr)
  212. {
  213.     uchar Tmp;
  214.         IIC_Start();
  215.     SendByte(DS3231_WriteAddress);
  216.     if(ack==0)
  217.         return(0);            
  218.     SendByte(random_addr);
  219.     if(ack==0)
  220.         return(0);
  221.         Tmp=read_current();
  222.         if(random_addr==DS3231_HOUR)
  223.                 Tmp&=0x3f;
  224.                                             
  225.     return(BCD2HEX(Tmp));//都轉10進制輸出
  226. }

  227. /***********************/
  228. uchar read_random1(uchar random_addr)  //這個是讀溫度函數
  229. {
  230.     uchar Tmp;
  231. //        write_byte(0x0e,0x20);//0x0e寄存器的CONV位置1開啟溫度轉換,要這句,溫度實時刷新,這句不要,溫度要64s才刷新1次
  232.                                                   //數碼管顯示不能要這句,否則溫度值小數部分亂跳
  233.         IIC_Start();
  234.     SendByte(DS3231_WriteAddress);
  235.     if(ack==0)
  236.         return(0);            
  237.     SendByte(random_addr);
  238.     if(ack==0)
  239.         return(0);
  240.         Tmp=read_current();
  241.         return Tmp;
  242. }                                 

  243. void ModifyTime(uchar address,uchar num)
  244. {
  245.     uchar temp=0;
  246.            if(address>6 && address <0) return;
  247.     temp=HEX2BCD(num);
  248.         write_byte(address,temp);
  249. }



  250. ////////////////
  251. /*
  252. void IapIdle()
  253. {
  254.     IAP_CONTR = 0;                              //關閉IAP功能
  255.     IAP_CMD = 0;                                //清除命令寄存器
  256.     IAP_TRIG = 0;                               //清除觸發寄存器
  257.     IAP_ADDRH = 0x80;                           //將地址設置到非IAP區域
  258.     IAP_ADDRL = 0;
  259. }

  260. char IapRead(int addr)
  261. {
  262.     char dat;

  263.     IAP_CONTR = 0x80;                           //使能IAP
  264.     IAP_TPS = 12;                               //設置等待參數12MHz
  265.     IAP_CMD = 1;                                //設置IAP讀命令
  266.     IAP_ADDRL = addr;                           //設置IAP低地址
  267.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  268.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  269.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  270.     _nop_();
  271.     dat = IAP_DATA;                             //讀IAP數據
  272.     IapIdle();                                  //關閉IAP功能

  273.     return dat;
  274. }

  275. void IapProgram(int addr, char dat)
  276. {
  277.     IAP_CONTR = 0x80;                           //使能IAP
  278.     IAP_TPS = 12;                               //設置等待參數12MHz
  279.     IAP_CMD = 2;                                //設置IAP寫命令
  280.     IAP_ADDRL = addr;                           //設置IAP低地址
  281.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  282.     IAP_DATA = dat;                             //寫IAP數據
  283.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  284.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  285.     _nop_();
  286.     IapIdle();                                  //關閉IAP功能
  287. }

  288. void IapErase(int addr)
  289. {
  290.     IAP_CONTR = 0x80;                           //使能IAP
  291.     IAP_TPS = 12;                               //設置等待參數12MHz
  292.     IAP_CMD = 3;                                //設置IAP擦除命令
  293.     IAP_ADDRL = addr;                           //設置IAP低地址
  294.     IAP_ADDRH = addr >> 8;                      //設置IAP高地址
  295.     IAP_TRIG = 0x5a;                            //寫觸發命令(0x5a)
  296.     IAP_TRIG = 0xa5;                            //寫觸發命令(0xa5)
  297.     _nop_();                                    //
  298.     IapIdle();                                  //關閉IAP功能
  299. }
  300. */
  301. ////////////////////
  302. void Timer0Init(void)                //2毫秒@11.0592MHz
  303. {
  304.         AUXR |= 0x80;                //定時器時鐘1T模式
  305.         TMOD &= 0xF0;                //設置定時器模式  16位自動重載
  306.         TL0 = 0x9A;                //設置定時初始值
  307.         TH0 = 0xA9;                //設置定時初始值
  308.         TF0 = 0;                //清除TF0標志
  309.         TR0 = 1;                //定時器0開始計時
  310.         EA = 1;                        //開總中斷
  311.         ET0 = 1;                //開T0中斷
  312. }


  313. //void Timer0Init(void)                //5毫秒@11.0592MHz
  314. //{
  315. //        AUXR |= 0x80;                //定時器時鐘1T模式
  316. //        TMOD &= 0xF0;                //設置定時器模式
  317. //        TL0 = 0x00;                //設置定時初始值
  318. //        TH0 = 0x28;                //設置定時初始值
  319. //        TF0 = 0;                //清除TF0標志
  320. //        TR0 = 1;                //定時器0開始計時
  321. //        EA = 1;                        //開總中斷
  322. //        ET0 = 1;                //開T0中斷
  323. //}
  324. /////////////////////////////
  325. void keyscan()
  326. {
  327.         uchar temp;
  328.         hour = read_random(DS3231_HOUR);
  329.         minute = read_random(DS3231_MINUTE) ;
  330.         second = read_random(DS3231_SECOND);

  331.         
  332.         if(k1)        //
  333.         {                                                //
  334.                 k1_time_count=0;
  335.                 k1_lock=0;
  336.                 flag1 = 0;
  337.         }
  338.         else if((k1_lock==0))
  339.         {
  340.                 flag1 = 1; //按鍵按下 消抖計時標志置1 開始消抖計時
  341.                 if((k1_time_count==10))  //20毫秒
  342.                 {
  343.                         k1_time_count=0;
  344.                         k1_lock=1;
  345.                         knum++;
  346.                         if(knum==3)
  347.                         {
  348.                                 knum=0;
  349.                                 second=0;
  350.                                 write_byte(DS3231_SECOND, second); //秒寫0
  351.                         }
  352.                 }
  353.         }

  354. /////////////////////////////
  355.         if(knum==1)  //設置小時
  356.         {
  357.                 if(k2 ==1)                                   //++
  358.                 {
  359.                         k2_time_count=0;
  360.                         k2_lock=0;
  361.                         flag2 = 0;
  362.                 }
  363.                 else if(k2_lock==0)
  364.                 {
  365.                 //        flag = 0;
  366.                         flag2 = 1;
  367.                 //        save_flag = 1;
  368.                         if(k2_time_count==10)                //短按
  369.                         {
  370.                                 k2_time_count=0;
  371.                                 k2_lock=1;
  372.                                 hour++;
  373.                                 if(hour>23)
  374.                                         hour=0;
  375.                                 temp=HEX2BCD(hour);
  376.                                 write_byte(DS3231_HOUR, temp);
  377.                         }        
  378.                 }
  379.                 else if(k2_time_count>500)                 //長按
  380.                 {
  381.                   // cont1=0; num=0;
  382.                    k2_time_count=400;
  383.                         hour++;
  384.                         if(hour>23)
  385.                                 hour=0;
  386.                         temp=HEX2BCD(hour);        //10進制轉16進制
  387.                         write_byte(DS3231_HOUR, temp);

  388.                 }
  389. //////////////////////////
  390.                 if(k3 == 1)                                   //--
  391.                 {
  392.                         k3_time_count=0;
  393.                         k3_lock=0;
  394.                         flag3 = 0;
  395.                 }
  396.                 else if(k3_lock==0)
  397.                 {
  398.                
  399.                         flag3 = 1;
  400.                 //        save_flag1 = 1;
  401.                         if(k3_time_count==10)                //短按
  402.                         {
  403.                         //        cont1=0; num=0;
  404.                                 k3_time_count=0;
  405.                                 k3_lock=1;
  406.                                 hour--;
  407.                                 if(hour==255)
  408.                                         hour=23;
  409.                                 temp=HEX2BCD(hour);
  410.                                 write_byte(DS3231_HOUR, temp);

  411.                         }
  412.                                 
  413.                 }
  414.                 else if(k3_time_count>500)                 //長按
  415.                 {
  416.                   // cont1=0; num=0;  
  417.                    k3_time_count=400;         //長按200ms連減
  418.                                 hour--;
  419.                         if(hour==255)
  420.                                 hour=23;
  421.                         temp=HEX2BCD(hour);
  422.                         write_byte(DS3231_HOUR, temp);

  423.                 }
  424.         }
  425.   ////////////////////////////////
  426.         if(knum==2)                 //設置分鐘
  427.         {
  428.                 if(k2 ==1)                                   //++
  429.                 {
  430.                         k2_time_count=0;
  431.                         k2_lock=0;
  432.                         flag2 = 0;
  433.                 }
  434.                 else if(k2_lock==0)
  435.                 {
  436.                 //        flag = 0;
  437.                         flag2 = 1;
  438.                 //        save_flag = 1;
  439.                         if(k2_time_count==10)                //短按
  440.                         {
  441.                                 k2_time_count=0;
  442.                                 k2_lock=1;
  443.                                 minute++;
  444.                                 if(minute>59)
  445.                                         minute=0;
  446.                                 temp=HEX2BCD(minute);
  447.                                 write_byte(DS3231_MINUTE, temp);
  448.                         }        
  449.                 }
  450.                 else if(k2_time_count>500)                 //長按
  451.                 {
  452.                   // cont1=0; num=0;
  453.                    k2_time_count=400;
  454.                         minute++;
  455.                         if(minute>59)
  456.                                 minute=0;
  457.                         temp=HEX2BCD(minute);
  458.                         write_byte(DS3231_MINUTE, temp);

  459.                 }
  460. //////////////////////////
  461.                 if(k3 == 1)                                   //--
  462.                 {
  463.                         k3_time_count=0;
  464.                         k3_lock=0;
  465.                         flag3 = 0;
  466.                 }
  467.                 else if(k3_lock==0)
  468.                 {
  469.                
  470.                         flag3 = 1;
  471.                 //        save_flag1 = 1;
  472.                         if(k3_time_count==10)                //短按
  473.                         {
  474.                         //        cont1=0; num=0;
  475.                                 k3_time_count=0;
  476.                                 k3_lock=1;
  477.                                 minute--;
  478.                                 if(minute==255)
  479.                                         minute=59;
  480.                                 temp=HEX2BCD(minute);
  481.                                 write_byte(DS3231_MINUTE, temp);
  482.                         }
  483.                                 
  484.                 }
  485.                 else if(k3_time_count>500)                 //長按
  486.                 {
  487.                   // cont1=0; num=0;  
  488.                    k3_time_count=400;
  489.                         minute--;
  490.                         if(minute==255)
  491.                                 minute=59;
  492.                         temp=HEX2BCD(minute);
  493.                         write_byte(DS3231_MINUTE, temp);
  494.                 }
  495.         }
  496. }

  497. ///////////////////////////////
  498. void display_sf() //顯示 時分
  499. {
  500. //                        year = read_random(DS3231_YEAR);               
  501. //                    month = read_random(DS3231_MONTH);        
  502. //                    day = read_random(DS3231_DAY);        
  503. //                    week = read_random(DS3231_WEEK);
  504.         hour = read_random(DS3231_HOUR);
  505.         minute = read_random(DS3231_MINUTE) ;
  506.         second = read_random(DS3231_SECOND);
  507.         if(knum==0)
  508.         {
  509.                 LedBuff[0]= table[hour/10];
  510.                 LedBuff[1]= table[hour%10];

  511.                 LedBuff[2]= table[minute/10];
  512.                 LedBuff[3]= table[minute%10];
  513.                 if(shan>250)
  514.                 {w5=1; }
  515.                 else {w5=0;}


  516.         }
  517.         if(knum==1)
  518.         {
  519.                 if(shan1>125)        
  520.                 {
  521.                         LedBuff[0]= table[hour/10];
  522.                         LedBuff[1]= table[hour%10];
  523.                 }
  524.                 else
  525.                 {
  526.                         LedBuff[0]= table[10];
  527.                         LedBuff[1]= table[10];
  528.                
  529.                 }
  530.                 LedBuff[2]= table[minute/10];
  531.                 LedBuff[3]= table[minute%10];
  532.         }
  533.         if(knum==2)
  534.         {
  535.                
  536.                 LedBuff[0]= table[hour/10];
  537.                 LedBuff[1]= table[hour%10];
  538.                
  539.                 if(shan1>125)
  540.                 {
  541.                         LedBuff[2]= table[minute/10];
  542.                         LedBuff[3]= table[minute%10];
  543.                 }
  544.                 else
  545.                 {
  546.                         LedBuff[2]= table[10];
  547.                         LedBuff[3]= table[10];               
  548.                 }
  549.         }
  550. }


  551. ///////////////////////

  552. void ds18b20disp(uint Value)
  553. {
  554.         if(s==0) //顯示正溫度
  555.         {
  556.                 if((Value/1000)>0)//大于100度顯示最高位
  557.                         LedBuff[0]= table[Value/1000];               
  558.                 else                        
  559.                         LedBuff[0]=table[10];//小于100度不顯示最高位
  560.         }else {LedBuff[0]=s;}//顯示負號
  561.         LedBuff[1]=table[Value%1000/100];        //十位
  562.         LedBuff[2]=table[Value%100/10];//
  563.         LedBuff[3]=table[11];
  564. }  
  565. /////////////////////

  566. /////////////////////

  567. void main()
  568. {
  569.         Timer0Init();
  570.         P0M0 = 0x00;   //
  571.     P0M1 = 0x00;   //
  572.     P1M0 = 0x00;   //
  573.         P1M1 = 0x00;
  574.     P2M0 = 0x1f;   //p2.0-p2.4 設為推挽輸出
  575.     P2M1 = 0x00;
  576.     P3M0 = 0x04;  //P3.2設為推挽輸出才能驅動繼電器
  577.     P3M1 = 0x00;
  578.     P4M0 = 0x00;
  579.     P4M1 = 0x00;
  580.     P5M0 = 0x10;
  581.     P5M1 = 0x00;

  582. //        P2PU=0x10;
  583. //        P2DR=0X00;
  584. //        w5=1;
  585.         while(1)
  586.         {
  587.                
  588.                 keyscan();
  589.                 if(qh_flag==0)
  590.                 {
  591.                         display_sf();
  592.                 }
  593.                 else
  594.                 {
  595.                         if(knum==0)
  596.                         {
  597.                                 read_temp();         //DS18B20溫度
  598.                                 ds18b20disp(tvalue);
  599.                                 w5=1;
  600.                         }
  601.                 }

  602.                 if(knum!=0)
  603.                 {
  604.                         qh_flag=0;
  605.                 }
  606. //                if(shan>250)
  607. //                {BZ=1;}
  608. //                else {BZ=0;}
  609.                
  610. //                BZ=0;
  611. //                Delay_us(10);//實測11us(延時函數里面4個_nop_();@11.0592MHz)
  612. //                BZ=1;
  613. //                Delay_us(10);
  614.                  
  615.         }
  616. }

  617. void timer0() interrupt 1
  618. {

  619.         static uint i,j;
  620.         /*
  621.         if(fm_flag)
  622.         {
  623.                 BZ = 0;        //蜂鳴器開
  624.                 cont3++;
  625.                 if(cont3==100)//0.2秒
  626.                 {
  627.                         cont3=0;
  628.                         BZ = 1;         //蜂鳴器關
  629.                         fm_flag=0;        
  630.                 }        
  631.         } */
  632.                                                                                                                                                                  
  633.         shan++;
  634.         if(shan==500)
  635.         {
  636.                 shan=0;
  637.         }

  638.         if(knum != 0)
  639.         {
  640.                 shan1++;
  641.                 if(shan1==250)
  642.                         shan1=0;
  643.         }

  644.         Ledcount++;
  645.         P1=0xff;   //消影
  646.         if(Ledcount==4)
  647.         {
  648.                 Ledcount=0;
  649.         }
  650.         switch(Ledcount)
  651.         {
  652.                 case 0: w2 = 1; w3 = 1; w4 = 1;w1 = 0; P1 = LedBuff[0];  break;
  653.                 case 1: w1 = 1; w3 = 1; w4 = 1;w2 = 0; P1 = LedBuff[1];  break;
  654.                 case 2: w1 = 1; w2 = 1; w4 = 1;w3 = 0; P1 = LedBuff[2];  break;
  655.                 case 3: w1 = 1; w2 = 1; w3 = 1;w4 = 0; P1 = LedBuff[3];  break;
  656.                 default: break;
  657.         }
  658.         


  659.         if(flag1) //按鍵消抖計時
  660.         {k1_time_count++;}

  661.         if(flag2) //按鍵消抖計時
  662.         {k2_time_count++;}

  663.         if(flag3) //按鍵消抖計時
  664.         {k3_time_count++;}

  665.         if(qh_flag1==0 && knum==0)
  666.         {
  667.                 i++;
  668.                 if(i==500)
  669.                 {
  670.                         i=0;
  671.                         j++;
  672.                         if(j==7)
  673.                         {
  674.                                 j=0;
  675.                                 qh_flag=1;
  676.                                 qh_flag1=1;
  677.                         }
  678.                 }
  679.         }
  680.         else
  681.         {
  682.                 if(knum==0)
  683.                 {
  684.                         i++;
  685.                         if(i==500)
  686.                         {
  687.                                 i=0;
  688.                                 j++;
  689.                                 if(j==3)
  690.                                 {
  691.                                         j=0;
  692.                                         qh_flag=0;
  693.                                         qh_flag1=0;
  694.                                 }
  695.                         }
  696.                 }
  697.         }

  698. }

  699. [code]#ifndef __DS18B20_H__
  700. #define __DS18B20_H__

  701. //#include "delay.h"
  702. #define uchar unsigned char
  703. #define uint unsigned int

  704. /*定義DS18B20數據線*/
  705. sbit DQ = P0^1;
  706. //sbit DQ = P5^4;

  707. /*DS18B20驅動程序------------------------------------------------------------*/
  708. uchar data disdata[5];
  709. uint tvalue;//溫度值
  710. uint s;
  711. void Delay_us(uchar i)        //us延時 STC  Y6指令 使用STC8系列
  712. {                                                 //@11.0592MHz
  713.          while(i--)
  714.          {        
  715.          _nop_();
  716.      _nop_();
  717.          _nop_();
  718.      _nop_();
  719.          ////////////
  720.          _nop_(); //_nop_();// _nop_();        _nop_();
  721.          }
  722. }  




  723. /*單總線初始化時序*/
  724. bit ds_init()
  725. {
  726.         bit i;
  727.         DQ = 1;
  728.         _nop_();_nop_();_nop_();_nop_();_nop_();
  729.         DQ = 0;
  730.         Delay_us(250); Delay_us(250);//拉低總線499.45us 掛接在總線上的18B20將會全部被復位
  731.         DQ = 1; //釋放總線
  732.         Delay_us(38); //延時37.95us 等待18B20發回存在信號
  733.         i = DQ;
  734.         Delay_us(145); //141.95us
  735.         DQ = 1;
  736.         _nop_();
  737.         return (i);
  738. }
  739. /*寫一個字節*/
  740. void write_byte_ds18b20(uchar dat)
  741. {
  742.         uchar i;
  743.         for(i=0;i<8;i++)
  744.         {
  745.                 DQ = 0;
  746.                 _nop_();//產生些時序
  747.                 DQ = dat & 0x01;
  748.                 Delay_us(78);//76.95us
  749.                 DQ = 1; //釋放總線準備下一次數據寫入
  750.                 _nop_();
  751.                 dat >>= 1;
  752.         }
  753. }

  754. uchar read_byte()
  755. {
  756.         uchar i, j, dat;
  757.         for(i=0;i<8;i++)
  758.         {
  759.                 DQ = 0;
  760.                 _nop_();//產生讀時序
  761.                 DQ = 1;
  762.                 _nop_();//釋放總線
  763.                 j = DQ;
  764.                 Delay_us(78);//76.95us
  765.                 DQ = 1;
  766.                 _nop_();
  767.                 dat = (j<<7)|(dat>>1);        
  768.         }
  769.         return (dat);
  770. }

  771. read_temp()
  772. {
  773. //        float tt;
  774.         uchar L,M;
  775.            ds_init();   
  776.            write_byte_ds18b20(0xcc);//*跳過讀序列號*/
  777.            write_byte_ds18b20(0x44);//*啟動溫度轉換*/
  778.                 Delay_us(100);
  779.            ds_init();   
  780.            write_byte_ds18b20(0xcc);//*跳過讀序列號*/
  781.            write_byte_ds18b20(0xbe);//*讀取溫度*/
  782.                 Delay_us(100);
  783.            L=read_byte();
  784.            M=read_byte();
  785.            tvalue=M;
  786.            tvalue<<=8;
  787.            tvalue=tvalue|L;


  788. //        if(M >= 0x08)        //判斷是否為負數
  789. //        {
  790. //                tvalue = ~tvalue + 1;//負數是以補碼的形式存放的需要取反加1
  791. //                s = "-";  //顯示負數符號
  792. //        }
  793. //        else s = 0;           //為正數則不顯示負數符號


  794.            tvalue=tvalue*(0.625);//溫度值擴大10倍,精確到1位小數
  795.         return(tvalue);
  796. }
  797. /*溫度值顯示-----------------------------------------------------------------*/
  798. /*
  799. void ds1820disp()
  800. {
  801.         disdata[0]=tvalue%1000/100+0x30;         //十位數
  802.         disdata[1]=tvalue%100/10+0x30;           //個位數
  803.         disdata[2]=tvalue%10+0x30;               //小數位   
  804.         if(disdata[0]==0x30) { disdata[0]=0x20; }//如果十位為0,不顯示
  805.         set1616pic(5,4,0,1);                                         //顯示"溫度計圖標"
  806.         write_com(0x30); write_com(0x06);        
  807.         write_com(0x9d);           //在液晶上顯示溫度起始位置:"28.8°C
  808.         write_data(disdata[0]);    //顯示十位         
  809.         write_data(disdata[1]);    //顯示個位         
  810.         write_data(0x2e);          //顯示小數點         
  811.         write_data(disdata[2]);    //顯示小數位
  812.         set1616pic(8,4,0,0);           //在第8列第4行不反白的°C圖標
  813. }  */
  814. /*---------------------------------------------------------------------------*/
  815. #endif
復制代碼
回復

使用道具 舉報

6#
ID:140489 發表于 2023-12-21 15:16 | 只看該作者
ds3231(8腳封裝)買了兩家的,都是掉電走時有問題,重新買了ds3231(16腳封裝)的掉電走時很好,看來ds3231(8腳封裝)掉電走時是有問題的
回復

使用道具 舉報

7#
ID:95809 發表于 2023-12-23 20:25 | 只看該作者
lids 發表于 2023-12-21 15:16
ds3231(8腳封裝)買了兩家的,都是掉電走時有問題,重新買了ds3231(16腳封裝)的掉電走時很好,看來ds323 ...

我用的就是8腳的,沒發現問題。秒點不需要單獨用三極管驅動,公共端接在gon第二個個的公共端就行了,我都是這樣處理的。
回復

使用道具 舉報

8#
ID:140489 發表于 2023-12-27 15:21 | 只看該作者
掉電走時,重新上電時間會亂的問題解決了,原因是I2C總線的上拉電阻要接在單片機的IO口,并且要上拉到5V,時鐘芯片是3.3V供電(DS3231芯片3.3V供電比5V供電走時精度高些),時鐘芯片SDA  SCL的上拉不用
回復

使用道具 舉報

9#
ID:95809 發表于 2024-1-5 16:31 來自手機 | 只看該作者
把第三個數碼管倒過來,利用點來模擬秒點閃爍,我都是這樣做的。DS3231直接利用5V供電精度沒問題,
回復

使用道具 舉報

10#
ID:140489 發表于 2024-1-8 11:27 | 只看該作者
bxyyhan 發表于 2024-1-5 16:31
把第三個數碼管倒過來,利用點來模擬秒點閃爍,我都是這樣做的。DS3231直接利用5V供電精度沒問題,

我這數碼管是一體的,不是單獨的四個。數碼管倒過來那種我做過的,兩個秒點有點丑,才做這種四位一體帶秒點的數碼管的
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 超碰在线97国产 | 一级毛片免费 | 999久久久久久久久6666 | 尤物在线精品视频 | 久久久婷 | 久久精品亚洲精品国产欧美kt∨ | 精品伊人久久 | 国产亚洲一区在线 | 91一区二区三区 | 草比网站 | 福利电影在线 | 国产伦精品一区二区三区视频金莲 | 一级片免费视频 | 国产视频中文字幕 | 亚洲一二三区精品 | 久久久久香蕉视频 | 欧美老妇交乱视频 | 国产精品夜间视频香蕉 | 一区二区三区免费观看 | 国产成人精品一区二区三区视频 | 中文av在线播放 | 欧美午夜精品 | 国产一区二区三区四区 | 国产精品自产拍在线观看蜜 | 青青草原精品99久久精品66 | 看av在线| 免费的黄色片子 | 国产免费一区二区 | 亚洲综合国产精品 | 国产 欧美 日韩 一区 | h片在线看 | 在线午夜| 国产操操操 | 欧美精品一区二区三区蜜桃视频 | 美女国内精品自产拍在线播放 | 亚洲啪啪一区 | 亚洲国产成人精 | 亚洲精品乱码久久久久久按摩观 | 久久久久亚洲精品 | 天堂资源| 狠狠骚|