//實例85:將數(shù)據(jù)"0x0f"寫入AT24C02再讀出送P1口顯示
#include <reg51.h> // 包含51單片機(jī)寄存器定義的頭文件 #include <intrins.h> //包含_nop_()函數(shù)定義的頭文件 #define OP_READ 0xa1 // 器件地址以及讀取操作,0xa1即為1010 0001B #define OP_WRITE 0xa0 // 器件地址以及寫入操作,0xa1即為1010 0000B sbit SDA=P3^4; //將串行數(shù)據(jù)總線SDA位定義在為P3.4引腳 sbit SCL=P3^3; //將串行時鐘總線SDA位定義在為P3.3引腳 /*****************************************************
函數(shù)功能:延時1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以認(rèn)為是1毫秒 ***************************************************/ void delay1ms() { unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } /*****************************************************
函數(shù)功能:延時若干毫秒 入口參數(shù):n ***************************************************/ void delaynms(unsigned char n) { unsigned char i; for(i=0;i<n;i++) delay1ms(); } /*************************************************** 函數(shù)功能:開始數(shù)據(jù)傳送 ***************************************************/ void start() // 開始位 { SDA = 1; //SDA初始化為高電平“1” SCL = 1; //開始數(shù)據(jù)傳送時,要求SCL為高電平“1” _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SDA = 0; //SDA的下降沿被認(rèn)為是開始信號 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SCL = 0; //SCL為低電平時,SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞) } /*************************************************** 函數(shù)功能:結(jié)束數(shù)據(jù)傳送 ***************************************************/ void stop() // 停止位 { SDA = 0; //SDA初始化為低電平“0” _n SCL = 1; //結(jié)束數(shù)據(jù)傳送時,要求SCL為高電平“1” _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SDA = 1; //SDA的上升沿被認(rèn)為是結(jié)束信號 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SDA=0; SCL=0; } /*************************************************** 函數(shù)功能:從AT24Cxx讀取數(shù)據(jù) 出口參數(shù):x ***************************************************/ unsigned char ReadData() // 從AT24Cxx移入數(shù)據(jù)到MCU { unsigned char i; unsigned char x; //儲存從AT24Cxx中讀出的數(shù)據(jù) for(i = 0; i < 8; i++) { SCL = 1; //SCL置為高電平 x<<=1; //將x中的各二進(jìn)位向左移一位 x|=(unsigned char)SDA; //將SDA上的數(shù)據(jù)通過按位“或“運算存入x中 SCL = 0; //在SCL的下降沿讀出數(shù)據(jù) } return(x); //將讀取的數(shù)據(jù)返回 } /*************************************************** 函數(shù)功能:向AT24Cxx的當(dāng)前地址寫入數(shù)據(jù) 入口參數(shù):y (儲存待寫入的數(shù)據(jù)) ***************************************************/ //在調(diào)用此數(shù)據(jù)寫入函數(shù)前需首先調(diào)用開始函數(shù)start(),所以SCL=0 bit WriteCurrent(unsigned char y) { unsigned char i; bit ack_bit; //儲存應(yīng)答位 for(i = 0; i < 8; i++) // 循環(huán)移入8個位 { SDA = (bit)(y&0x80); //通過按位“與”運算將最高位數(shù)據(jù)送到S //因為傳送時高位在前,低位在后 _nop_(); //等待一個機(jī)器周期 SCL = 1; //在SCL的上升沿將數(shù)據(jù)寫入AT24Cxx _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SCL = 0; //將SCL重新置為低電平,以在SCL線形成傳送數(shù)據(jù)所需的8個脈沖 y <<= 1; //將y中的各二進(jìn)位向左移一位 } SDA = 1; // 發(fā)送設(shè)備(主機(jī))應(yīng)在時鐘脈沖的高電平期間(SCL=1)釋放SDA線, //以讓SDA線轉(zhuǎn)由接收設(shè)備(AT24Cxx)控制 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 SCL = 1; //根據(jù)上述規(guī)定,SCL應(yīng)為高電平 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 _nop_(); //等待一個機(jī)器周期 ack_bit = SDA; //接受設(shè)備(AT24Cxx)向SDA送低電平,表示已經(jīng)接收到一個字節(jié) //若送高電平,表示沒有接收到,傳送異常 SCL = 0; //SCL為低電平時,SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞) return ack_bit; // 返回AT24Cxx應(yīng)答位 } /*************************************************** 函數(shù)功能:向AT24Cxx中的指定地址寫入數(shù)據(jù) 入口參數(shù):add (儲存指定的地址);dat(儲存待寫入的數(shù)據(jù)) ***************************************************/ void WriteSet(unsigned char add, unsigned char dat) // 在指定地址addr處寫入數(shù)據(jù)WriteCurrent { start(); //開始數(shù)據(jù)傳遞 WriteCurrent(OP_WRITE); //選擇要操作的AT24Cxx芯片,并告知要對其寫入數(shù)據(jù) WriteCurrent(add); //寫入指定地址 WriteCurrent(dat); //向當(dāng)前地址(上面指定的地址)寫入數(shù)據(jù) stop(); //停止數(shù)據(jù)傳遞 delaynms(4); //1個字節(jié)的寫入周期為1ms, 最好延時1ms以上 } /*************************************************** 函數(shù)功能:從AT24Cxx中的當(dāng)前地址讀取數(shù)據(jù) 出口參數(shù):x (儲存讀出的數(shù)據(jù)) ***************************************************/ unsigned char ReadCurrent() { unsigned char x; start(); //開始數(shù)據(jù)傳遞 WriteCurrent(OP_READ); //選擇要操作的AT24Cxx芯片,并告知要讀其數(shù)據(jù) x=ReadData(); //將讀取的數(shù)據(jù)存入x stop(); //停止數(shù)據(jù)傳遞 return x; //返回讀取的數(shù)據(jù) } /*************************************************** 函數(shù)功能:從AT24Cxx中的指定地址讀取數(shù)據(jù) 入口參數(shù):set_addr 出口參數(shù):x ***************************************************/ unsigned char ReadSet(unsigned char set_addr) // 在指定地址讀取 { start(); //開始數(shù)據(jù)傳遞 WriteCurrent(OP_WRITE); //選擇要操作的AT24Cxx芯片,并告知要對其寫入數(shù)據(jù) WriteCurrent(set_addr); //寫入指定地址 return(ReadCurrent()); //從指定地址讀出數(shù)據(jù)并返回 } /*************************************************** 函數(shù)功能:主函數(shù) ***************************************************/ main(void) { SDA = 1; // SDA=1,SCL=1,使主從設(shè)備處于空閑狀態(tài) SCL = 1; WriteSet(0x36,0x0f); //在指定地址“0x36”中寫入數(shù)據(jù)“0x0f” P1=ReadSet(0x36); //從指定地址“0x36中讀取數(shù)據(jù)并送P1口顯示 } |
|