这个是用AT24C02和51单片机做得本来只差年的拆分了,其他部分都可以正常变化,因为AT24C02一个地址只能存一字节,结果后来自己调的年月份都有问题,我直接在write_add里给除年以外的月份,日,小时赋正常值,结果有时只会有一个比如月份变化,其他的几个没变化,我怀疑是不是EEPORM有啥问题,为啥我直接赋值都没变化,每次赋值后我还RESET了一下然后再重启,求大佬解决一下,调了几天了。
- /***************************************************
- 程序功能:实现一个万年历
- 拓展模块:之后加GPS定位和温度数据以及红外遥控
- ***************************************************/
- #include<reg52.h>
- #include<string.h>
- #include<stdio.h>
- #define uchar unsigned char
- #define unit unsigned int
- unit nian;
- uchar yue,ri,shi,feng,miao; //将这些数据定义为全局变量,因为等下会对他们进行计数
- unit num,num0; //通过对功能选择键按的次数进行计数来选择对年月日还是时分秒进行修改
- unit number;
- sbit lcden=P2^5;
- sbit lcdrs=P1^0;
- sbit RW=P1^1;
- sbit dula=P2^6;
- sbit wela=P2^7;
- sbit SDA=P2^0;
- sbit SCL=P2^1;
- sbit option=P3^4;
- sbit add=P3^5;
- sbit dcen=P3^6;
- sbit beef=P2^3;
- /*****************************
- 延迟函数
- *****************************/
- void delayms(unit ms)
- {
- unit i,j;
- for(i=ms;i>0;i--)
- for(j=110;j>0;j--);
- }
- void delay()
- {
- }
- /******************************
- 初始化函数
- ******************************/
- void init()
- {
- EA=1;
- ET0=1;
- TMOD=0x01;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TR0=1;
- }
- /******************************
- 蜂鸣器函数
- ******************************/
- void di()
- {
- beef=0;
- delayms(100);
- beef=1;
- }
- ///////////////////////////////////////////////////////////////////////
- // 1602模块程序 //
- ///////////////////////////////////////////////////////////////////////
- /****************************
- 写命令函数
- ****************************/
- void write_com(uchar com)
- {
- P0=0xff;
- P0=com;
- lcdrs=0;
- RW=0;
- delayms(5);
- lcden=1;
- delayms(5);
- lcden=0;
- }
- /****************************
- 写数据函数
- ****************************/
- void write_data(uchar Data)
- {
- P0=0xff;
- P0=Data;
- lcdrs=1;
- RW=0;
- delayms(5);
- lcden=1;
- delayms(5);
- lcden=0;
- }
- /*****************************
- 屏幕初始化函数
- *****************************/
- void screen_init()
- {
- dula=0;
- wela=0; ///关闭数码管
- write_com(0x38);
- write_com(0x0e);
- write_com(0x06);
- write_com(0x01);
- }
- /*****************************
- 1602显示函数
- *****************************/
- void display(unit nian,uchar yue,uchar ri,uchar shi,uchar feng,uchar miao) //此函数的形参变化由中断函数提供
- {
- screen_init();
- write_com(0x80);
- write_data(nian/1000+0x30);
- write_data(nian/100%10+0x30);
- write_data(nian%100/10+0x30);
- write_data(nian%10+0x30);
- write_data('-');
- write_data(yue/10+0x30);
- write_data(yue%10+0x30);
- write_data('-');
- write_data(ri/10+0x30);
- write_data(ri%10+0x30);
- write_com(0x80+0x40);
- write_data(shi/10+0x30);
- write_data(shi%10+0x30);
- write_data('-');
- write_data(feng/10+0x30);
- write_data(feng%10+0x30);
- write_data('-');
- write_data(miao/10+0x30);
- write_data(miao%10+0x30);
- }
- //////////////////////////////////////////////////////////////////////////////////////
- // AT24C02模块程序 //
- //////////////////////////////////////////////////////////////////////////////////////
- /*****************************
- 启动信号函数
- *****************************/
- void start()
- {
- SDA=1;
- delay();
- SCL=1;
- delay();
- SDA=0;
- delay();
- }
- /*****************************
- 终止信号函数
- *****************************/
- void stop()
- {
- SDA=0;
- delay();
- SCL=1;
- delay();
- SDA=1;
- delay();
- }
- /*****************************
- 应答函数
- *****************************/
- void response()
- {
- unit i;
- SCL=1;
- delay();
- while((SDA==1)&&(i<255))
- i++;
- SCL=0;
- delay();
- }
- /*****************************
- 写一字节函数
- *****************************/
- void write_byte(uchar Data)
- {
- uchar temp;
- uchar i;
- temp=Data;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- SCL=0;
- delay();
- SDA=CY;
- delay();
- SCL=1;
- delay();
- }
- SCL=0;
- delay();
- SDA=1;
- delay();
- }
- /****************************
- 读一字节函数
- ****************************/
- uchar read_byte()
- {
- uchar i,k;
- SCL=0;
- delay();
- SDA=1;
- delay();
- for(i=0;i<8;i++)
- {
- SCL=1;
- delay();
- k=(k<<1)|SDA;
- SCL=0;
- delay();
- }
- delay();
- return k;
- }
- /*****************************
- 写操作方式函数
- *****************************/
- void write_add(uchar address,uchar Data)
- {
- start();
- write_byte(0xa0);
- response();
- write_byte(address);
- response();
- write_byte(Data);
- response();
- stop();
- }
- /*****************************
- 读操作方式函数
- *****************************/
- uchar read_add(uchar address)
- {
- uchar Data;
- start();
- write_byte(0xa0);
- response();
- write_byte(address);
- response();
- start();
- write_byte(0xa1);
- response();
- Data=read_byte();
- stop();
- return Data;
- }
- ////////////////////////////////////////////////////////////////////////////
- // 键盘功能程序 //
- ////////////////////////////////////////////////////////////////////////////
- void keyscan()
- {
- if(option==0)
- {
- TR0=0;
- delayms(10);
- if(option==0) //检测功能键是否按下
- {
- di();
- number++;
- while(!option);
- if(number==1)
- {
- write_com(0x80+4); //光标定义到年位置
-
- }
- if(number==2)
- {
- write_com(0x80+7);
- }
- if(number==3)
- {
- write_com(0x80+10);
- }
- if(number==4)
- {
- write_com(0x80+0x40+2);
- }
- if(number==5)
- {
- write_com(0x80+0x40+5);
- }
- if(number==6)
- {
- write_com(0x80+0x40+8);
- }
-
- }
- }
- if(number!=0) //如果按下了功能键 以下是功能键次数
- {
- if(add==0)
- {
- delayms(10);
- if(add==0)
- {
- while(!add);
- di();
- if(number==1)
- {
- nian++;
- }
- if(number==2)
- {
- yue++;
- }
- if(number==3)
- {
- ri++;
- }
- if(number==4)
- {
- shi++;
- }
- if(number==5)
- {
- feng++;
- }
- if(number==6)
- {
- miao++;
- }
- }
- }
-
- if(dcen==0)
- {
- delayms(10);
- if(dcen==0)
- {
- while(!dcen);
- di();
- if(number==1)
- {
- nian--;
- }
- if(number==2)
- {
- yue--;
- }
- if(number==3)
- {
- ri--;
- }
- if(number==4)
- {
- shi--;
- }
- if(number==5)
- {
- feng--;
- }
- if(number==6)
- {
- miao--;
- }
- }
- }
- }
- TR0=1;
- }
-
- ////////////////////////////////////////////////////////
- /// 主函数 /////
- ////////////////////////////////////////////////////////
- void main()
- {
- init();
- nian=read_add(1);
- yue=read_add(2);
- ri=read_add(3);
- shi=read_add(4);
- feng=read_add(5);
- miao=read_add(6);
- while(1)
- {
-
- display(nian,yue,ri,shi,feng,miao); //接收到数据后在1602上显示
-
- keyscan(); //对日期时间的调整,同时注意对日期进行调整的时候是不允许进入中断的
- //接收到数据显示完,而且更改完了之后就把数据写入内存中,以方便以后断电保存
-
-
-
-
-
- write_add(1,nian);
- write_add(2,yue);
- write_add(3,ri);
- write_add(4,shi); //刚才显示时15,因为直接写21会默认你为int,记住要复位重烧也不会改变数据
- write_add(5,feng);
- write_add(6,miao);
- }
- }
- /***************************
- 定时器中断函数
- ****************************/
- void ser()interrupt 1
- {
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- num++;
-
- if(num>=20)
- {
- miao++;
- num=0;
-
- }
- if(miao==60)
- {
- feng++;
- miao=0;
- }
- if(feng==60)
- {
- feng=0;
- shi++;
-
- }
- if(shi==24)
- {
- shi=0;
- ri++;
-
- }
- if(ri==30)
- {
- ri=0;
- yue++;
- }
- if(yue==12)
- {
- yue=0;
- nian++;
- }
-
- }
复制代码
|