找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1346|回复: 2
收起左侧

单片机1.2寸数码管时钟程序 带温度 光控 含源码电路原理图

[复制链接]
ID:378402 发表于 2023-6-30 18:34 | 显示全部楼层 |阅读模式
首先感谢论坛中提供”1寸数码管时钟+12C5A60S2单片机+自动亮度+时间温度轮流显示(实物+代码)“作者,
本人在原作者基础上,根据现有元器件,成功制作了1.2寸数码管时钟,由于首次使用嘉立创绘制原理图和PCB,
由于使用双面板制作PCB

线径较细和过孔处理技术不行改为单面板制作,制作中DS1302不计时,后增加了C3和C4
滤波电容解决了问题。

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

单片机源程序如下:
  1. /********************************************************************************
  2.            本人在原作者基础上,根据现有元器件,成功制作了1.2寸数码管时钟,由于首次使用嘉立创绘制原理图和PCB,
  3.            使用双面板制作PCB,由于线径较细和过孔处理技术不行改为单面板制作,制作中DS1302不计时,后增加了C3和C4
  4.            滤波电容解决了问题。

  5. 描述: 4位共阳数码管时钟,显示88:88样式,正常走时的时候,“:”1秒闪烁2次;调时间的的时候冒号熄灭
  6.        调时:按KEY1按键第1次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
  7.                          按KEY1按键第2次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
  8.                          按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
  9.                          校时的时候先调好时、分,分钟要比参考时间的分钟加1分,
  10.                          再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时就比较准了。
  11.                          加备用电池,掉电走时
  12.                         
  13.                          KEY2键第2功能:非调时状态,为光控开关;
  14.                          KEY3键第2功能:非调时状态,为显示切换开关;
  15.                          DS18B20做温度检测,实时时钟与温度轮流显示;
  16.                          温度显示范围: -9.9℃~99.9℃;
  17.                          增加数码管调亮度功能,按键10级亮度P1.0接10K电阻上拉、光敏电阻下拉分压;
  18.                          环境光线越亮,数码管越亮,反之数码管越暗。
  19. 实物通过.  
  20.                          12MHz晶振,STC15F2K60S2+DS1302时钟芯片+DS18B20,
  21.                          P0口接段位,P2^4~P2^7接pnp三极管控制4个共阳极。
  22. **********************************************************************************/
  23. //#include <STC12C5A60S2.h>
  24. #include <STC15F2K60S2.h>
  25. #include <intrins.h>
  26. #define uchar unsigned char
  27. #define uint unsigned int


  28. sbit TSCLK = P2^2;//时钟线
  29. sbit TIO   = P2^1;//数据线
  30. sbit TRST  = P2^0;//使能端

  31. sbit key1 = P3^4;   //设置键
  32. sbit key2 = P3^3;   //加 /光控开关键(校时的时候做加键,反之为光控开关)
  33. sbit key3 = P3^2;   // 减/显示切换键
  34. sbit DQ = P2^3;                //DS18B20数据口

  35. sbit w1 = P2^4;          //设置位驱动口
  36. sbit w2 = P2^5;
  37. sbit w3 = P2^6;
  38. sbit w4 = P2^7;
  39. sbit w5 = P3^7;         //此位不显示
  40. sbit dd = P1^4;         //蜂鸣器控制端        

  41. uchar xs=0; //显示切换计数变量
  42. uchar tian=0;
  43. uchar knum,shan_cont;
  44. char shi,fen,miao;
  45. uchar ba=40;
  46. uint mh,mh_count,count;
  47. bit shan;           //校时闪烁标志位
  48. uchar s=0;                   //显示负号
  49. uint temp;        //温度值
  50. bit flag;                  //轮流显示标志位
  51. bit flag_gk;          //光控标志位
  52. bit flag_js=0;          //自动校时标志
  53. bit flag_fm;          //蜂鸣器启动标志
  54. uchar fm;                //蜂鸣器计时变量
  55. /***************************************定义转换控制寄存器控制位*****************************************/
  56. #define ADC_POWER                   0X80            //电源控制位
  57. #define ADC_FLAG                    0X10            //转换结束标志位
  58. #define ADC_START                   0X08            //转换开始位
  59. /*********************************************定义AD转换速度*********************************************/
  60. #define ADC_SPEEDLL_540         0X00           
  61. #define ADC_SPEEDLL_360                0X20
  62. #define ADC_SPEEDLL_180                0X40
  63. #define ADC_SPEEDLL_90                0X60
  64. /***********写时分秒地址************/
  65. #define write_shi  0x84
  66. #define write_fen  0x82
  67. #define write_miao 0x80
  68. #define write_ram  0xc0
  69. /***********读时分秒地址************/
  70. #define read_shi  0x85
  71. #define read_fen  0x83
  72. #define read_miao 0x81
  73. #define read_ram  0xc1
  74. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x46,0xbf};//共阳段码 (0--9、黑屏、C、-)


  75. ...............程序已在2楼更新...........
复制代码

下载: 程序和PDF格式原理图.7z (96.29 KB, 下载次数: 38)

评分

参与人数 1黑币 +50 收起 理由
admin + 50

查看全部评分

回复

使用道具 举报

ID:378402 发表于 2023-7-2 18:05 | 显示全部楼层

RE: 1.2寸数码管时钟_温度_光控_含源码_原理图

首先感谢论坛中提供”1寸数码管时钟+12C5A60S2单片机+自动亮度+时间温度轮流显示(实物+代码)“作者,
           本人在原作者基础上,根据现有元器件,成功制作了1.2寸数码管时钟,由于首次使用嘉立创绘制原理图和PCB,
           使用双面板制作PCB,由于线径较细和过孔处理技术不行改为单面板制作,制作中DS1302不计时,后增加了C3和C4
           滤波电容解决了问题。
  1. /*********************************************************************************
  2. 描述: 4位共阳数码管时钟,显示88:88样式,正常走时的时候,“:”1秒闪烁2次;调时间的的时候冒号熄灭
  3.        调时:按KEY1按键第1次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
  4.                          按KEY1按键第2次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
  5.                          按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
  6.                          校时的时候先调好时、分,分钟要比参考时间的分钟加1分,
  7.                          再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时就比较准了。
  8.                          加备用电池,掉电走时
  9.                          
  10.                          KEY2键第2功能:非调时状态,为光控开关;
  11.                          KEY3键第2功能:非调时状态,为显示切换开关;
  12.                          DS18B20做温度检测,实时时钟与温度轮流显示;
  13.                          温度显示范围: -9.9℃~99.9℃;
  14.                          增加数码管调亮度功能,按键10级亮度P1.0接10K电阻上拉、光敏电阻下拉分压;
  15.                          环境光线越亮,数码管越亮,反之数码管越暗。
  16. 实物通过.  
  17.                          12MHz晶振,STC15F2K60S2+DS1302时钟芯片+DS18B20,
  18.                          P0口接段位,P2^4~P2^7接pnp三极管控制4个共阳极。
  19. **********************************************************************************/
  20. //#include <STC12C5A60S2.h>
  21. #include <STC15F2K60S2.h>
  22. #include <intrins.h>
  23. #define uchar unsigned char
  24. #define uint unsigned int


  25. sbit TSCLK = P2^2;//时钟线
  26. sbit TIO   = P2^1;//数据线
  27. sbit TRST  = P2^0;//使能端

  28. sbit key1 = P3^4;   //设置键
  29. sbit key2 = P3^3;   //加 /光控开关键(校时的时候做加键,反之为光控开关)
  30. sbit key3 = P3^2;   // 减/显示切换键
  31. sbit DQ = P2^3;                //DS18B20数据口

  32. sbit w1 = P2^4;          //设置位驱动口
  33. sbit w2 = P2^5;
  34. sbit w3 = P2^6;
  35. sbit w4 = P2^7;
  36. sbit w5 = P3^7;         //此位不显示
  37. sbit dd = P1^4;         //蜂鸣器控制端       

  38. uchar xs=0; //显示切换计数变量
  39. uchar tian=0;
  40. uchar knum,shan_cont;
  41. char shi,fen,miao;
  42. uchar ba=40;
  43. uint mh,mh_count,count;
  44. bit shan;           //校时闪烁标志位
  45. uchar s=0;                   //显示负号
  46. uint temp;        //温度值
  47. bit flag;                  //轮流显示标志位
  48. bit flag_gk;          //光控标志位
  49. bit flag_js=0;          //自动校时标志
  50. bit flag_fm;          //蜂鸣器启动标志
  51. uchar fm;                //蜂鸣器计时变量
  52. /***************************************定义转换控制寄存器控制位*****************************************/
  53. #define ADC_POWER                   0X80            //电源控制位
  54. #define ADC_FLAG                    0X10            //转换结束标志位
  55. #define ADC_START                   0X08            //转换开始位
  56. /*********************************************定义AD转换速度*********************************************/
  57. #define ADC_SPEEDLL_540         0X00           
  58. #define ADC_SPEEDLL_360                0X20
  59. #define ADC_SPEEDLL_180                0X40
  60. #define ADC_SPEEDLL_90                0X60
  61. /***********写时分秒地址************/
  62. #define write_shi  0x84
  63. #define write_fen  0x82
  64. #define write_miao 0x80
  65. #define write_ram  0xc0
  66. /***********读时分秒地址************/
  67. #define read_shi  0x85
  68. #define read_fen  0x83
  69. #define read_miao 0x81
  70. #define read_ram  0xc1
  71. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x46,0xbf};//共阳段码 (0--9、黑屏、C、-)

  72. /*********************************************************************************************************
  73. ** 函数功能 :延时函数
  74. ** 函数说明 :利用软件延时,占用CPU
  75. ** 入口参数 :time:需要延时的时间,
  76. ** 出口参数 :无
  77. *********************************************************************************************************/
  78. void Delay_ms(uint time)
  79. {
  80.         uint i,j;
  81.         for(i = 0;i < time;i ++)
  82.                 for(j = 0;j < 45;j ++);
  83. }

  84. /*********************************************************************************************************
  85. ** 函数功能 :延时函数
  86. ** 函数说明 :利用软件延时,占用CPU,经调试最小单位大约为1us
  87. ** 入口参数 :time:需要延时的时间,单位us
  88. ** 出口参数 :无
  89. *********************************************************************************************************/
  90. void delay(uchar n)
  91. {
  92.     while (n--)
  93.     {
  94.         _nop_();
  95.         _nop_();
  96.     }
  97. }

  98. /*****************DS18B20******************/

  99. void Init_Ds18b20(void)     //DS18B20初始化send reset and initialization command
  100. {
  101.         DQ = 1;                     //DQ复位,不要也可行。
  102.         delay(1);                  //稍做延时
  103.         DQ = 0;                    //单片机拉低总线
  104.         //delay(250);                //精确延时,维持至少480us
  105.         EA=0;
  106.         delay(170);
  107.         EA=1;
  108.         DQ = 1;
  109.         EA=0;                    //释放总线,即拉高了总线
  110.         delay(170);                //此处延时有足够,确保能让DS18B20发出存在脉冲。
  111.         EA=1;
  112. }

  113. uchar Read_One_Byte()       //读取一个字节的数据read a byte date
  114.                             //读数据时,数据以字节的最低有效位先从总线移出
  115. {
  116.         uchar i   = 0;
  117.         uchar dat = 0;
  118.         for(i=8;i>0;i--)
  119.         {
  120.            DQ = 0;                  //将总线拉低,要在1us之后释放总线                       //单片机要在此下降沿后的15us内读数据才会有效。
  121.            delay(1);                //至少维持了1us,表示读时序开始
  122.            dat >>= 1;               //让从总线上读到的位数据,依次从高位移动到低位。
  123.            DQ = 1;                  //释放总线,此后DS18B20会控制总线,把数据传输到总线上
  124.            delay(7);                //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
  125.            if(DQ)                   //控制器进行采样
  126.            {
  127.             dat |= 0x80;            //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0
  128.            }
  129.            EA=0;        
  130.            delay(40);              //此延时不能少,确保读时序的长度60us。
  131.            EA=1;
  132.         }
  133.         return (dat);
  134. }

  135. void Write_One_Byte(uchar dat)
  136. {
  137.         uchar i = 0;
  138.         for(i=8;i>0;i--)
  139.         {
  140.            DQ = 0;                        //拉低总线
  141.            delay(1);                       //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
  142.            DQ = dat&0x01;                 //从字节的最低位开始传输
  143.                                          //指令dat的最低位赋予给总线,必须在拉低总线后的15us内,                              //因为15us后DS18B20会对总线采样。
  144.            delay(60);                     //必须让写时序持续至少60us
  145.            DQ = 1;                        //写完后,必须释放总线,
  146.            dat >>= 1;
  147.            delay(1);
  148.         }
  149. }


  150. uint Get_Tmp()                   //获取温度get the temperature
  151. {
  152.         float tt;
  153.         uchar L,M;
  154. EA=0;
  155.         Init_Ds18b20();                //初始化
  156.         Write_One_Byte(0xcc);          //忽略ROM指令
  157.         Write_One_Byte(0x44);          //温度转换指令
  158.         Init_Ds18b20();                 //初始化
  159.         Write_One_Byte(0xcc);          //忽略ROM指令
  160.         Write_One_Byte(0xbe);          //读暂存器指令
  161.         L = Read_One_Byte();           //读取到的第一个字节为温度LSB
  162.         M = Read_One_Byte();           //读取到的第一个字节为温度MSB
  163.         temp = M;                      //先把高八位有效数据赋于temp
  164.         temp <<= 8;                    //把以上8位数据从temp低八位移到高八位
  165.         temp = temp|L;                //两字节合成一个整型变量
  166. EA=1;
  167.         if(M >= 0x08)        //判断是否为负数
  168.         {
  169.                 temp = ~temp + 1;//负数是以补码的形式存放的需要取反加1
  170.                 s = 0xbf;  //显示负数符号
  171.         }
  172.         else s = 0;           //为正数则不显示负数符号

  173.         tt = temp*0.0625;              //得到真实十进制温度值
  174.                                         //因为DS18B20可以精确到0.0625度
  175.                                         //所以读回数据的最低位代表的是0.0625度
  176.         temp = tt*10+0.5;               //放大十倍
  177.                                         //这样做的目的将小数点后第一位也转换为可显示数字
  178.                                //同时进行一个四舍五入操作。
  179.         return temp;
  180. }


  181. /****************温度显示函数**************/

  182. void Display_tem(uint temp)   //显示程序
  183. {
  184.         uchar A1,A2,A3;
  185.         A1 = temp/100;    //百位
  186.         A2 = temp%100/10;   //十位
  187.         A3 = temp%10;    //个位
  188.        
  189.         if(A1 > 0 && s == 0 )
  190.         {
  191.                 P0 = 0xff;
  192.                 w2 = 1; w3 = 1; w4 = 1;
  193.                 Delay_ms(50-ba);
  194.                 P0 = table[A1];    //显示百位
  195.                 w1 = 0;
  196.                 Delay_ms(ba);
  197.         }
  198.         else
  199.         {
  200.                 if(A1 == 0 && s == 0)
  201.                 {
  202.                         P0 = 0xff;
  203.                         w2 = 1; w3 = 1; w4 = 1;
  204.                         Delay_ms(50-ba);
  205.                         P0 = table[10];    //百位为0不显
  206.                         w1 = 0;
  207.                         Delay_ms(ba);
  208.                 }
  209.                 else
  210.                 if(s != 0)
  211.                 {
  212.                         P0 = 0xff;
  213.                         w2 = 1; w3 = 1; w4 = 1;
  214.                         Delay_ms(50-ba);
  215.                         P0 = s;    //百位为负数显示-
  216.                         w1 = 0;
  217.                         Delay_ms(ba);
  218.                 }
  219.                  
  220.        
  221.         }
  222.        
  223.        
  224.         P0 = 0xff;
  225.         w1 = 1; w3 = 1; w4 = 1;
  226.         Delay_ms(50-ba);
  227.         P0 = table[A2]&0X7F;   //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)
  228.         w2 = 0;
  229.         Delay_ms(ba);
  230.        
  231.         P0 = 0xff;
  232.         w1 = 1; w2 = 1;  w4 = 1;
  233.         Delay_ms(50-ba);
  234.         P0 = table[A3];
  235.         w3 = 0;   
  236.         Delay_ms(ba);       
  237.          
  238.         P0 = 0xff;
  239.         w1 = 1; w2 = 1; w3 = 1;
  240.         Delay_ms(50-ba);
  241.         P0 = 0x46;   //显示C字样
  242.         w4 = 0;
  243.         Delay_ms(ba);
  244.        
  245.         P0 = 0xff;
  246.         w1 = 1; w2 = 1; w3 = 1;
  247.         Delay_ms(50-ba);
  248.         P0 = 0xff;   
  249.         w5 = 0;
  250.         P0 = 0xff;
  251.         Delay_ms(ba);       
  252. }



  253. void display( uchar shi,uchar fen)           //时间显示函数
  254. {

  255. /*****正常显示******/
  256.         if(knum == 0)
  257.         {
  258.                 if(shi/10 > 0)
  259.                 {
  260.                         w2 = 1; w3 = 1; w4 = 1;
  261.                         Delay_ms(50-ba);
  262.                         P0 = table[shi/10];    //显示小时十位
  263.                         w1 = 0;
  264.                         Delay_ms(ba);
  265.                 }
  266.                 else
  267.                 {
  268.                         w2 = 1; w3 = 1; w4 = 1;
  269.                         Delay_ms(50-ba);
  270.                         P0 = table[10];    //小时十位为0不显示
  271.                         w1 = 0;
  272.                         Delay_ms(ba);
  273.                
  274.                 }
  275.        
  276.                 P0 = 0xff;
  277.                 w1 = 1; w3 = 1; w4 = 1;
  278.                 Delay_ms(50-ba);
  279.                 if(mh_count>=50)
  280.                 P0 = table[shi%10]&0x7f;    //显示小时个位
  281.                 else
  282.                 P0 = table[shi%10];
  283.                 w2 = 0;
  284.                 Delay_ms(ba);
  285.                  
  286.                 P0 = 0xff;
  287.                 w1 = 1; w2 = 1; w4 = 1;
  288.                 Delay_ms(50-ba);
  289.                 if(mh_count>=50)
  290.                 P0 = table[fen/10]&0x7f;    //显示分钟十位
  291.                 else
  292.                 P0 = table[fen/10];
  293.                 w3 = 0;
  294.                 Delay_ms(ba);
  295.        
  296.                 P0 = 0xff;
  297.                 w2 = 1; w3 = 1; w1 = 1;
  298.                 Delay_ms(50-ba);
  299.                 P0 = table[fen%10];    //显示分钟个位
  300.                 w4 = 0;
  301.                 Delay_ms(ba);
  302.        
  303.                 P0 = 0xff;
  304.                 w1 = 1; w2 = 1; w3 = 1;
  305.                 Delay_ms(50-ba);
  306.                 P0 = 0xff;   
  307.                 w5 = 0;                  //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
  308.                 P0 = 0xff;
  309.                 Delay_ms(ba);       
  310.         }

  311. /********校时小时位闪烁************/

  312.         if(knum==1)
  313.         {
  314.                  if( shan==0 )
  315.                 {
  316.                 w2 = 1; w3 = 1; w4 = 1;
  317.                 Delay_ms(50-ba);
  318.                 P0 = 0xff;    //显示小时十位
  319.                 w1 = 0;
  320.                 Delay_ms(ba);

  321.                 P0 = 0xff;
  322.                 w1 = 1; w3 = 1; w4 = 1;
  323.                 Delay_ms(50-ba);
  324.                 P0 = 0xff;;
  325.                 w2 = 0;
  326.                 Delay_ms(ba);
  327.                 }
  328.        

  329.                 else
  330.                 {
  331.                         w2 = 1; w3 = 1; w4 = 1;
  332.                         Delay_ms(50-ba);
  333.                         P0 = table[shi/10];    //显示小时十位
  334.                         w1 = 0;
  335.                         Delay_ms(ba);
  336.                  
  337.                         P0 = 0xff;
  338.                         w1 = 1; w3 = 1; w4 = 1;
  339.                         Delay_ms(50-ba);
  340.                         P0 = table[shi%10];
  341.                         w2 = 0;
  342.                         Delay_ms(ba);
  343.                 }         
  344.                 P0 = 0xff;
  345.                 w1 = 1; w2 = 1; w4 = 1;
  346.                 Delay_ms(50-ba);
  347.                 P0 = table[fen/10];
  348.                 w3 = 0;
  349.                 Delay_ms(ba);
  350.        
  351.                 P0 = 0xff;
  352.                 w2 = 1; w3 = 1; w1 = 1;
  353.                 Delay_ms(50-ba);
  354.                 P0 = table[fen%10];    //显示分钟个位
  355.                 w4 = 0;
  356.                 Delay_ms(ba);
  357.        
  358.                 P0 = 0xff;
  359.                 w1 = 1; w2 = 1; w3 = 1;
  360.                 Delay_ms(50-ba);
  361.                 P0 = 0xff;   
  362.                 w5 = 0;                  //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
  363.                 P0 = 0xff;
  364.                 Delay_ms(ba);
  365.         }       
  366. /*******校时分钟位闪烁*******/

  367.         if(knum==2 )
  368.         {
  369.                 if(shan==0)
  370.                 {
  371.                 w2 = 1; w1 = 1; w4 = 1;
  372.                 Delay_ms(50-ba);
  373.                 P0 = 0xff;    //显示小时十位
  374.                 w3 = 0;
  375.                 Delay_ms(ba);

  376.                 P0 = 0xff;
  377.                 w1 = 1; w3 = 1; w2 = 1;
  378.                 Delay_ms(50-ba);
  379.                 P0 = 0xff;;
  380.                 w4 = 0;
  381.                 Delay_ms(ba);
  382.                 }
  383.                 else
  384.                 {
  385.                         w2 = 1; w1 = 1; w4 = 1;
  386.                         Delay_ms(50-ba);
  387.                         P0 = table[fen/10];    //显示小时十位
  388.                         w3 = 0;
  389.                         Delay_ms(ba);
  390.                  
  391.                         P0 = 0xff;
  392.                         w1 = 1; w3 = 1; w3 = 1;
  393.                         Delay_ms(50-ba);
  394.                         P0 = table[fen%10];
  395.                         w4 = 0;
  396.                         Delay_ms(ba);
  397.                 }         

  398.                 P0 = 0xff;
  399.                 w3 = 1; w2 = 1; w4 = 1;
  400.                 Delay_ms(50-ba);
  401.                 P0 = table[shi/10];
  402.                 w1 = 0;
  403.                 Delay_ms(ba);
  404.        
  405.                 P0 = 0xff;
  406.                 w4 = 1; w3 = 1; w1 = 1;
  407.                 Delay_ms(50-ba);
  408.                 P0 = table[shi%10];    //显示分钟个位
  409.                 w2 = 0;
  410.                 Delay_ms(ba);


  411.        
  412.                 P0 = 0xff;
  413.                 w1 = 1; w2 = 1; w3 = 1;
  414.                 Delay_ms(50-ba);
  415.                 P0 = 0xff;   
  416.                 w5 = 0;                  //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
  417.                 P0 = 0xff;
  418.                 Delay_ms(ba);
  419.         }               
  420.        
  421. }


  422. void t0_init()
  423. {
  424.         TMOD |= 0x01;  //定时器0,16位模式
  425.         TL0 = 0xF0;                //设置定时初值 10毫秒初值 @12MHz
  426.         TH0 = 0xD8;                //设置定时初值
  427.         EA=1;
  428.         ET0=1;
  429.         TR0 = 1;
  430. }





  431. /*********************************************************************************************************
  432. ** 函数功能 :内置ADC的初始化配置
  433. ** 函数说明 :使用内置ADC时需要先配置对应的P1口的管脚为模拟输入
  434. ** 入口参数 :port:需要配置为模拟输入的通道,使用或运算可以同时配置多个管脚
  435. **                          如:ADC_Init(ADC_PORT0 | ADC_PORT1 | ADC_PORT2)调用此函数后可以同时配置P1^0,P1^1,P1^2为模拟输入
  436. ** 出口参数 :无
  437. *********************************************************************************************************/

  438. void ADC_Init()
  439. {
  440.         P1ASF=0x01;//设置AD转换通道 P1.0
  441.         ADC_RES=0;//清空转换结果
  442.         ADC_CONTR=ADC_POWER | ADC_SPEEDLL_540;//打开AD转化器电源
  443.         _nop_();
  444.         _nop_();
  445.         _nop_();
  446.         _nop_();
  447. }
  448. /*********************************************************************************************************
  449. ** 函数功能 :获取ADC对应通道的值,查询法
  450. ** 函数说明 :每次只能获取一个通道的值,不同通道需要分别调用该函数获取
  451. ** 入口参数 :
  452. ** 出口参数 :
  453. *********************************************************************************************************/
  454. uchar GetADCResult()//读取通道ch的电压值
  455. {
  456.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL_540 | ADC_START;//开始转换,并设置测量通道为P1^0
  457.         _nop_();//需经过四个CPU时钟延时,上述值才能保证被设进ADC_CONTR控制寄存器
  458.         _nop_();
  459.         _nop_();
  460.         _nop_();
  461.         while(!(ADC_CONTR & ADC_FLAG));//等待转换结束
  462.         ADC_CONTR &= ~ADC_FLAG;//软件清除中断控制位
  463.         return         ADC_RES;
  464. }
  465. void timer0() interrupt 1

  466. {

  467.         TL0 = 0xF0;                //重装定时初值 10毫秒初值 @12MHz
  468.         TH0 = 0xD8;                //重装定时初值

  469.        
  470.         mh_count++;                  //冒号闪烁变量
  471.         if(mh_count==100) //1秒时间到
  472.         {
  473.                 mh_count=0;
  474.                 count++;
  475.                 if(count==5)
  476.                 {
  477.                         count=0;
  478.                         flag = !flag;
  479.                 }
  480.         }


  481.         if(knum != 0)  //调时间的时候,闪烁的位表示为调节的位
  482.     {
  483.                 shan_cont++;
  484.         if(shan_cont==30)  //设置时,300ms闪烁时间,可根据实际效果调整
  485.         {
  486.                 shan_cont=0;
  487.                 shan = !shan;
  488.         }
  489.     }

  490.         if(flag_fm)         //如果蜂鸣器启动标志为1
  491.         {
  492.                 dd = 0;           //蜂鸣器响
  493.                 fm++;           //计时变量自加
  494.                 if(fm == 30) //到300ms,蜂鸣器停
  495.                 {
  496.                         fm = 0;         //计时变量清零
  497.                         dd = 1;        // 蜂鸣器停
  498.                         flag_fm = 0;//启动标志清零
  499.                 }

  500.         }
  501. }  


  502. //写DS1302数据
  503. void Write_DS1302_DAT(uchar cmd, uchar dat)
  504. {
  505. uchar i;
  506. /****************************************/               
  507.         TSCLK = 1;                         //把复位线拿高
  508.         for(i=0;i<8;i++)
  509.         {                                     //低位在前
  510.                 TRST = 0;                 //时钟线拿低开始写数据
  511.                 TIO = cmd & 0x01;           
  512.                 cmd >>= 1;                 //把地址右移一位
  513.                 TRST = 1;                 //时钟线拿高
  514.         }       
  515.         for(i=0;i<8;i++)
  516.         {
  517.                 TRST = 0;                 //时钟线拿低开始写数据
  518.                 TIO = dat & 0x01;
  519.                 dat >>= 1;                 //把数据右移一位
  520.                 TRST = 1;                 //时钟线拿高
  521.         }
  522.         TSCLK = 0;                         //复位线合低
  523.         TRST = 0;
  524.         TIO = 0;
  525. /**************************************/
  526. }
  527. //读DS1302数据
  528. uchar Read_DS1302_DAT(uchar cmd)
  529. {
  530.         uchar i, dat;
  531. /*************************************************/

  532.         TSCLK = 1; //拉低数据总线
  533.         for(i = 0; i < 8; i++)//每次写1位,写8次
  534.         {
  535.                 TRST = 0;                 //拉低时钟总线
  536.                 TIO = cmd & 0x01;//写1位数据,从最低位开始写
  537.                 cmd >>=1;                 //右移一位
  538.                 TRST = 1;                 //拉高时钟总线,产生上升沿数据被DS1302读走

  539.         }
  540.         for(i = 0; i < 8; i++)//每次读1位,读8次
  541.         {
  542.                 TRST = 0;                  //拉低时钟总线,产生下降沿,DS1302把数据放到TIO上
  543.                 dat >>= 1;                  //右移一位
  544.                 if(TIO==1)        dat |= 0x80;//读取数据,从最低位开始
  545.                 TRST = 1;                        //拉高时钟总线,以备下一次产生下降沿
  546.         }
  547.         TSCLK=0;
  548.         TRST=0;
  549.         TIO=0;

  550.         return dat;        //返回读出数据

  551. /************************************************/


  552. }


  553. //数据转BCD码
  554. uchar Dat_Chg_BCD(uchar dat)
  555. {
  556.         uchar dat1, dat2;
  557.         dat1 = dat / 10;
  558.         dat2 = dat % 10;
  559.         dat2 = dat2 + dat1 * 16;
  560.         return dat2;
  561. }       


  562. //BCD码转换为数据
  563. uchar BCD_Chg_Dat(uchar dat)
  564. {
  565.         uchar dat1, dat2;
  566.         dat1 = dat / 16;
  567.         dat2 = dat % 16;
  568.         dat2 = dat2 + dat1 * 10;
  569.         return dat2;
  570. }


  571. void init_1302()                //初始化函数 设置时间
  572. {                                                //加备用电池,掉电走时

  573.         if(Read_DS1302_DAT(read_ram) != 0xaa) //如果第00个RAM位置不等于0xaa,就初始化1302
  574.         {
  575.                 Write_DS1302_DAT(0x8e, 0);//清除写保护
  576.         Write_DS1302_DAT(write_miao, Dat_Chg_BCD(Read_DS1302_DAT(0x81)));//调时钟芯片秒(并且进行BCD码转换)
  577.                 Write_DS1302_DAT(write_fen, Dat_Chg_BCD(Read_DS1302_DAT(0x83)));//调时钟芯片分
  578.                 Write_DS1302_DAT(write_shi, Dat_Chg_BCD(Read_DS1302_DAT(0x85)));//调时钟芯片时
  579.                 Write_DS1302_DAT(write_ram,0xaa);//写入初始化标志RAM(第00个RAM位置)
  580.                 Write_DS1302_DAT(0x8e, 0x80);//开写保护
  581.         }
  582. }

  583. void read_sf()
  584. {

  585.         miao = BCD_Chg_Dat(Read_DS1302_DAT(0x81));//读秒寄存器(并且进行BCD码转换)
  586.         fen        = BCD_Chg_Dat(Read_DS1302_DAT(0x83));//读分寄存器
  587.         shi = BCD_Chg_Dat(Read_DS1302_DAT(0x85));//读时寄存器
  588. }

  589. void keysan()
  590. {
  591.     static bit kf1=0, kf3=0,kf2=0;  //自锁标志,这里一定要加static(或者用全局变量),否则按键不灵
  592.     static uint i=0,j=0,k=0,m=0,n=0;        //消抖延时变量
  593.                
  594.         if(key1==1)                //设置         //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
  595.         {       
  596.         i=0;           //按键消抖计时变量清零
  597.         kf1=0;           //按键自锁标志清零
  598.         }
  599.         else if(kf1 == 0)        //有按键按下,且是第一次被按下
  600.         {       
  601.         flag_fm = 1;         //启动蜂鸣器
  602.                 ++i;
  603.         if(i>10)                   //i>10  ADC查询方式用
  604.         {
  605.             i=0;
  606.             kf1=1;         //自锁按键置位,避免一直触发
  607.             knum++;
  608.                         if(knum==1)
  609.                         {
  610.                                 Write_DS1302_DAT(0x8e,0x00);                //写保护取消
  611.                                 Write_DS1302_DAT(write_miao,0x80); //  写秒80,时钟停止走时;
  612.                        
  613.                         }
  614.             if(knum==3)
  615.                         {
  616.                                  knum = 0;

  617.                                 Write_DS1302_DAT(write_miao,0x00);
  618.                                 Write_DS1302_DAT(0x8e,0x80);                //保护启动

  619.                         }
  620.         }        
  621.         }
  622. /************显示和光控切换****************/
  623.         if(knum == 0)
  624.         {
  625.                 if(key3==1)                //设置         //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
  626.                 {       
  627.                 m=0;           //按键消抖计时变量清零
  628.                 kf3=0;           //按键自锁标志清零
  629.                 }
  630.                 else if(kf3 == 0)        //有按键按下,且是第一次被按下
  631.                 {        flag_fm = 1;         //启动蜂鸣器
  632.                 ++m;
  633.                 if(m>10)                   //i>10  ADC查询方式用
  634.                 {
  635.                     m=0;
  636.                     kf3=1;         //自锁按键置位,避免一直触发
  637.                     xs++;
  638.                    if(xs==3)
  639.                                 {
  640.                                          xs = 0;
  641.        
  642.                                 }
  643.                 }        
  644.                 }

  645.                 if(key2==1)                //设置         //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
  646.                 {
  647.                 n=0;           //按键消抖计时变量清零
  648.                 kf2=0;           //按键自锁标志清零
  649.                 }
  650.                 else if(kf2 == 0)        //有按键按下,且是第一次被按下
  651.                 {        flag_fm = 1;         //启动蜂鸣器
  652.                 ++n;
  653.                 if(n>10)                   //i>10  ADC查询方式用
  654.                 {
  655.                     n=0;
  656.                     kf2=1;         //自锁按键置位,避免一直触发
  657.                                 flag_gk = !flag_gk;
  658.                 }        
  659.                 }


  660.         }



  661. ///-------加--------///
  662.         if(knum != 0)
  663.         {
  664.                 if(key2==0)                //加
  665.             {  
  666.                        
  667.                 j++;
  668.         //        if(j >= 5000)           //长按连加 ADC中断方式用
  669.                 if(j >= 100)           //长按连加 ADC查询方式用
  670.        
  671.                 {   //flag_fm = 0;                                    
  672.                     if(knum==2)
  673.                     {
  674.                                 fen++;
  675.                                 fen=fen/10*16+fen%10;                //转为16进制
  676.                                 if(fen==0x60)
  677.                                             fen=0x00;
  678.                                         Write_DS1302_DAT(write_fen,fen);
  679.                                 read_sf();                                        //读出时间,然后显示
  680.                     }
  681.        
  682.                     if(knum==1)
  683.                     {
  684.                                         shi++;
  685.                                         shi=shi/10*16+shi%10;                //转为16进制
  686.                                         if(shi==0x24)
  687.                                                 shi=0x00;
  688.                                         Write_DS1302_DAT(write_shi,shi);
  689.                                         read_sf();
  690.                     }
  691.        
  692.                     j=90;           //这里j的值可以设置连加的快慢,j的值越大就越快
  693.                                                         //因为初值越大,加到100的时间就越短
  694.                                 flag_fm = 1;  //启动蜂鸣器
  695.                         }                           
  696.             }        
  697.        
  698.             else
  699.             {
  700.                 if(j>10 && j<100) //短按
  701.                 {
  702.                     flag_fm = 1;         //启动蜂鸣器   
  703.                     if(knum==2)
  704.                     {
  705.                                 fen++;
  706.                                 fen=fen/10*16+fen%10;                //转为16进制
  707.                                 if(fen==0x60)
  708.                                     fen=0x00;
  709.                                         Write_DS1302_DAT(write_fen,fen);
  710.                                 read_sf();                                        //读出时间,然后显示
  711.                     }
  712.        
  713.                     if(knum==1)
  714.                     {
  715.                                         shi++;
  716.                                         shi=shi/10*16+shi%10;                //转为16进制
  717.                                         if(shi==0x24)
  718.                                                 shi=0x00;
  719.                                        
  720.                                         Write_DS1302_DAT(write_shi,shi);
  721.                                         read_sf();
  722.                     }
  723.        
  724.                         j=0;
  725.                     }
  726.                 }        
  727.    
  728. //----------减-----------//   
  729.         if(key3==0)                //减
  730.     {           flag_fm = 1;         //启动蜂鸣器
  731.             k++;
  732.             if(k >= 100)           //长按
  733.             {
  734.                     if(knum==2)
  735.                     {
  736.                                                 fen--;
  737.                                                 fen=fen/10*16+fen%10;                //转为16进制
  738.                                                 if(fen==-1)
  739.                                                 fen=0x59;
  740.                                                 Write_DS1302_DAT(write_fen,fen);
  741.                                                 read_sf();
  742.                     }

  743.                     if(knum==1)
  744.                     {
  745.                                                 shi--;
  746.                                                 shi=shi/10*16+shi%10;                //转为16进制
  747.                                                 if(shi==-1)
  748.                                                 shi=0x23;
  749.                                                 Write_DS1302_DAT(write_shi,shi);
  750.                                                 read_sf();
  751.                     }

  752.                     k=90;
  753.             }
  754.     }        

  755.     else
  756.     {
  757.             if(k>10 && k<100) //短按
  758.             {
  759.                     flag_fm = 1;         //启动蜂鸣器        
  760.                     if(knum==2)
  761.                     {
  762.                                                 fen--;
  763.                                                 fen=fen/10*16+fen%10;                //转为16进制
  764.                                                 if(fen==-1)
  765.                                                 fen=0x59;
  766.                                                 Write_DS1302_DAT(write_fen,fen);
  767.                                                 read_sf();
  768.                     }

  769.                     if(knum==1)
  770.                     {
  771.                                                 shi--;
  772.                                                 shi=shi/10*16+shi%10;                //转为16进制
  773.                                                 if(shi==-1)
  774.                                                 shi=0x23;
  775.                                                 Write_DS1302_DAT(write_shi,shi);
  776.                                                 read_sf();
  777.                     }

  778.             }
  779.             k=0;        //消抖变量清零,为下次按键做准备        
  780.         }
  781.         }                
  782. }


  783. void main()
  784. {       
  785.         t0_init();
  786.         read_sf();
  787.         init_1302();
  788.         ADC_Init();
  789.         flag_fm = 1;         //启动蜂鸣器
  790.         while(1)
  791.         {

  792.            read_sf();
  793.            switch(xs)
  794.            {
  795.                         case 0:if(flag==0 && knum == 0)         //时间、温度轮流显示,5秒切换一次
  796.                                            {Display_tem(Get_Tmp());}
  797.                                            else       
  798.                                            display( shi,fen);        break;
  799.                         case 1: display( shi,fen);  break;         //显示时间
  800.                         case 2: Display_tem(Get_Tmp()); break;//显示温度
  801.                         default: break;
  802.            }
  803.            keysan();
  804.                 if(shi>=5 && shi<=21) ba=20;else ba=1;//5~21 亮度最大,22~4 亮度最小
  805.                 if(!flag_gk)                //如果光控标志为0,就为自动亮度        ;默认为自动亮度
  806.                 {
  807.                         if(GetADCResult()>5 && GetADCResult()<25) ba=40;
  808.                         if(GetADCResult()>25 && GetADCResult()<50) ba=39; //10级亮度,ba值越大,LED越亮
  809.                         if(GetADCResult()>50 && GetADCResult()<80) ba=35;
  810.                         if(GetADCResult()>80 && GetADCResult()<100) ba=30;
  811.                         if(GetADCResult()>100 && GetADCResult()<130) ba=25;
  812.                         if(GetADCResult()>130 && GetADCResult()<150) ba=20;
  813.                         if(GetADCResult()>150 && GetADCResult()<180) ba=15;
  814.                         if(GetADCResult()>180 && GetADCResult()<200) ba=10;
  815.                         if(GetADCResult()>200 && GetADCResult()<230) ba=5;
  816.                         if(GetADCResult()>230 && GetADCResult()<250) ba=1;
  817.                 }
  818.                 else ba = 40; // 否则为最大亮度
  819.                 if((shi>=5 && shi<=21) && fen ==0 && miao == 0) //整点报时
  820.                 {
  821.                         flag_fm = 1;
  822.                 }
  823.          
  824.         }
  825. }


  826. char shifen,baifen,ge,result;

  827. void adc_isr() interrupt 5 using 1
  828. {
  829.         unsigned int temp;
  830.         temp=ADC_RES;                         //AD取8位结果
  831.         result=temp*0.01953125*1000;   //ad结果换算成电压值, 将5V分成256份,每份5v/256=0.01953125v        ,再扩大1000倍
  832.         ge=result/1000;
  833.         shifen=result%1000/100;
  834.         baifen=result%100/10;
  835.         
  836.        ADC_CONTR = 0xc8;//开启转换
  837. }
复制代码



IMG_20230702_1.jpg
IMG_20230702_2.jpg
IMG_20230702_3.jpg

1.2寸数码管时钟_温度_光控_双面制版上传20230702修改版.rar

611.95 KB, 下载次数: 18, 下载积分: 黑币 -5

回复

使用道具 举报

ID:378402 发表于 2023-7-2 18:52 | 显示全部楼层
程序调整后,原理图未调整,图片发不了,只能文字叙述。USB的D+连接单片机的P3.1;USB的D-连接单片机的P3.2不变,调整SW2原连接P3.1改为连接P3.3;调整SW1原连接P3.0改为连接P3.4,主要解决下载程序问题。另一处需要调整的是:时钟芯片的SCLK原连接P2.0改为连接P2.2;RST原连接P2.2改为连接P2.0。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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