找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1046|回复: 9
收起左侧

单片机0.8寸数码管时钟完整资料 程序+Gerber PCB文件

  [复制链接]
ID:140489 发表于 2023-12-7 12:41 | 显示全部楼层 |阅读模式
/*
项目名称: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用跳线短接。

制作出来的实物图如下:
实物.jpg

电路原理图如下:
电路图.jpg
附件是完整资料
  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, 下载次数: 35)

评分

参与人数 1黑币 +90 收起 理由
admin + 90 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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脚封装)的这个时钟芯片也有问题
回复

使用道具 举报

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
复制代码
回复

使用道具 举报

ID:140489 发表于 2023-12-21 15:16 | 显示全部楼层
ds3231(8脚封装)买了两家的,都是掉电走时有问题,重新买了ds3231(16脚封装)的掉电走时很好,看来ds3231(8脚封装)掉电走时是有问题的
回复

使用道具 举报

ID:95809 发表于 2023-12-23 20:25 | 显示全部楼层
lids 发表于 2023-12-21 15:16
ds3231(8脚封装)买了两家的,都是掉电走时有问题,重新买了ds3231(16脚封装)的掉电走时很好,看来ds323 ...

我用的就是8脚的,没发现问题。秒点不需要单独用三极管驱动,公共端接在gon第二个个的公共端就行了,我都是这样处理的。
回复

使用道具 举报

ID:140489 发表于 2023-12-27 15:21 | 显示全部楼层
掉电走时,重新上电时间会乱的问题解决了,原因是I2C总线的上拉电阻要接在单片机的IO口,并且要上拉到5V,时钟芯片是3.3V供电(DS3231芯片3.3V供电比5V供电走时精度高些),时钟芯片SDA  SCL的上拉不用
回复

使用道具 举报

ID:95809 发表于 2024-1-5 16:31 来自手机 | 显示全部楼层
把第三个数码管倒过来,利用点来模拟秒点闪烁,我都是这样做的。DS3231直接利用5V供电精度没问题,
回复

使用道具 举报

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 单片机教程网

快速回复 返回顶部 返回列表