標(biāo)題:
單片機(jī)模擬I2C總線通信Proteus仿真源程序
[打印本頁]
作者:
wuchx12
時(shí)間:
2020-3-6 14:45
標(biāo)題:
單片機(jī)模擬I2C總線通信Proteus仿真源程序
書上關(guān)于89c52連接24C02,利用I2C總線通信實(shí)現(xiàn)秒表斷電或復(fù)位后從新開機(jī)仍能將上次數(shù)據(jù)讀取出來繼續(xù)計(jì)時(shí),書上關(guān)于I2C總線通信部分的代碼用proteus模擬無法成功,我從網(wǎng)上找到的一個(gè)I2C_51.C和.H文件進(jìn)行了改寫,實(shí)現(xiàn)了Proteus模擬。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei圖片20200306143811.png
(92.35 KB, 下載次數(shù): 63)
下載附件
2020-3-6 14:39 上傳
單片機(jī)源程序如下:
/*************************************
單片機(jī)模擬I2C總線C語言代碼
*************************************/
//#include<string.h>
#include<reg52.h>
#include "I2C_51.h"
/********** Function Definition 函數(shù)定義 ***************/
void delay(uint t) /*延時(shí)函數(shù)*/
{
while(t!=0)
t--;
}
/*初始化I2C總線*****************************************/
void i2c_init()
{
scl=1;
delay(DELAY_TIME);
sda=1;
delay(DELAY_TIME);
}
/*啟動I2C總線的函數(shù),當(dāng)scl為高電平時(shí)使sda產(chǎn)生一個(gè)負(fù)跳變*/
void i2c_start()
{
sda=1;
scl=1;
delay(DELAY_TIME);
sda=0;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*終止I2C總線,當(dāng)scl為高電平時(shí)使sda產(chǎn)生一個(gè)正跳變******/
void i2c_stop()
{
scl=0;
sda=0;
scl=1;
delay(DELAY_TIME);
sda=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*發(fā)送0,在scl為高電平時(shí)使sda信號為低*****************/
void send_0() /* SEND ACK */
{
sda=0;
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*發(fā)送1,在scl為高電平時(shí)使sda信號為高****************/
void send_1()
{
sda=1;
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
}
/*發(fā)送完一個(gè)字節(jié)后檢驗(yàn)設(shè)備的應(yīng)答信號****************/
bit check_acknowledge()
{
sda=1;
scl=1;
delay(DELAY_TIME/2);
F0=sda;
delay(DELAY_TIME/2);
scl=0;
delay(DELAY_TIME);
if(F0==1)
return FALSE;
return TRUE;
}
/*向I2C總線寫一個(gè)字節(jié)*******************************/
void write_i2c_byte(char b)
{
char i;
for(i=8;i!=0;i--){ //for(i=0;i<8;i++)
if(b&0x80)
send_1();
else
send_0();
b<<=1;
/*if((b<<i)&0x80) //原來寫法
SEND_1();
else
SEND_0();*/
}
}
/*從I2C總線讀一個(gè)字節(jié)******************************/
char read_i2c_byte()
{
char b=0,i;
for(i=0;i<8;i++)
{
sda=1; /*釋放總線*/
scl=1; /*接受數(shù)據(jù)*/
delay(10);
F0=sda;
delay(10);
scl=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
/***************write one byte***********************************************************
功能:將ch寫到地址add處 *
輸入:地址add,待寫字節(jié)數(shù)據(jù)ch *
輸出:無 *
****************************************************************************************/
void write_byte(uchar add, uchar ch)
{
i2c_start(); //start
write_i2c_byte(0xa0); //control byte:1010+A2+A1+A0+1(write)/0(read)
while(!check_acknowledge());
write_i2c_byte(add); //address
while(!check_acknowledge());
write_i2c_byte(ch); //data
while(!check_acknowledge());
i2c_stop(); //stop
}
/***************Read one byte************************************************************
功能:從地址ch處讀取一字節(jié)數(shù)據(jù) *
輸入:地址add *
輸出:從地址add處讀得的一字節(jié)數(shù)據(jù) *
****************************************************************************************/
char read_byte(uchar add)
{
char b;
i2c_start(); //start
write_i2c_byte(0xa0); //control byte
while(!check_acknowledge());
write_i2c_byte(add); //address
while(!check_acknowledge());
i2c_start(); //start
write_i2c_byte(0xa1); //data
while(!check_acknowledge());
b=read_i2c_byte(); //N0 Acknowledge
// i2c_stop(); //stop 有該停止信號proteus要報(bào)錯(cuò)
return b;
}
/***************write string***************************************************************
功能:以add為起始地址連續(xù)寫入字符串p *
輸入:地址,待寫字符串 *
輸出:無 *
注意:字符串p的長度不需小于一頁數(shù)據(jù)(24c02c的一頁為16byte)。 *
數(shù)據(jù)字節(jié)臨時(shí)存儲在片內(nèi)頁緩沖器中。在主器件發(fā)送停止條件之后,這些數(shù)據(jù)將被寫入存儲器。*
每接收一個(gè)字,內(nèi)部地址計(jì)數(shù)器加一。如果在停止條件產(chǎn)生前,主器件有超出一頁的數(shù)據(jù)要發(fā)送,
地址計(jì)數(shù)器將會翻轉(zhuǎn),先前寫入的數(shù)據(jù)將被覆蓋。 *
******************************************************************************************/
/*void write_string(uchar add, uchar *p)
{
/*224C02C(2kbit),strlen(p)should<=16bit*/
/*uchar i;
i2c_start();
write_i2c_byte(0xa0);
while(!check_acknowledge());
write_i2c_byte(add);
while(!check_acknowledge());
for(i=strlen(p);i!=0;i--)
{
write_i2c_byte(*p);
while(!check_acknowledge());
p++;
}
i2c_stop();
}*/
/***************read string*************************************************************************
功能:以add為起始地址連續(xù)讀len長字節(jié)數(shù)據(jù),并通過*P返回 *
輸入:地址add,讀取長度len *
輸出:字符串*p *
說明:連續(xù)讀操作的起動過程和隨機(jī)讀操作相同,只是在 24XX發(fā)送完第一個(gè)數(shù)據(jù)字節(jié)后,主器件發(fā)出確認(rèn)信號,*
而在隨機(jī)讀操作中發(fā)送的是停止條件。確認(rèn)信號指示 24XX 器件發(fā)送下一個(gè)連續(xù)地址的數(shù)據(jù)字節(jié)(圖 8-4)。
在24器件向主器件發(fā)送完最后一個(gè)字節(jié)后,主器件不會 產(chǎn)生確認(rèn)信號,而是產(chǎn)生停止條件。 *
***************************************************************************************************/
/*void read_string(uchar add, uchar *p, uchar len)
{
i2c_start(); //start
write_i2c_byte(0xa0);
while(!check_acknowledge()); //control byte,
write_i2c_byte(add);
while(!check_acknowledge()); //address
i2c_start(); //start
write_i2c_byte(0xa1);
while(!check_acknowledge()); //data
while(len--)
{
*p=read_i2c_byte();
sda=0; //MCU發(fā)確認(rèn)信號,使器件發(fā)送下一個(gè)連續(xù)地址的數(shù)據(jù)字節(jié)
scl=1;
delay(DELAY_TIME);
scl=0;
delay(DELAY_TIME);
p++;
} //讀完最后一個(gè)字節(jié)不確認(rèn),停止結(jié)束
i2c_stop(); //stop
}*/
復(fù)制代碼
所有資料51hei提供下載:
新建文件夾.rar
(301.46 KB, 下載次數(shù): 48)
2020-3-6 14:45 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1