时隔一年,pcb版1.8寸数码管时钟2.0版出炉了,平时带娃上班没时间,所以久了点。(老版本没上传,这次上传看看)
去年做的pcb时自己学protel99画的,本想找淘宝的,pcb厂家说不带画,于是找带画的,可一个种带画收费800块,觉得不难,所以一气之下自己自学了。现在一年没动,忘记好多,在3231芯片画封装的时候没实物测量,直接上下两排引脚距离写错了,本来9mm写成5了,板子到手才发现,幸亏家里有热风枪,所以把3231的引脚向里弯后用风枪焊,电烙铁是不行了。所以PCB就不发出来了,有兴趣的朋友可自己画。
之前pcb版的秒用的是led,这次直接用数码管的点表示秒。
之前的DS3231直接用5v电源供电,发现误差大,这次添加3.3v稳压管后正常。
之前数码管使用MAX7219驱动4位共阴数码管,虽然芯片有调光功能,但使用中发现经常死机不动或黑屏,现在直接使用PNP三极管驱动4位共阳数码管+AD功能光控。
功能:
1、使用STC12C5A60S2 AD功能检测环境光线控制数码管亮暗。(60K太大觉得浪费的朋友可换小容量的芯片,我是本着价格差距不大,情愿容量大的想法所以用60s2)
2、有按键和红外遥控功能(正面为了美观。实测红外接收头在反面,遥控器在正面也能接收信号)
3、采用DS3231时钟芯片,年误差+-2min
4、时钟芯片电池使用LIR系列可充电纽扣电池(这里用的LIR1220,可换LIR2032等更大容量电池)
5、由于给老年人使用,所以没设闹钟功能,但引脚以连,可在程序里自行添加。
6、目前为止1.8寸是最大数码管(5V驱动里),更大的数码管需要>=12V电压供电,芯片驱动,电路比较麻烦。所以这里使用1.8寸数码管。
7、由于画线路图时数码管标号A~DP对应的管脚写反了,PCB文件没细看就发厂商制版了,所以程序中数码管显示数组另外写了,常用如下:
uchar code table[]= //共阳数码管编码0~F
{0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xc0,0x86,0x8e};
制作出来的实物图如下:
电路原理图如下:
单片机源程序如下:
- /*****************************************************************************************************
- *******************************************头文件与宏定义*********************************************
- *****************************************************************************************************/
- #include <STC12C5A60S2.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*****************************************************************************************************
- ***********************************************ADC定义************************************************
- *****************************************************************************************************/
- sfr ADC_LOW2 = 0xBE; //ADC低2位结果
- #define ADC_POWER 0x80 //ADC电源控制位
- #define ADC_FLAG 0x10 //ADC完成标志
- #define ADC_START 0x08 //ADC起始控制位
- #define ADC_SPEEDLL 0x00 //540个时钟
- #define ADC_SPEEDL 0x20 //360个时钟
- #define ADC_SPEEDH 0x40 //180个时钟
- #define ADC_SPEEDHH 0x60 //90个时钟
- /*****************************************************************************************************
- ********************************************红外遥控定义**********************************************
- *****************************************************************************************************/
- #define Imax 14000
- #define Imin 8000
- #define Inum1 1450
- #define Inum3 3000
- #define Inum2 700
- uchar f;
- uchar IrOK;
- unsigned long m,Tc;
- uchar Im[4]={0x00,0x00,0x00,0x00};
- /*****************************************************************************************************
- **********************************************DS3231定义**********************************************
- *****************************************************************************************************/
- uchar RTC_Data[7];
- uchar RTC_Data1[7];
- uchar RTC_Set_ID;
- code uchar rtc_address[7]={0x00,0x01,0x02,0x04,0x05,0x03,0x06};
- /*****************************************************************************************************
- **********************************************标志位定义**********************************************
- *****************************************************************************************************/
- bit T0_Flag; //定时器0标志位
- bit laba_flag; //蜂鸣器标志位
- bit set_flag; //设置显示标志位
- bit RTC_Save_Flag; //设置时间标志位
- bit gk; //光控标志位
- /*****************************************************************************************************
- **********************************************管脚定义************************************************
- *****************************************************************************************************/
- sbit IIC_SCL=P3^6; //DS3231_SCL
- sbit IIC_SDA=P3^5; //DS3231_SDA
- sbit hongwai=P3^3; //红外接收数据输入端
- sbit key1=P2^0; //设置键
- sbit key2=P2^1; //加键
- sbit key3=P2^2; //减键
- sbit key4=P2^3; //确定键
- //sbit key5=P2^4; //PWM键
- sbit key6=P2^5; //光控键
- sbit laba=P3^4; //喇叭输出端
- sbit D1=P1^3; //数码管位码
- sbit D2=P1^2; //数码管位码
- sbit D3=P1^1; //数码管位码
- sbit D4=P1^0; //数码管位码
- int ld; //光控ADC用
- uint temp[3]; //光控ADC用
- uchar code table[]={0x03,0x9f,0x25,0x0d, //共阳数码管不带小数点
- 0x99,0x49,0x41,0x1f,
- 0x01,0x09,0x11,0xc1,
- 0x63,0x85,0x61,0x71};
- uchar code table1[]={0x02,0x9e,0x24,0x0c, //共阳数码管带小数点
- 0x98,0x48,0x40,0x1e,
- 0x00,0x08,0x10,0xc0,
- 0x62,0x84,0x60,0x70};
- /*****************************************************************************************************
- **********************************************延时函数************************************************
- *****************************************************************************************************/
- void Delay_xms(uint x)
- {
- uint i,j;
- for(i=0;i<x;i++)
- for(j=0;j<112;j++);
- }
- void Delayms(uint t)
- {
- uchar i;
- while(t--)
- for(i=0;i<123;i++);
- }
- /*****************************************************************************************************
- **********************************************显示函数************************************************
- *****************************************************************************************************/
- void display()
- {
- D1=0;
- P0=table[RTC_Data[2]/10];
- Delayms(4);
- P0=0xff;
- D1=1;
- D2=0;
- if(RTC_Data[0]/1%2==0) P0=table[RTC_Data[2]%10];
- else P0=table1[RTC_Data[2]%10];
- Delayms(4);
- P0=0xff;
- D2=1;
- D3=0;
- if(RTC_Data[0]/1%2==0) P0=table[RTC_Data[1]/10];
- else P0=table1[RTC_Data[1]/10];
- Delayms(4);
- P0=0xff;
- D3=1;
- D4=0;
- P0=table[RTC_Data[1]%10];
- Delayms(4);
- P0=0xff;
- D4=1;
- }
- /*****************************************************************************************************
- **************************************显示小时函数*****设置用*****************************************
- *****************************************************************************************************/
- void display_set_shi()
- {
- D1=0;
- P0=0x91;
- Delayms(2);
- P0=0xff;
- D1=1;
- D2=0;
- P0=0xff;
- Delayms(2);
- P0=0xff;
- D2=1;
- D3=0;
- P0=table[RTC_Data[2]/10];
- Delayms(2);
- P0=0xff;
- D3=1;
- D4=0;
- P0=table[RTC_Data[2]%10];
- Delayms(2);
- P0=0xff;
- D4=1;
- }
- /*****************************************************************************************************
- **************************************显示分钟函数*****设置用*****************************************
- *****************************************************************************************************/
- void display_set_fen()
- {
- D1=0;
- P0=table[15];
- Delayms(2);
- P0=0xff;
- D1=1;
- D2=0;
- P0=0xff;
- Delayms(2);
- P0=0xff;
- D2=1;
- D3=0;
- P0=table[RTC_Data[1]/10];
- Delayms(2);
- P0=0xff;
- D3=1;
- D4=0;
- P0=table[RTC_Data[1]%10];
- Delayms(2);
- P0=0xff;
- D4=1;
- }
- /*****************************************************************************************************
- ***************************************显示秒函数*****设置用******************************************
- *****************************************************************************************************/
- void display_set_miao()
- {
- D1=0;
- P0=0x49;
- Delayms(2);
- P0=0xff;
- D1=1;
- D2=0;
- P0=0xff;
- Delayms(2);
- P0=0xff;
- D2=1;
- D3=0;
- P0=table[RTC_Data[0]/10];
- Delayms(2);
- P0=0xff;
- D3=1;
- D4=0;
- P0=table[RTC_Data[0]%10];
- Delayms(2);
- P0=0xff;
- D4=1;
- }
- /*****************************************************************************************************
- ********************************************键值处理函数**********************************************
- *****************************************************************************************************/
- void KeyDataProcess()
- {
- if(key1==0)// 设置
- {
- if(key1==0)
- {
- Delay_xms(20);
- while(!key1);
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- RTC_Set_ID++;
- if(RTC_Set_ID>=4)
- RTC_Set_ID=1;
- }
- }
- if(key2==0)//+
- {
- if(key2==0)
- {
- Delay_xms(20);
- while(!key2);
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- if(RTC_Set_ID==1)
- {
- RTC_Data[2]++;
- if(RTC_Data[2]>23)
- RTC_Data[2]=0;
- display_set_shi();
- }
- else if(RTC_Set_ID==2)
- {
- RTC_Data[1]++;
- if(RTC_Data[1]>59)
- RTC_Data[1]=0;
- display_set_fen();
- }
- else if(RTC_Set_ID==3)
- {
- RTC_Data[0]++;
- if(RTC_Data[0]>59)
- RTC_Data[0]=0;
- display_set_miao();
- }
- }
- }
- if(key3==0)//-
- {
- if(key3==0)
- {
- Delay_xms(20);
- while(!key3);
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- if(RTC_Set_ID==1)
- {
- RTC_Data[2]--;
- if(RTC_Data[2]==-1)
- RTC_Data[2]=23;
- display_set_shi();
- }
- else if(RTC_Set_ID==2)
- {
- RTC_Data[1]--;
- if(RTC_Data[1]==-1)
- RTC_Data[1]=59;
- display_set_fen();
- }
- else if(RTC_Set_ID==3)
- {
- RTC_Data[0]--;
- if(RTC_Data[0]==-1)
- RTC_Data[0]=59;
- display_set_miao();
- }
- }
- }
- if(key4==0)//ok
- {
- if(key4==0)
- {
- Delay_xms(20);
- while(!key4);
- laba_flag=1; //蜂鸣器响一声
- set_flag=1;
- RTC_Save_Flag=1;
- }
- }
- if(key6==0)//gk
- {
- if(key6==0)
- {
- Delay_xms(20);
- while(!key6);
- laba_flag=1; //蜂鸣器响一声
- set_flag=1;
- gk=!gk;
- }
- }
- //以下为红外遥控部分
- if(IrOK==1) //设置键
- {
- if(Im[2]==0x0d)
- {
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- RTC_Set_ID++;
- if(RTC_Set_ID>=4)
- RTC_Set_ID=1;
- }
- else if(Im[2]==0x40)//遥控器+键
- {
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- if(RTC_Set_ID==1)
- {
- RTC_Data[2]++;
- if(RTC_Data[2]>23)
- RTC_Data[2]=0;
- display_set_shi();
- }
- else if(RTC_Set_ID==2)
- {
- RTC_Data[1]++;
- if(RTC_Data[1]>59)
- RTC_Data[1]=0;
- display_set_fen();
- }
- else if(RTC_Set_ID==3)
- {
- RTC_Data[0]++;
- if(RTC_Data[0]>59)
- RTC_Data[0]=0;
- display_set_miao();
- }
- }
- else if(Im[2]==0x19)//遥控器-键
- {
- laba_flag=1; //蜂鸣器响一声
- set_flag=0;
- if(RTC_Set_ID==1)
- {
- RTC_Data[2]--;
- if(RTC_Data[2]==-1)
- RTC_Data[2]=23;
- display_set_shi();
- }
- else if(RTC_Set_ID==2)
- {
- RTC_Data[1]--;
- if(RTC_Data[1]==-1)
- RTC_Data[1]=59;
- display_set_fen();
- }
- else if(RTC_Set_ID==3)
- {
- RTC_Data[0]--;
- if(RTC_Data[0]==-1)
- RTC_Data[0]=59;
- display_set_miao();
- }
- }
- else if(Im[2]==0x15)//遥控器播放键
- {
- laba_flag=1; //蜂鸣器响一声
- set_flag=1;
- RTC_Save_Flag=1;
- }
- else if(Im[2]==0x47)//遥控器MENU键
- {
- laba_flag=1; //蜂鸣器响一声
- set_flag=1;
- gk=!gk;
- }
- IrOK=0;
- }
- }
- /*****************************************************************************************************
- *****************************************DS3231时钟函数***********************************************
- *****************************************************************************************************/
- void delay_IIC()
- {
- _nop_();_nop_();_nop_();_nop_();//IIC总线限速延时函数。该函数是空函数,延时4个机器周期。
- }
- void IIC_Init() //IIC总线初始化函数
- {
- IIC_SDA=1;//释放IIC总线的数据线。
- IIC_SCL=1;//释放IIC总线的时钟线。
- }
- void IIC_start() //IIC总线产生起始信号函数
- {
- IIC_SDA=1;//拉高数据线
- IIC_SCL=1;//拉高时钟线
- delay_IIC();
- IIC_SDA=0;//在时钟线为高电平时,拉低数据线,产生起始信号。
- delay_IIC();
- IIC_SCL=0;//拉低时钟线
- }
- void IIC_stop()//IIC总线产生停止信号函数
- {
- IIC_SDA=0;//拉低数据线
- delay_IIC();
- IIC_SCL=1;//拉高时钟线。
- delay_IIC();
- IIC_SDA=1;//时钟时线为高电平时,拉高数据线,产生停止信号。
- delay_IIC();
- }
- bit IIC_Tack() //接收应答信号函数
- {
- bit ack;//定义一个位变量,来暂存应答状态。
- IIC_SDA=1;//释放数据总线,准备接收应答信号。
- delay_IIC();
- IIC_SCL=1;//拉高时钟线。
- delay_IIC();
- ack=IIC_SDA;//读取应答信号的状态。
- delay_IIC();
- IIC_SCL=0;//拉低时钟线。
- delay_IIC();
- return ack;//返回应答信号的状态,0表示应答,1表示非应答。
- }
- void IIC_write_byte(uchar Data)//向IIC总线写入一个字节的数据函数
- {
- uchar i;
- for(i=0;i<8;i++)//有8位数据
- {
- if(Data&0x80)
- IIC_SDA=1;//写最高位的数据
- else
- IIC_SDA = 0;
- delay_IIC();
- IIC_SCL=1; //拉高时钟线,将数写入到设备中。
- delay_IIC();
- IIC_SCL=0;//拉低时钟线,允许改变数据线的状态
- delay_IIC();
- Data=Data<<1;//数据左移一位,把次高位放在最高位,为写入次高位做准备
- }
- }
- uchar IIC_read_byte()//从IIC总线读取一个字节的数据函数
- {
- uchar i;
- uchar Data; //定义一个缓冲寄存器。
- for(i=0;i<8;i++)//有8位数据
- {
- IIC_SCL=1;//拉高时钟线,为读取下一位数据做准备。
- delay_IIC();
- Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。
- delay_IIC();
-
- if(IIC_SDA)//如果数据线为高平电平。
- Data=Data|0x01;//则给缓冲字节的最低位写1。
- IIC_SCL=0;//拉低时钟线,为读取下一位数据做准备。
- delay_IIC();
- }
- return Data;//返回读取的一个字节数据。
- }
- void IIC_single_byte_write(uchar Waddr,uchar Data) //向任意地址写入一个字节数据函数
- {
- IIC_start();//产生起始信号
- IIC_write_byte(0xd0);//写入设备地址(写)
- IIC_Tack();//等待设备的应答
- IIC_write_byte(Waddr);//写入要操作的单元地址。
- IIC_Tack();//等待设备的应答。
- IIC_write_byte(Data);//写入数据。
- IIC_Tack();//等待设备的应答。
- IIC_stop();//产生停止符号。
- }
- uchar IIC_single_byte_read(uchar Waddr) //从任意地址读取一个字节数据函数
- {
- uchar Data;//定义一个缓冲寄存器。
- IIC_start();//产生起始信号
- IIC_write_byte(0xd0);//写入设备地址(写)
- IIC_Tack();//等待设备的应答
- IIC_write_byte(Waddr);//写入要操作的单元地址。
- IIC_Tack();//等待设备的应答。
- IIC_stop();//产生停止符号。
- IIC_start();//产生起始信号
- IIC_write_byte(0xd1);//写入设备地址(写)
- IIC_Tack();//等待设备的应答
- Data=IIC_read_byte();//写入数据。
- delay_IIC();
- IIC_stop();//产生停止符号。
- return Data;//返回读取的一个字节数据。
- }
- /*****************************************************************************************************
- ********************************************时钟写入函数**********************************************
- *****************************************************************************************************/
- void Set_RTC()
- {
- uchar i,tmp;
- for(i=0;i<7;i++)
- {
- tmp=RTC_Data[i]/10;
- RTC_Data1[i]=RTC_Data[i]%10;
- RTC_Data1[i]=RTC_Data1[i]+tmp*16;
- }
- for(i=0;i<7;i++)
- {
- IIC_single_byte_write(rtc_address[i],RTC_Data1[i]);
- }
- IIC_single_byte_write(0x0e,0x0c);
- }
- /*****************************************************************************************************
- *******************************************时钟初始化函数*********************************************
- *****************************************************************************************************/
- void DS3231_Init()
- {
- IIC_SDA=1;
- IIC_SCL=1;
- IIC_single_byte_write(0x0e,0x0c);
- }
- /*****************************************************************************************************
- ********************************************时钟读取函数**********************************************
- *****************************************************************************************************/
- void Read_RTC()
- {
- uchar i,tmp,tmp1,tmp2;
- for(i=0;i<7;i++)
- {
- tmp = IIC_single_byte_read(rtc_address[i]);
- tmp1 = tmp/16;
- tmp2 = tmp%16;
- RTC_Data[i]=tmp1*10+tmp2;
- }
- }
- void Ram_init()
- {
- Read_RTC(); //读取 秒分时日月周年
- if((!RTC_Data[6])&&(!RTC_Data[4])&&(!RTC_Data[3])&&(!RTC_Data[2])&&(!RTC_Data[1])&&(!RTC_Data[0]))
- {
- RTC_Data[0]=0; //秒 //秒分时日月周年 最低位读写位
- RTC_Data[1]=0; //分
- RTC_Data[2]=12; //时
- RTC_Data[3]=3; //日
- RTC_Data[4]=11; //月
- RTC_Data[5]=2; //周
- RTC_Data[6]=15; //年
- Set_RTC(); //写入 秒分时日月周年
- }
- RTC_Set_ID=0;
- }
- /*****************************************************************************************************
- *******************************************ADC初始化函数**********************************************
- *****************************************************************************************************/
- void InitADC()
- {
- P1ASF = 0x80; //Open channels ADC function 1000 0000 p1.7使用AD功能
- ADC_RES = 0;
- ADC_LOW2 = 0;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- }
- /*****************************************************************************************************
- *********************************************ADC处理函数**********************************************
- *****************************************************************************************************/
- void GetADCResult(unsigned char ch,unsigned int *value)
- {
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //Must wait before inquiry
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //Must wait before inquiry
- _nop_();
- while(!(ADC_CONTR & ADC_FLAG));//Wait complete flag
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
- *value = 0;
- *value = ADC_RES;
- *value = ((*value)*4 + ADC_LOW2);
- }
- /*****************************************************************************************************
- **********************************************走时函数************************************************
- *****************************************************************************************************/
- void Time_Fun()
- {
- static uchar T10Ms_Cnt=0,T200Ms_Cnt=0;
- static uchar Buzz_On_Cnt=0,RTC_Save_Cnt=0;
-
- T10Ms_Cnt++;
- if(T10Ms_Cnt>=5)
- {
- T10Ms_Cnt=0;
- KeyDataProcess();
- if(laba_flag)
- {
- Buzz_On_Cnt++;
- if(Buzz_On_Cnt>=10)
- {
- laba_flag=0;
- Buzz_On_Cnt=0;
- }
- }
- if(RTC_Save_Flag) //按确定键RTC_Save_Flag=1,保存数据
- {
- RTC_Save_Cnt++;
- if(RTC_Save_Cnt>=50)
- {
- RTC_Save_Cnt=0;
- RTC_Save_Flag=0;
- RTC_Set_ID=0;
- Set_RTC();
- }
- }
- }
- T200Ms_Cnt++;
- if(T200Ms_Cnt>=5)
- {
- T200Ms_Cnt=0;
- if(!RTC_Set_ID)
- Read_RTC();
- GetADCResult(7,&temp[2]);
- if(gk==1) //开光控
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
1.8CLOCK.rar
(56.9 KB, 下载次数: 261)
|