本帖最后由 lids 于 2018-12-21 08:41 编辑
描述: 4位共阳1寸数码管时钟,显示88:88样式,正常走时的时候,“:”1秒亮灭1次;调时间的的时候冒号熄灭
调时:按KEY1按键第1次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
按KEY1按键第2次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
校时的时候先调好时、分,分钟要比参考时间的分钟加1分,
再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时就比较准了,因为KEY1按键按第3次后秒会清零。
加备用电池,掉电走时
KEY2键第2功能:非调时状态,为光控开关;
KEY3键第2功能:非调时状态,为显示切换开关;
DS18B20做温度检测, 可显示3个界面:1.实时时钟与温度轮流显示、2.只显示温度、3.只显示时间;
温度显示范围: -9.9℃~99.9℃;
增加数码管调亮度功能,自动10级亮度,P1.0接5.1K电阻上拉、光敏电阻下拉分压;
环境光线越亮,数码管越亮,反之数码管越暗,晚上看不刺眼。
实物通过.
12MHz晶振,STC12C5A60S2+DS1302时钟芯片+DS18B20,
P0口接段位,P2^4~P2^7接pnp三极管控制4个共阳极。
制作出来的实物图如下:
附件里有完整C文件,PCB文件,原理图
- /*********************************************************************************
- 描述: 4位共阳数码管时钟,显示88:88样式,正常走时的时候,“:”1秒闪烁2次;调时间的的时候冒号熄灭
- 调时:按KEY1按键第1次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
- 按KEY1按键第2次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
- 按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
- 校时的时候先调好时、分,分钟要比参考时间的分钟加1分,
- 再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时就比较准了。
- 加备用电池,掉电走时
-
- KEY2键第2功能:非调时状态,为光控开关;
- KEY3键第2功能:非调时状态,为显示切换开关;
- DS18B20做温度检测,实时时钟与温度轮流显示;
- 温度显示范围: -9.9℃~99.9℃;
- 增加数码管调亮度功能,按键10级亮度P1.0接5.1K电阻上拉、光敏电阻下拉分压;
- 环境光线越亮,数码管越亮,反之数码管越暗。
- 实物通过.
- 12MHz晶振,STC12C5A60S2+DS1302时钟芯片+DS18B20,
- P0口接段位,P2^4~P2^7接pnp三极管控制4个共阳极。
- **********************************************************************************/
- #include <STC12C5A60S2.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit TSCLK = P2^0;//时钟线
- sbit TIO = P2^1;//数据线
- sbit TRST = P2^2;//使能端
- sbit key1 = P3^0; //设置键
- sbit key2 = P3^1; //加 /光控开关键(校时的时候做加键,反之为光控开关)
- sbit key3 = P3^2; // 减/显示切换键
- sbit DQ = P2^3; //DS18B20数据口
- sbit w1 = P2^4; //设置位驱动口
- sbit w2 = P2^5;
- sbit w3 = P2^6;
- sbit w4 = P2^7;
- sbit w5 = P3^7; //此位不显示
- sbit dd = P1^4; //蜂鸣器控制端
- uchar xs=0; //显示切换计数变量
- uchar knum,shan_cont;
- char shi,fen,miao;
- uchar ba=40;
- uint mh,mh_count,count;
- bit shan; //校时闪烁标志位
- uchar s=0; //显示负号
- uint temp; //温度值
- bit flag; //轮流显示标志位
- bit flag_gk; //光控标志位
- bit flag_js=0; //自动校时标志
- bit flag_fm; //蜂鸣器启动标志
- uchar fm; //蜂鸣器计时变量
- /***************************************定义转换控制寄存器控制位*****************************************/
- #define ADC_POWER 0X80 //电源控制位
- #define ADC_FLAG 0X10 //转换结束标志位
- #define ADC_START 0X08 //转换开始位
- /*********************************************定义AD转换速度*********************************************/
- #define ADC_SPEEDLL_540 0X00
- #define ADC_SPEEDLL_360 0X20
- #define ADC_SPEEDLL_180 0X40
- #define ADC_SPEEDLL_90 0X60
- /***********写时分秒地址************/
- #define write_shi 0x84
- #define write_fen 0x82
- #define write_miao 0x80
- #define write_ram 0xc0
- /***********读时分秒地址************/
- #define read_shi 0x85
- #define read_fen 0x83
- #define read_miao 0x81
- #define read_ram 0xc1
- uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x46,0xbf};//共阳段码 (0--9、黑屏、C、-)
- /*********************************************************************************************************
- ** 函数功能 :延时函数
- ** 函数说明 :利用软件延时,占用CPU
- ** 入口参数 :time:需要延时的时间,
- ** 出口参数 :无
- *********************************************************************************************************/
- void Delay_ms(uint time)
- {
- uint i,j;
- for(i = 0;i < time;i ++)
- for(j = 0;j < 45;j ++);
- }
- /******************************/
- //void Delay_1(uint time)
- //{
- // uint i,j;
- // for(i = 0;i < time;i ++)
- // for(j = 0;j < 600;j ++);
- //}
- /*********************************************************************************************************
- ** 函数功能 :延时函数
- ** 函数说明 :利用软件延时,占用CPU,经调试最小单位大约为1us
- ** 入口参数 :time:需要延时的时间,单位us
- ** 出口参数 :无
- *********************************************************************************************************/
- void delay(uchar n)
- {
- while (n--)
- {
- _nop_();
- _nop_();
- }
- }
- /*************蜂鸣器*****************/
- //void didi(uchar i)
- //{
- // uchar x;
- // for(x = i; x >0; x--)
- // {
- // dd = 0;
- // Delay_1(200);
- // dd = 1;
- // Delay_1(200);
- // }
- //}
- /*****************DS18B20******************/
- void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
- {
- DQ = 1; //DQ复位,不要也可行。
- delay(1); //稍做延时
- DQ = 0; //单片机拉低总线
- //delay(250); //精确延时,维持至少480us
- delay(240);
- delay(240);
- DQ = 1; //释放总线,即拉高了总线
- delay(240); //此处延时有足够,确保能让DS18B20发出存在脉冲。
- }
- uchar Read_One_Byte() //读取一个字节的数据read a byte date
- //读数据时,数据以字节的最低有效位先从总线移出
- {
- uchar i = 0;
- uchar dat = 0;
- for(i=8;i>0;i--)
- {
- DQ = 0; //将总线拉低,要在1us之后释放总线
- //单片机要在此下降沿后的15us内读数据才会有效。
- delay(1); //至少维持了1us,表示读时序开始
- dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。
- DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上
- delay(7); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
- if(DQ) //控制器进行采样
- {
- dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0
- }
- delay(60); //此延时不能少,确保读时序的长度60us。
- }
- return (dat);
- }
- void Write_One_Byte(uchar dat)
- {
- uchar i = 0;
- for(i=8;i>0;i--)
- {
- DQ = 0; //拉低总线
- delay(1); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
- DQ = dat&0x01; //从字节的最低位开始传输
- //指令dat的最低位赋予给总线,必须在拉低总线后的15us内,
- //因为15us后DS18B20会对总线采样。
- delay(60); //必须让写时序持续至少60us
- DQ = 1; //写完后,必须释放总线,
- dat >>= 1;
- delay(1);
- }
- }
- uint Get_Tmp() //获取温度get the temperature
- {
- float tt;
- uchar L,M;
- Init_Ds18b20(); //初始化
- Write_One_Byte(0xcc); //忽略ROM指令
- Write_One_Byte(0x44); //温度转换指令
- Init_Ds18b20(); //初始化
- Write_One_Byte(0xcc); //忽略ROM指令
- Write_One_Byte(0xbe); //读暂存器指令
- L = Read_One_Byte(); //读取到的第一个字节为温度LSB
- M = Read_One_Byte(); //读取到的第一个字节为温度MSB
- //模拟显示-0.5度,实际测温需注解掉下面这两句
- // L = 0xf8;
- // M = 0xff;
-
- //模拟显示+0.5度,实际测温需注解掉下面这两句
- // L = 0x08;
- // M = 0x00;
- temp = M; //先把高八位有效数据赋于temp
- temp <<= 8; //把以上8位数据从temp低八位移到高八位
- temp = temp|L; //两字节合成一个整型变量
- if(M >= 0x08) //判断是否为负数
- {
- temp = ~temp + 1;//负数是以补码的形式存放的需要取反加1
- s = 0xbf; //显示负数符号
- }
- else s = 0; //为正数则不显示负数符号
- tt = temp*0.0625; //得到真实十进制温度值
- //因为DS18B20可以精确到0.0625度
- //所以读回数据的最低位代表的是0.0625度
- temp = tt*10+0.5; //放大十倍
- //这样做的目的将小数点后第一位也转换为可显示数字
- //同时进行一个四舍五入操作。
- return temp;
- }
- /****************温度显示函数**************/
- void Display_tem(uint temp) //显示程序
- {
- uchar A1,A2,A3;
- A1 = temp/100; //百位
- A2 = temp%100/10; //十位
- A3 = temp%10; //个位
-
- if(A1 > 0 && s == 0 )
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A1]; //显示百位
- w1 = 0;
- Delay_ms(ba);
- }
- else
- {
- if(A1 == 0 && s == 0)
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[10]; //百位为0不显
- w1 = 0;
- Delay_ms(ba);
- }
- else
- if(s != 0)
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = s; //百位为负数显示-
- w1 = 0;
- Delay_ms(ba);
- }
-
-
- }
-
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A2]&0X7F; //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A3];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0x46; //显示C字样
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0;
- P0 = 0xff;
- Delay_ms(ba);
- }
- void display( uchar shi,uchar fen) //时间显示函数
- {
- /*****正常显示******/
- if(knum == 0)
- {
- if(shi/10 > 0)
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10]; //显示小时十位
- w1 = 0;
- Delay_ms(ba);
- }
- else
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[10]; //小时十位为0不显示
- w1 = 0;
- Delay_ms(ba);
-
- }
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- if(mh_count>=50)
- P0 = table[shi%10]&0x7f; //显示小时个位
- else
- P0 = table[shi%10];
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- if(mh_count>=50)
- P0 = table[fen/10]&0x7f; //显示分钟十位
- else
- P0 = table[fen/10];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w2 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10]; //显示分钟个位
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
- /********校时小时位闪烁************/
- // P0 = 0xff;
- if(knum==1)
- {
- if( shan==0 )
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff; //显示小时十位
- w1 = 0;
- Delay_ms(ba);
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;;
- w2 = 0;
- Delay_ms(ba);
- }
-
- else
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10]; //显示小时十位
- w1 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi%10];
- w2 = 0;
- Delay_ms(ba);
- }
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[fen/10];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w2 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10]; //显示分钟个位
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
- /*******校时分钟位闪烁*******/
- if(knum==2 )
- {
- if(shan==0)
- {
- w2 = 1; w1 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff; //显示小时十位
- w3 = 0;
- Delay_ms(ba);
- P0 = 0xff;
- w1 = 1; w3 = 1; w2 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;;
- w4 = 0;
- Delay_ms(ba);
- }
- else
- {
- w2 = 1; w1 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[fen/10]; //显示小时十位
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10];
- w4 = 0;
- Delay_ms(ba);
- }
- P0 = 0xff;
- w3 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10];
- w1 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w4 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[shi%10]; //显示分钟个位
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //这里扫描一个空位,数码管前4位亮度就均匀了,第4位与前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
-
- }
- void t0_init()
- {
- // TMOD |= 0x02; //定时器0,8位自动重装模式
- // TH0=TL0= 0X9c; //100微秒初值 @12MHz
- // TH0=TL0= 0Xce; //50微秒初值 @12MHz
- TMOD |= 0x01; //定时器0,16位模式
- TL0 = 0xF0; //设置定时初值 10毫秒初值 @12MHz
- TH0 = 0xD8; //设置定时初值
- EA=1;
- ET0=1;
- TR0 = 1;
- // EADC=1;
- }
- //void InitADC()
- //{
- // P1ASF = 0x01;//使能P1.0口ADC功能
- // ADC_RES = 0; //初始AD转换结果为零
- // ADC_CONTR = 0xc8; //1100 1000 ,打开AD转换电源,转换速度180个时钟周期,ADC_FLAG清零,ADC_START置1启动AD,选择P1.0为AD输入通道
- // Delay_ms(1);
- //}
- /*********************************************************************************************************
- ** 函数功能 :内置ADC的初始化配置
- ** 函数说明 :使用内置ADC时需要先配置对应的P1口的管脚为模拟输入
- ** 入口参数 :port:需要配置为模拟输入的通道,使用或运算可以同时配置多个管脚
- ** 如:ADC_Init(ADC_PORT0 | ADC_PORT1 | ADC_PORT2)调用此函数后可以同时配置P1^0,P1^1,P1^2为模拟输入
- ** 出口参数 :无
- *********************************************************************************************************/
- void ADC_Init()
- {
- P1ASF=0x01;//设置AD转换通道 P1.0
- ADC_RES=0;//清空转换结果
- ADC_CONTR=ADC_POWER | ADC_SPEEDLL_540;//打开AD转化器电源
- // IE=0XA0;//开启总中断,ADC中断
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- /*********************************************************************************************************
- ** 函数功能 :获取ADC对应通道的值,查询法
- ** 函数说明 :每次只能获取一个通道的值,不同通道需要分别调用该函数获取
- ** 入口参数 :
- ** 出口参数 :
- *********************************************************************************************************/
- uchar GetADCResult()//读取通道ch的电压值
- {
- // unsigned int ADC_RESULT = 0;//用来存放结果
- // float result;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL_540 | ADC_START;//开始转换,并设置测量通道为P1^0
- _nop_();//需经过四个CPU时钟延时,上述值才能保证被设进ADC_CONTR控制寄存器
- _nop_();
- _nop_();
- _nop_();
- while(!(ADC_CONTR & ADC_FLAG));//等待转换结束
- ADC_CONTR &= ~ADC_FLAG;//软件清除中断控制位
- // ADC_RESULT = ADC_RES;
- // ADC_RESULT = (ADC_RESULT << 2) | (0x02 & ADC_RESL); //默认数据存储方式:高八位在ADC_RES,低二位在ADC_RESL低二位
- // result = ADC_RESULT * 5.0 / 1024.0 ; //基准电压为电源电压5V,10的分辨率,即1024
- // return result;
- return ADC_RES;
- }
- void timer0() interrupt 1
- {
- TL0 = 0xF0; //重装定时初值 10毫秒初值 @12MHz
- TH0 = 0xD8; //重装定时初值
-
- mh_count++; //冒号闪烁变量
- if(mh_count==100) //1秒时间到
- {
- mh_count=0;
- count++;
- if(count==5)
- {
- count=0;
- flag = !flag;
- }
- }
- if(knum != 0) //调时间的时候,闪烁的位表示为调节的位
- {
- shan_cont++;
- if(shan_cont==30) //设置时,300ms闪烁时间,可根据实际效果调整
- {
- shan_cont=0;
- shan = !shan;
- }
- }
- if(flag_fm) //如果蜂鸣器启动标志为1
- {
- dd = 0; //蜂鸣器响
- fm++; //计时变量自加
- if(fm == 30) //到300ms,蜂鸣器停
- {
- fm = 0; //计时变量清零
- dd = 1; // 蜂鸣器停
- flag_fm = 0;//启动标志清零
- }
- }
- }
- //写DS1302数据
- void Write_DS1302_DAT(uchar cmd, uchar dat)
- {
- uchar i;
- TRST = 0; //拉低使能端
- TSCLK = 0;//拉低数据总线
- TRST = 1; //拉高使能端,产生上升沿开始写数据
- for(i = 0; i < 8; i++)//每次写1位,写8次
- {
- TSCLK = 0; //拉低时钟总线
- TIO = cmd & 0x01; //写1位数据,从最低位开始写
- TSCLK = 1; //拉高时钟总线,产生上升沿数据被DS1302读走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次写1位,写8次
- {
- TSCLK = 0; //拉低时钟总线
- TIO = dat & 0x01; //写1位数据,从最低位开始写
- TSCLK = 1; //拉高时钟总线,产生上升沿数据被DS1302读走
- dat >>= 1; //右移一位
- }
- }
- //读DS1302数据
- uchar Read_DS1302_DAT(uchar cmd)
- {
- uchar i, dat;
- TRST = 0; //拉低使能端
- TSCLK = 0; //拉低数据总线
- TRST = 1; //拉高使能端,产生上升沿开始写数据
- for(i = 0; i < 8; i++)//每次写1位,写8次
- {
- TSCLK = 0; //拉低时钟总线
- TIO = cmd & 0x01;//写1位数据,从最低位开始写
- TSCLK = 1; //拉高时钟总线,产生上升沿数据被DS1302读走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次读1位,读8次
- {
- TSCLK = 0; //拉低时钟总线,产生下降沿,DS1302把数据放到TIO上
- dat >>= 1; //右移一位
- if(TIO) dat |= 0x80;//读取数据,从最低位开始
- TSCLK = 1; //拉高时钟总线,以备下一次产生下降沿
- }
- return dat; //返回读出数据
- }
- //数据转BCD码
- uchar Dat_Chg_BCD(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 10;
- dat2 = dat % 10;
- dat2 = dat2 + dat1 * 16;
- return dat2;
- }
- //BCD码转换为数据
- uchar BCD_Chg_Dat(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 16;
- dat2 = dat % 16;
- dat2 = dat2 + dat1 * 10;
- return dat2;
- }
- void init_1302() //初始化函数 设置时间
- { //加备用电池,掉电走时
- // if((Read_DS1302_DAT(0x81)& 0x80) != 0) //读出秒数据,再跟80h(0x80)与运算看结果,结果是0则不需要初始化1302;是80h就要初始化!
-
- if(Read_DS1302_DAT(read_ram) != 0xaa) //如果第00个RAM位置不等于0xaa,就初始化1302
- {
- Write_DS1302_DAT(0x8e, 0);//清除写保护
- Write_DS1302_DAT(write_miao, Dat_Chg_BCD(58));//58秒(并且进行BCD码转换)
- Write_DS1302_DAT(write_fen, Dat_Chg_BCD(10));//10分
- Write_DS1302_DAT(write_shi, Dat_Chg_BCD(9));//9时
- Write_DS1302_DAT(write_ram,0xaa);//写入初始化标志RAM(第00个RAM位置)
- Write_DS1302_DAT(0x8e, 0x80);//开写保护
- }
- }
- void read_sf()
- {
- miao = BCD_Chg_Dat(Read_DS1302_DAT(0x81));//读秒寄存器(并且进行BCD码转换)
- fen = BCD_Chg_Dat(Read_DS1302_DAT(0x83));//读分寄存器
- shi = BCD_Chg_Dat(Read_DS1302_DAT(0x85));//读时寄存器
- // display(shi,fen);
- }
- void zdjs() //自动校时,这方法测试可行,每天减去快出的秒数
- {
- if((shi==7)&&(fen==30)&&(miao==6)) // 时钟每天快6秒
- {
- if(flag_js==0)
- {
- Write_DS1302_DAT(0x8e,0x00); //写保护取消
- Write_DS1302_DAT(write_miao,0x00); //写秒0,这里是假如每天快6秒,每到这个时候就减去6秒
- Write_DS1302_DAT(0x8e,0x80); //启动写保护
- flag_js=1; //标志位置1,不然这里会成一个死循环
- }
- }
- if((shi==7)&&(fen==35)&&(miao==0))
- flag_js=0; //标志位清零,准备第二天校时
- }
- void keysan()
- {
- static bit kf1=0, kf3=0,kf2=0; //自锁标志,这里一定要加static(或者用全局变量),否则按键不灵
- static uint i=0,j=0,k=0,m=0,n=0; //消抖延时变量
-
- if(key1==1) //设置 //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
- {
- i=0; //按键消抖计时变量清零
- kf1=0; //按键自锁标志清零
- }
- else if(kf1 == 0) //有按键按下,且是第一次被按下
- {
- flag_fm = 1; //启动蜂鸣器
- ++i;
- if(i>10) //i>10 ADC查询方式用
- {
- i=0;
- kf1=1; //自锁按键置位,避免一直触发
- knum++;
- if(knum==1)
- {
- Write_DS1302_DAT(0x8e,0x00); //写保护取消
- Write_DS1302_DAT(write_miao,0x80); // 写秒80,时钟停止走时;
-
- }
- if(knum==3)
- {
- knum = 0;
- Write_DS1302_DAT(write_miao,0x00);
- Write_DS1302_DAT(0x8e,0x80); //保护启动
- }
- }
- }
- /************显示和光控切换****************/
- if(knum == 0)
- {
- if(key3==1) //设置 //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
- {
- m=0; //按键消抖计时变量清零
- kf3=0; //按键自锁标志清零
- }
- else if(kf3 == 0) //有按键按下,且是第一次被按下
- { flag_fm = 1; //启动蜂鸣器
- ++m;
- if(m>10) //i>10 ADC查询方式用
- {
- m=0;
- kf3=1; //自锁按键置位,避免一直触发
- xs++;
- if(xs==3)
- {
- xs = 0;
-
- }
- }
- }
- if(key2==1) //设置 //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
- {
- n=0; //按键消抖计时变量清零
- kf2=0; //按键自锁标志清零
- }
- else if(kf2 == 0) //有按键按下,且是第一次被按下
- { flag_fm = 1; //启动蜂鸣器
- ++n;
- if(n>10) //i>10 ADC查询方式用
- {
- n=0;
- kf2=1; //自锁按键置位,避免一直触发
- flag_gk = !flag_gk;
- }
- }
- }
- ///-------加--------///
- if(knum != 0)
- {
- if(key2==0) //加
- {
-
- j++;
- // if(j >= 5000) //长按连加 ADC中断方式用
- if(j >= 100) //长按连加 ADC查询方式用
-
- { //flag_fm = 0;
- if(knum==2)
- {
- fen++;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- read_sf(); //读出时间,然后显示
- }
-
- if(knum==1)
- {
- shi++;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==0x24)
- shi=0x00;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
-
- j=90; //这里j的值可以设置连加的快慢,j的值越大就越快
- //因为初值越大,加到100的时间就越短
- flag_fm = 1; //启动蜂鸣器
- }
- }
-
- else
- {
- if(j>10 && j<100) //短按
- {
- flag_fm = 1; //启动蜂鸣器
- if(knum==2)
- {
- fen++;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- read_sf(); //读出时间,然后显示
- }
-
- if(knum==1)
- {
- shi++;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==0x24)
- shi=0x00;
-
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
-
- j=0;
- }
- }
-
- //----------减-----------//
- if(key3==0) //减
- { flag_fm = 1; //启动蜂鸣器
- k++;
- if(k >= 100) //长按
- {
- if(knum==2)
- {
- fen--;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- read_sf();
- }
- if(knum==1)
- {
- shi--;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==-1)
- shi=0x23;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
- k=90;
- }
- }
- else
- {
- if(k>10 && k<100) //短按
- {
- flag_fm = 1; //启动蜂鸣器
- if(knum==2)
- {
- fen--;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- read_sf();
- }
- if(knum==1)
- {
- shi--;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==-1)
- shi=0x23;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
- }
- k=0; //消抖变量清零,为下次按键做准备
- }
- }
- }
- void main()
- {
- // uchar i;
- t0_init();
- init_1302();
- // InitADC();
- ADC_Init();
- flag_fm = 1; //启动蜂鸣器
- while(1)
- {
- read_sf();
- switch(xs)
- {
- case 0:if(flag==0 && knum == 0) //时间、温度轮流显示,5秒切换一次
- {Display_tem(Get_Tmp());}
- else
- display( shi,fen); break;
- case 1: display( shi,fen); break; //显示时间
- case 2: Display_tem(Get_Tmp()); break;//显示温度
- default: break;
- }
- keysan();
- zdjs();//自动校时
- // if(shi>=5 && shi<=21) //5~21 亮度最大
- // ba=20;
- // else ba=1; //22~4 亮度最小
- // if(ADC_RES>5 && ADC_RES<25) ba=40;
- // if(ADC_RES>25 && ADC_RES<50) ba=39; //10级亮度,ba值越大,LED越亮
- // if(ADC_RES>50 && ADC_RES<80) ba=35;
- // if(ADC_RES>80 && ADC_RES<100) ba=30;
- // if(ADC_RES>100 && ADC_RES<130) ba=25;
- // if(ADC_RES>130 && ADC_RES<150) ba=20;
- // if(ADC_RES>150 && ADC_RES<180) ba=15;
- // if(ADC_RES>180 && ADC_RES<200) ba=10;
- // if(ADC_RES>200 && ADC_RES<230) ba=5;
- // if(ADC_RES>230 && ADC_RES<250) ba=1;
- /**************************/
- if(!flag_gk) //如果光控标志为0,就为自动亮度 ;默认为自动亮度
- {
- if(GetADCResult()>5 && GetADCResult()<25) ba=40;
- if(GetADCResult()>25 && GetADCResult()<50) ba=39; //10级亮度,ba值越大,LED越亮
- if(GetADCResult()>50 && GetADCResult()<80) ba=35;
- if(GetADCResult()>80 && GetADCResult()<100) ba=30;
- if(GetADCResult()>100 && GetADCResult()<130) ba=25;
- if(GetADCResult()>130 && GetADCResult()<150) ba=20;
- if(GetADCResult()>150 && GetADCResult()<180) ba=15;
- if(GetADCResult()>180 && GetADCResult()<200) ba=10;
- if(GetADCResult()>200 && GetADCResult()<230) ba=5;
- if(GetADCResult()>230 && GetADCResult()<250) ba=1;
- }
- else ba = 40; // 否则为最大亮度
- /*********************/
- if((shi>=5 && shi<=21) && fen ==0 && miao == 0) //整点报时
- {
- flag_fm = 1;
- }
- }
- }
- /*------------------------------------------------
- ADC中断处理函数
- ------------------------------------------------*/
- //void adc_isr() interrupt 5 using 1
- //{
- //// unsigned int temp;
- //// temp=ADC_RES; //AD取8位结果
- //// result=temp*0.01953125*1000; //ad结果换算成电压值, 将5V分成256份,每份5v/256=0.01953125v ,再扩大1000倍
- //// ge=result/1000;
- //// shifen=result%1000/100;
- //// baifen=result%100/10;
- //
- // ADC_CONTR = 0xc8;//开启转换
- //}
复制代码 全部资料51hei下载地址:
1寸数码管时钟资料.rar
(283.97 KB, 下载次数: 263)
|