單片機(jī)C語(yǔ)言實(shí)例-353-對(duì)I2C總線上掛接多個(gè)AT24C02的讀寫操作
//實(shí)例87:對(duì)I2C總線上掛接多個(gè)AT24C02的讀寫操作
#include <reg51.h> // 包含51單片機(jī)寄存器定義的頭文件
#include <intrins.h> //包含_nop_()函數(shù)定義的頭文件
#define OP_READ1 0xa1 // 器件1地址以及讀取操作,0xa1即為1010 0001B
#define OP_WRITE1 0xa0 // 器件1地址以及寫入操作,0xa1即為1010 0000B
#define OP_READ2 0xaf // 器件2地址以及讀取操作,0xa1即為1010 1111B
#define OP_WRITE2 0xae // 器件2地址以及寫入操作,0xa1即為1010 1110B
sbit SDA=P3^4; //將串行數(shù)據(jù)總線SDA位定義在為P3.4引腳
sbit SCL=P3^3; //將串行時(shí)鐘總線SDA位定義在為P3.3引腳
/*****************************************************
函數(shù)功能:延時(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í)若干毫秒
入口參數(shù):n
***************************************************/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函數(shù)功能:開(kāi)始數(shù)據(jù)傳送
***************************************************/
void start()
// 開(kāi)始位
{
SDA = 1; //SDA初始化為高電平“1”
SCL = 1; //開(kāi)始數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SDA = 0; //SDA的下降沿被認(rèn)為是開(kāi)始信號(hào)
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SCL = 0; //SCL為低電平時(shí),SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
_nop_(); //等待一個(gè)機(jī)器周期
}
/***************************************************
函數(shù)功能:結(jié)束數(shù)據(jù)傳送
***************************************************/
void stop()
// 停止位
{
SDA = 0; //SDA初始化為低電平“0”
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SCL = 1; //結(jié)束數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SDA = 1; //SDA的上升沿被認(rèn)為是結(jié)束信號(hào)
}
/***************************************************
函數(shù)功能:從AT24Cxx讀取數(shù)據(jù)
出口參數(shù):x
***************************************************/
unsigned char ReadData()
// 從AT24Cxx移入數(shù)據(jù)到MCU
{
unsigned char i;
unsigned char x; //儲(chǔ)存從AT24Cxx中讀出的數(shù)據(jù)
for(i = 0; i < 8; i++)
{
SCL = 1; //SCL置為高電平
x<<=1; //將x中的各二進(jìn)位向左移一位
x|=(unsigned char)SDA; //將SDA上的數(shù)據(jù)通過(guò)按位“或“運(yùn)算存入x中
SCL = 0; //在SCL的下降沿讀出數(shù)據(jù)
}
return(x); //將讀取的數(shù)據(jù)返回
}
/***************************************************
函數(shù)功能:向AT24Cxx的當(dāng)前地址寫入數(shù)據(jù)
入口參數(shù):y (儲(chǔ)存待寫入的數(shù)據(jù))
***************************************************/
//在調(diào)用此數(shù)據(jù)寫入函數(shù)前需首先調(diào)用開(kāi)始函數(shù)start(),所以SCL=0
bit WriteCurrent(unsigned char y)
{
unsigned char i;
bit ack_bit; //儲(chǔ)存應(yīng)答位
for(i = 0; i < 8; i++) // 循環(huán)移入8個(gè)位
{
SDA = (bit)(y&0x80); //通過(guò)按位“與”運(yùn)算將最高位數(shù)據(jù)送到S
//因?yàn)閭魉蜁r(shí)高位在前,低位在后
_nop_(); //等待一個(gè)機(jī)器周期
SCL = 1; //在SCL的上升沿將數(shù)據(jù)寫入AT24Cxx
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SCL = 0; //將SCL重新置為低電平,以在SCL線形成傳送數(shù)據(jù)所需的8?jìng)(gè)脈沖
y <<= 1; //將y中的各二進(jìn)位向左移一位
}
SDA = 1; // 發(fā)送設(shè)備(主機(jī))應(yīng)在時(shí)鐘脈沖的高電平期間(SCL=1)釋放SDA線,
//以讓SDA線轉(zhuǎn)由接收設(shè)備(AT24Cxx)控制
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
SCL = 1; //根據(jù)上述規(guī)定,SCL應(yīng)為高電平
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
_nop_(); //等待一個(gè)機(jī)器周期
ack_bit = SDA; //接受設(shè)備(AT24Cxx)向SDA送低電平,表示已經(jīng)接收到一個(gè)字節(jié)
//若送高電平,表示沒(méi)有接收到,傳送異常
SCL = 0; //SCL為低電平時(shí),SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
return ack_bit;// 返回AT24Cxx應(yīng)答位
}
/***************************************************
函數(shù)功能:向第一個(gè)AT24Cxx中的指定地址寫入數(shù)據(jù)
入口參數(shù):add (儲(chǔ)存指定的地址);dat(儲(chǔ)存待寫入的數(shù)據(jù))
***************************************************/
void WriteSet1(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數(shù)據(jù)WriteCurrent
{
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_WRITE1); //選擇要操作的第一個(gè)AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù)
WriteCurrent(add); //寫入指定地址
WriteCurrent(dat); //向當(dāng)前地址(上面指定的地址)寫入數(shù)據(jù)
stop(); //停止數(shù)據(jù)傳遞
delaynms(4); //1個(gè)字節(jié)的寫入周期為1ms, 最好延時(shí)1ms以上
}
/***************************************************
函數(shù)功能:向第二個(gè)AT24Cxx中的指定地址寫入數(shù)據(jù)
入口參數(shù):add (儲(chǔ)存指定的地址);dat(儲(chǔ)存待寫入的數(shù)據(jù))
***************************************************/
void WriteSet2(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數(shù)據(jù)WriteCurrent
{
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_WRITE2); //選擇要操作的AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù)
WriteCurrent(add); //寫入指定地址
WriteCurrent(dat); //向當(dāng)前地址(上面指定的地址)寫入數(shù)據(jù)
stop(); //停止數(shù)據(jù)傳遞
delaynms(4); //1個(gè)字節(jié)的寫入周期為1ms, 最好延時(shí)1ms以上
}
/***************************************************
函數(shù)功能:從第一個(gè)AT24Cxx中的當(dāng)前地址讀取數(shù)據(jù)
出口參數(shù):x (儲(chǔ)存讀出的數(shù)據(jù))
***************************************************/
unsigned char ReadCurrent1()
{
unsigned char x;
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_READ1); //選擇要操作的第一個(gè)AT24Cxx芯片,并告知要讀其數(shù)據(jù)
x=ReadData(); //將讀取的數(shù)據(jù)存入x
stop(); //停止數(shù)據(jù)傳遞
return x; //返回讀取的數(shù)據(jù)
}
/***************************************************
函數(shù)功能:從第二個(gè)AT24Cxx中的當(dāng)前地址讀取數(shù)據(jù)
出口參數(shù):x (儲(chǔ)存讀出的數(shù)據(jù))
***************************************************/
unsigned char ReadCurrent2()
{
unsigned char x;
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_READ2); //選擇要操作的第二個(gè)AT24Cxx芯片,并告知要讀其數(shù)據(jù)
x=ReadData(); //將讀取的數(shù)據(jù)存入x
stop(); //停止數(shù)據(jù)傳遞
return x; //返回讀取的數(shù)據(jù)
}
/***************************************************
函數(shù)功能:從第一個(gè)AT24Cxx中的指定地址讀取數(shù)據(jù)
入口參數(shù):set_addr
出口參數(shù):x
***************************************************/
unsigned char ReadSet1(unsigned char set_addr)
// 在指定地址讀取
{
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_WRITE1); //選擇要操作的第一個(gè)AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù)
WriteCurrent(set_addr); //寫入指定地址
return(ReadCurrent1()); //從第一個(gè)AT24Cxx芯片指定地址讀出數(shù)據(jù)并返回
}
/***************************************************
函數(shù)功能:從第二個(gè)AT24Cxx中的指定地址讀取數(shù)據(jù)
入口參數(shù):set_addr
出口參數(shù):x
***************************************************/
unsigned char ReadSet2(unsigned char set_addr)
// 在指定地址讀取
{
start(); //開(kāi)始數(shù)據(jù)傳遞
WriteCurrent(OP_WRITE2); //選擇要操作的第二個(gè)AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù)
WriteCurrent(set_addr); //寫入指定地址
return(ReadCurrent2()); //從第二個(gè)AT24Cxx芯片指定地址讀出數(shù)據(jù)并返回
}
/***************************************************
函數(shù)功能:主函數(shù)
***************************************************/
main(void)
{
unsigned char x;
SDA = 1; // SDA=1,SCL=1,使主從設(shè)備處于空閑狀態(tài)
SCL = 1;
WriteSet1(0x36,0xaa); //將數(shù)據(jù)"0xaa"寫入第一個(gè)AT24C02的指定地址"0x36"
x=ReadSet1(0x36); //從第二個(gè)AT24C02中的指定地址"0x36"讀出數(shù)據(jù)
WriteSet2(0x48,x); //將讀出的數(shù)據(jù)寫入第二個(gè)AT24C02的指定地址"0x48"?
P1=ReadSet2(0x48); //將從第二個(gè)AT24C02的指定地址讀出的數(shù)據(jù)送P1口顯示驗(yàn)證
}
更多詳情參考附件文檔
+08:00C098聯(lián)盟網(wǎng)6569.png (11.01 KB, 下載次數(shù): 2)
下載附件
保存到相冊(cè)
2022-4-2 09:21 上傳
游客,如果您要查看本帖隱藏內(nèi)容請(qǐng) 回復(fù)
|