单片机源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define AT24C02_addr
- bit write=0;//写24C02的标志
- sbit sda=P2^0;
- sbit scl=P2^1;
- sbit dula=P2^6;//申明U1锁存器的锁存端
- sbit wela=P2^7;//U2锁存端
- uchar i,miao,t;
- uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- void Delay5us() //@11.0592MHz
- {
- uchar i;
- _nop_();
- i = 11;
- while (--i);
- }
- void start()//起始信号
- {
- scl=1;//先保持高电平,再进行数据传输
- _nop_();//延时1微秒
- sda=1;
- Delay5us();//函数调用
- sda=0;
- Delay5us();
- }
- void stop()
- {
- scl=1;
- _nop_();
- sda=0;
- Delay5us();
- sda=1;
- Delay5us();
- }
- void Mster_ASK()//主机发送应答
- {
- uchar i;
- scl=1;
- _nop_();
- if(i==1)//受控器做出响应
- {
- sda=0;//释放sda线送出应答信号
- }
- else
- {
- sda=1;
- }
- _nop_();
- scl=1;//数据保持稳定
- Delay5us();
- scl=0;//占用总线进行通信
- sda=1;//准备下一次的通信
- }
- void test_ASK()//从机接受应答,低电平为应答
- {
- scl=1;//scl为高电平,数据不允许改变
- Delay5us();
- if(sda==1)//因为sda等于1时,表示空闲状态
- {
- scl=0;//表示不应答
- _nop_();
- stop();
- return (0);
- }
- else//sda等于0,表示应答,scl拉低,表示收到这个是否应达的信息
- {
- scl=0;//低电平有效
- _nop_();
- return (1);
- }
- }
- uchar sendbyte(uchar byte)//传送(写)一个字节
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- scl=0;//低电平时数据可以改变
- _nop_();//稳定一下
- if(byte&0x80)
- {
- sda=1;//发一个1的数据,先发高位
- _nop_();
- }
- else
- {
- sda=0;//如果if处是0的话,就说明最高位是0,所以传数据0
- _nop_();
- }
- scl=1;//数据手册看出来
- _nop_();
- byte<<=1;
- }
- }
- uchar readbyte()//读一个字节
- {
- uchar dat,i;
- scl=0;//可要可不要吧,看它忙不忙
- _nop_();
- scl=1;//置1,数据不允许改变
- _nop_();
- for(i=0;i<8;i++)
- {
- scl=1;//置1,数据不允许改变
- _nop_();
-
- if(sda)//若为1,则要读1出来
- {
- dat=dat|0x01;//或上都等于1
- else
- {
- dat=dat&0xfe;//与上都等于0
- }
- _nop_();
- scl=0; //释放总线,允许下一次数据输入
- dat<<=1;
- }
- }
- }
- void T0()interrpt 1//定时中断服务函数
- {
- uchar t,miao,write;
- TH0=(65536-50000)/256//从15536开始装初值,装满5000,即为50ms
- TL0=(65536-50000)%256//装计数初值
- t++;
- if(t==20)//表示记满1秒
- {
- t=0;//重新计数
- miao++;
- }
- if(miao=100)
- miao=0;//重新计数
- }
- void display()
- {
- uchar bai,ge;
- wela=1;//打开位选
- P0=0x7e;//点亮第一位数码管
- wela=0;//关闭位选
- dula=1;;//打开段选
- P0=table[bai];
- dula=0;
- wela=1;
- P0=0x7d;
- wela=0;
- dula=1;
- P0=table[ge];
- dula=0;
- main()
- {
- ACK_flag=0;
- Init();//初始化
- start();
- sendbyte(AT24C02+0)//器件地址加0
- if(!test_ASK())//若不应答,则为假,然 后取反
- {
- ACK_flag=1;
- }
- t=readbyte();//读出的时间赋予t
- if(t>100)
- t=0;//预防首次读取出错误数据
- TMOD=0x01;//定时器工作在方式1
- ET0=1;//开定时器0
- EA=1;//开总定时器
- TH0=(65536-50000)/256;//对TH0TL0赋值
- TL0=(65536-50000)%256;//使定时器50毫秒中断一次
- TR0=1;//开始计时
- while(1)
- {
- display(t/10,t%10)
- if(write==1)//判断计时器是否为1秒
- {
- write=0;//清0
- sendbyte(2,t)//在地址2中写入数据t
- }
-
- }
- }
- void write_address(uchar date,uchar address)
- {
- start();
- writebyte(0xa0);
- Mster_ASK;//应答
- write_byte(date);
- test_ASK;//应答
- stop();
- }
- void read_add(uchar address)
- {
- uchar date;
- start();
- writebyte(0xa0);
- Mster_ASK();
- writebyte(address);
- test_ASK();
- start();
- writebyte(0xa1);
- Mster_ASK();
- test_ASK();
- date=writebyte();
- stop();
- return date;
- }
- bit I2C_WriteData(uchar ADDR,uchar DAT) //I2C写数据
- {
- I2C_Start();
- I2C_send_byte(AT24C02_ADDR+0);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(ADDR);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(DAT);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_Stop();
- return(1);
- }
- uchar I2C_ReadData(uchar ADDR) //I2C读数据
- {
- uchar dat;
- I2C_Start();
- I2C_send_byte(AT24C02_ADDR+0);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(ADDR);
- if (!Test_ACK())
- {
- return(0);
- }
- Master_ACK(0);
- I2C_Start();
- I2C_send_byte(AT24C02_ADDR+1);
- if (!Test_ACK())
- {
- return(0);
- }
- dat = I2C_read_byte();
- Master_ACK(0);
- I2C_Stop();
- return(dat);
- }
- void main()
- {
- I2C_init();
- Timer0_init();
- EEPROM_DATA = I2C_ReadData(255); //上电后首先读出24C02第255单元的值
- while(1)
- {
- display(EEPROM_DATA);//数码管显示
-
- }
- }
- /*定时器0中断服务程序*/
- void timer0() interrupt 1 //T0内部查询顺序1
- {
- uchar i;
- TH0 = 0x4b;
- TL0 = 0xfe; //T0 定时50ms
- i++;
- if (i == 100) //5秒时间到
- {
- i = 0; //计数清零
- if (EEPROM_DATA < 99) //判断待写数据值
- {
- EEPROM_DATA++;
- }
- else
- {
- EEPROM_DATA = 0;
- }
- if(!I2C_WriteData(255,EEPROM_DATA)) //写入待写数据并判断是否成功写入
- {
- LED1 = 0;//如果写失败 让LED1小灯点亮
- }
- else
- {
- LED1 = 1;
- }
- }
- }
复制代码
|