求高手改时钟显示闪烁程序 和DS3231低温度程序 程序是在论坛里下载的 还想在修改哈 望高手帮帮忙
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
- #include <reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit SDA=P2^7; //数据传送位SDA
- sbit SCL=P2^6; //时钟控制位SCL
- sbit INT=P3^3; //中断位
- sbit RESET=P3^2; //复位
- sbit smg4=P1^1; //位码1声明 分个位
- sbit smg3=P1^3; //位码2声明 分十位
- sbit smg2=P1^5; //位码3声明 时个位
- sbit smg1=P1^7; //位码4声明 时十位
- sbit k1=P1^4; //按键k1的声明
- sbit k2=P1^6; //按键k2的声明
- sbit k3=P3^7; //按键k3的声明
- sbit bell=P3^5; //蜂鸣器声明
- sbit gm=P2^1; //测光声明,黑暗时等于1
- bit gm_en=0; //光敏使能信号;
- bit ack; //应答标志位
- char code dis_code[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E};//数码管没有按a-h的顺序连接,自定义的显示字库,0-9,A-F
- //0X28,0XEE,0X32,0XA2,0XE4,0XA1,0X21,0XEA,0X20,0XA0,0X60,0X25,0X37,0X26,0X31,0X71
- uchar bell_en=0,x=1;//闹钟使能信号,任意键关闭铃声标志位
- uchar tabtime[]={0x00,0x00,0x07,0x02,0x23,0x10,0x18}; //首次上电时默认的时间2018年 星期二 10月23日 07:00:00
- uchar year,month,day,week,hour,minute,second,temperature; //从1302读出的实时时间数据
- uchar gm_time=60,temp_en=0,n=0,a=0,b=0; //gm_time光敏控制亮度值,n是按键标志位,a产生一个1秒的计时,b控制字符闪烁,temp_en温度显示标志
- uint t=0; //用来产生30秒的计时
- uint TtempH,TtempL; //定义温度高位,低位
- char shi,fen,miao,b_shi=7,b_fen=0; //必须使用符号型:数据暂存单元shi/fen/miao,闹铃时间b_shi,b_fen,
- void baojing(); //报警函数
- void delay_50us(uint t); //延时50*T微妙函数的声明
- void Start_I2C(); //I2C总线产生起始信号函数
- void Stop_I2C(); //I2C总线产生停止信号函数
- void Ack_I2C(bit a); //接收应答信号函数;
- void SendByte(uchar c); //向I2C总线写入一个字节的数据函数
- uchar RcvByte(); //字节数据接收函数
- uchar write_byte(uchar addr, uchar write_data);//将一个字节写入DS3231指定地址
- uchar read_byte(uchar addr); //从DS3231指定地址读一个字节
- void Set_Time(); //设置时间
- void get_time(void); //读取时间
- void get_Temperature(); //读取温度
- void show_Temperature(); //显示温度
- void init(); //初始化函数
- void timer0(); //定时器0中断服务程序
- void display(uchar s,f); //显示子程序
- void key(); //按键控制函数
- void baojing()//报警函数
- {
- uint j=10,i=10;
- bell=0;
- while(i--)display(shi,fen);
- bell=1;
- while(j--)display(shi,fen);
- }
- //函数名称:void delay_50US(unsigned int t)
- //功能: 延时50*t(us)
- void delay_50us(uint t)
- {
- unsigned char j;
- for(;t>0;t--)
- {
- for(j=19;j>0;j--);
- }
- }
- void Start_I2C() //I2C总线产生起始信号函数
- {
- SDA=1; //拉高数据线,发送起始条件的数据信号
- SCL=1; //拉高时钟线
- SDA=0; //在时钟线为高电平时,拉低数据线,产生起始信号
- SCL=0; //钳住I2C总线,准备发送或接收数据
- }
- void Stop_I2C() //I2C总线产生停止信号函数
- {
- SDA=0; //拉低数据线,发送结束条件的数据信号
- SCL=1; //拉高时钟线,发送结束条件的时钟信号
- SDA=1; //时钟时线为高电平时,拉高数据线,发送I2C总线结束信号
- }
- /********************************************************************
- 应答子函数
- 函数原型: void I2CACK(bit a);
- 功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
- ********************************************************************/
- void Ack_I2C(bit a) //接收应答信号函数;a是定义的一个位变量,来暂存应答状态。
- {
-
- if(a==0)
- SDA=0; //在此发出应答或非应答信号
- else
- SDA=1;
- SCL=1;
- SCL=0; //清时钟线,钳住I2C总线以便继续接收
- }
- /*******************************************************************
- 字节数据发送函数
- 函数原型: void SendByte(uchar c);
- 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
- 此状态位进行操作.(不应答或非应答都使ack=0)
- ack=1 发送数据正常,
- ack=0 被控器无应答或损坏。
- ********************************************************************/
- void SendByte(uchar c) //向I2C总线写入一个字节的数据函数
- {
- uchar BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
- {
- if((c<<BitCnt)&0x80)
- SDA=1; //判断发送位
- else
- SDA=0;
- SCL=1; //置时钟线为高,通知被控器开始接收数据位
- SCL=0;
- }
-
- SDA=1; //8位发送完后释放数据线,准备接收应答位
- SCL=1;
- if(SDA==1)
- ack=0;
- else
- ack=1; //判断是否接收到应答信号
- SCL=0;
- }
- /*******************************************************************
- 字节数据接收函数
- 函数原型: uchar RcvByte();
- 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
- 发完后请用应答函数应答从机。
- ********************************************************************/
- uchar RcvByte() //字节数据接收函数
- {
- uchar retc;
- uchar BitCnt;
-
- retc=0;
- SDA=1; //置数据线为输入方式
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- SCL=0; //置时钟线为低,准备接收数据位
- SCL=1; //置时钟线为高使数据线上数据有效
- retc=retc<<1;
- if(SDA==1)
- retc=retc+1; //读数据位,接收的数据位放入retc中
- }
- SCL=0;
- return(retc);
- }
-
-
- /***********将一个字节写入DS3231指定地址***********/
- uchar write_byte(uchar addr, uchar write_data)
- {
- Start_I2C();
- SendByte(0xD0);
- if (ack == 0)
- return 0;
-
- SendByte(addr);
- if (ack == 0)
- return 0;
-
- SendByte(write_data);
- if (ack == 0)
- return 0;
-
- Stop_I2C();
- return 1;
- }
- /************从DS3231指定地址读一个字节************/
- uchar read_byte(uchar addr)
- {
- uchar read_data;
- Start_I2C();
- SendByte(0xD0);
- if(ack==0)
- return(0);
-
- SendByte(addr);
- if(ack==0)
- return(0);
-
- Start_I2C();
- SendByte(0xD1);
- if(ack==0)
- return(0);
- read_data = RcvByte();
- Ack_I2C(1);
- Stop_I2C();
- return read_data;
- }
-
- /**************************设置时间******************************************/
- void Set_Time()
- {
- uchar i;
- uchar ucAddr=0x00; //秒的地址
- for(i=0;i<7;i++)
- {
- write_byte(ucAddr,tabtime[i]);//从秒开始连续写入秒分时星期日月年
- ucAddr+=1;
- }
- }
-
-
- /*********************读取时间**********************/
- void get_time(void)
- {
- hour=read_byte(0x02)/16*10+read_byte(0x02)%16;
- minute=read_byte(0x01)/16*10+read_byte(0x01)%16; //因只显示时、分,故可只读取时、分
- year=read_byte(0x06)/16*10+read_byte(0x06)%16;
-
- /*
- uchar i;
- uchar ucCurtime[7];
- uchar ucAddr = 0x00; //秒地址
- for(i=0;i<7;i++)
- {ucCurtime[i]=0;}
-
- for(i=0; i<7; i++)
- {
- ucCurtime[i] = read_byte(ucAddr); //格式为: 从秒地址开始连续读取,秒分时星期日月年。
- ucAddr += 1;
- }
- year=ucCurtime[6]/16*10+ucCurtime[6]%16;
- month=ucCurtime[5]/16*10+ucCurtime[5]%16;
- day=ucCurtime[4]/16*10+ucCurtime[4]%16;
- week=ucCurtime[3]/16*10+ucCurtime[3]%16;
- hour=ucCurtime[2]/16*10+ucCurtime[2]%16;
- minute=ucCurtime[1]/16*10+ucCurtime[1]%16;
- second=ucCurtime[0]/16*10+ucCurtime[0]%16;
- */
- }
-
- /*********************读取温度**********************/
- void get_Temperature()
- {
- TtempH=read_byte(0X11); //读温度高字节
- //因数码管位数只有四位,故温度的小数部分不显示,可以不用读温度低字节
- TtempL=read_byte(0x12); //原为注释不用ox12 //读温度低字节
- TtempL=(TtempL>>6)*25; //原为注释不用 //将BIT7,BIT6的数据移入BIT1,BIT0位;分辨率数值扩大100倍便于整数运算
-
- }
- void show_Temperature() //显示温度
- {
- if((TtempH&0X80)==0x80) //判断首字节为1即为零下温度
- {
- P0=0xBF; //0xbf第一位数码管显示“-”
- smg1=0;
- delay_50us(gm_time);
- smg1=1;
- //////
- P0=dis_code[TtempL/10];//送显示断码 十位
- smg2=0;
- delay_50us(gm_time);
- smg2=1;
- P0=dis_code[TtempL%10];//送显示断码 个位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- P0=0xC6; //送显示断码 ℃
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
-
- }
- else
- smg1=1; //第一位数码管不显示
- if((TtempH/10)==0) //原为0 温度低于10度时,即为个位时,第二位数码管位不显示
- smg2=1; //原为=1
- else
- {
- P0=dis_code[TtempH/10];//送显示断码 十位
- smg2=0;
- delay_50us(gm_time);
- smg2=1;
- }
-
- P0=dis_code[TtempH%10];//送显示断码 个位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- P0=0xC6; //送显示断码 ℃
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
-
-
- }
- void init() //初始化函数
- {
- write_byte(0x0e,0x00); //设定DS3231的控制寄存器
- IE=0X82; //设定单片机的中断允许控制寄存器,(1000 0010)
- TMOD=0X01; //0000 0001选择定时器0的工作方式1 选择定时器1的工作方式0
- TH0=(65536-50000)/256;//初值15536定时50mS
- TL0=(65536-50000)%256;
- TR0=1; //设定TCON的TR0位,开启定时器0
- }
- void timer0() interrupt 1 //定时器0中断服务程序,用来设置冒号闪烁频率
- {
- TH0=(65536-50000)/256;//进入中断重新赋初值15536
- TL0=(65536-50000)%256;//计数5万次(50毫秒)
- a++; //标志位b,用来确定光标闪烁频率
- t++;
- if(t==600)t=0; //50ms*600次=30秒,用于温度显示,30秒一次
- if(t>520)temp_en=1; //温度显示持续3秒
- else temp_en=0;
- if(a==20)a=0;//a=20 时被清零 产生一个1秒的计时。
- }
- //四位数码管显示程序
- void display(uchar s,f)
- {
- if((s/10)<1) //小于10,第一位不显示
- smg1=1;
- else
- {
- P0=dis_code[s/10];//送显示断码 时的十位
- if((n==1||n==3)&&a<5)
- smg1=1; //锁存数据
- else
- smg1=0;
- delay_50us(gm_time);
- smg1=1;
- }
- P0=dis_code[s%10]; //送显示断码 时的个位
- if((n==1||n==3)&&a<5)
- smg2=1;
- else
- smg2=0; //锁存数据
- delay_50us(gm_time);
- smg2=1;
-
-
-
- if((n==2||n==4)&&a<5)
- P0=0x7F; //字符闪烁,小点不闪
- else if(a>=10)
- P0=dis_code[f/10]-0x80; //小点闪烁,字符不闪
- else
- P0=dis_code[f/10]; //送显示断码 分的十位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- if((n==2||n==4)&&a<5)
- P0=0x7F; //字符闪烁,小点不闪
- else if(a>=10)
- P0=dis_code[f%10]-0x80; //小点闪烁,字符不闪
- else
- P0=dis_code[f%10]; //送显示断码 分的个位
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
- }
- void key() //按键控制函数
- {
-
- if(k1==0&&k2==0) //k1k2同时按下,切换闹铃开关 并且在按下之后查看闹钟时间松手后恢复时间显示
- {
- delay_50us(40);
- if(k1==0&&k2==0)
- {
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果处于响零状态,就任意键关闭响铃
- shi=b_shi;
- fen=b_fen;
- bell_en=!bell_en;
- if(bell_en==1) //使能的话报警两声
- {
-
- baojing();
- baojing();
- }
- else
- {
-
- baojing(); //无效的话报警一声
- }
- while(k1==0&&k2==0)
- display(shi,fen);//等待松手
- shi=hour;
- fen=minute;
- }
- }
- if(k1==0&&k3==0) //k1k3同时按下,切换光控功能
- {
- delay_50us(40);
- if(k1==0&&k3==0)
- {
- gm_en=!gm_en;
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果处于响零状态,就任意键关闭响铃
- if(gm_en==1) //使能的话报警两声
- {
- baojing();
- baojing();
- }
- else baojing(); //无效的话报警一声
- while(k1==0&&k3==0)
- display(88,88);//等待松手
- }
- }
-
-
- if(k2==0&&k3==0) //K2,K3同时按下,进入 调时间 和 闹铃状态
- { //功能键k1被按下
- delay_50us(40); //消抖延时
- if(k2==0&&k3==0)
- {
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果处于响零状态,就任意键关闭响铃
- while(k2==0&&k3==0)
- n=1;
-
- }
- //要加入数字闪烁代码
- }
-
-
-
-
- if(n==0)//状态0,正常显示时间
- {
- b=a; //b是控制小数点闪烁的
- shi=hour;
- fen=minute;
- }
-
- if(n==1) //状态1:调节时间的"时"
- {
- b=10;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延时
- if(k1==0)
- {
- while(k1==0)
- n=2;
- }
- }
-
- if(k2==0)
- {
- delay_50us(40); //消抖延时
- if(k2==0)//k2被按下
- shi=shi+1; //小时加一
- if(shi>=24)
- shi=0; //达到24清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)
- {
- delay_50us(40); //消抖延时
- if(k3==0) //k3被按下
- shi--; //小时减一
- if(shi<0)
- shi=23;//小于0,重新赋值
- while(k3==0)
- display(shi,fen);
- }
- }
-
- if(n==2)//状态2:调节时间的"分"
- {
- b=10;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延时
- if(k1==0)
- {
- while(k1==0)
- n=3;
- }
- tabtime[2]=shi/10*16+shi%10;
- tabtime[1]=fen/10*16+fen%10;
-
- hour=shi;
- minute=fen;
- Set_Time();//设置DS1302的初始时间
-
- }
-
-
- if(k2==0)//k2被按下
- {
- delay_50us(40); //消抖延时
- if(k2==0)
- fen++;//分加一
- if(fen>=60)
- fen=0;//分到达60 分清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)//k3被按下
- {
- delay_50us(40); //消抖延时
- if(k3==0)
- fen--;//分减一
- if(fen<0)
- fen=59;//分小于0,分重新赋值59
- while(k3==0)
- display(shi,fen);
- }
-
- }
-
-
- if(n==3)//状态三:调节闹铃"时"
- {
- b=10;
- shi=b_shi;
- fen=b_fen;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延时
- if(k1==0)
- {
- while(k1==0)
- n=4;
- }
- }
-
- if(k2==0)//k2被按下
- {
- delay_50us(40); //消抖延时
- if(k2==0)
- b_shi++;//闹铃时间加一
- if(b_shi>=24)
- b_shi=0;//闹铃时间清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)//k3被按下
- {
- delay_50us(40); //消抖延时
- if(k3==0)
- b_shi--;//闹铃时间减一
- if(b_shi<0)
- b_shi=23;//闹铃时间
- while(k3==0)
- display(shi,fen);
- }
- }
-
-
- if(n==4)//状态四 :调节闹铃的"分"
- {
- b=10;
- shi=b_shi;
- fen=b_fen;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延时
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
0.8寸数码管 PCB 电路图 程序.rar
(3.56 MB, 下载次数: 82)
|