單片機源程序如下:
- #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;
- }
- }
- }
復制代碼
|