?? iic.h
字號:
//虛擬iic操作
//iic.h
#include "REG52s.H"
#include "intrins.h"
#define numlen 5
#define flashadw 0xa0//定義操作對象的寫地址
#define flashadr 0xa1//定義操作對象讀地址
typedef unsigned char uchar;
typedef unsigned int uint;
sbit VSDA=P1^7;//iic虛擬數(shù)據(jù)線
sbit VSCL=P1^6;//iic虛擬時(shí)鐘線
bit error0,ftemp;
bdata uchar bitdata;//定義到BDATA區(qū),在移位操作時(shí)可方便實(shí)現(xiàn)位尋址
sbit bd7=bitdata^7;//bitdata.7,即最高位
sbit bd0=bitdata^0;//bitdata.0,即最低位
void iicstart(void);
void iicstop(void);
void mack(void);
void mnack(void);
void cack(void);
void wrbyt(uchar data0);
uchar rdbyt(void);
void delay1ms(uint time);
void config(void);
uchar flashrb(bit end);
uchar flashra(uchar adrh,uchar adrl,bit end);
void flashwa(uchar adrh,uchar adrl);
void flashwb(uchar dataw, bit end);
void delay1us();
void iicstart(void){//產(chǎn)生iic位起始信號(幀起始),具體可參見iic總線或SMBUS總線
VSDA=1;
VSCL=1;
delay1us();
VSDA=0;
delay1us();
VSCL=0;
}
void iicstop(void){//產(chǎn)生iic位停止信號(幀結(jié)尾)
VSDA=0;
VSCL=1;
delay1us();
VSDA=1;
delay1us();
}
void mack(void){//主機(jī)應(yīng)答ACK信號,即單片機(jī)對操作對象的應(yīng)答信號
VSDA=0;
VSCL=1;
delay1us();
VSCL=0;
}
void mnack(void){//主機(jī)不應(yīng)答NACK信號,一般用于讀控制時(shí),告知對象產(chǎn)生幀結(jié)尾
VSDA=1;
VSCL=1;
delay1us();
VSCL=0;
}
void cack(void){//查詢從機(jī)應(yīng)答信號,若從機(jī)應(yīng)答,則error0(全局變量)返回0,從機(jī)不應(yīng)答,
//則返回1
VSDA=1;
VSCL=1;
_nop_();
error0=0;
ftemp=VSDA;
if(ftemp)
error0=1;
VSCL=0;
}
void wrbyt(uchar data0){//一字節(jié)寫操作,先發(fā)送高位
idata uchar i;
bitdata=data0;//巧用bitdata處于BDATA區(qū),能位尋址
for(i=0;i<8;i++){
if(bd7){
VSDA=1;
VSCL=1;
delay1us();
VSCL=0;
}
else{
VSDA=0;
VSCL=1;
delay1us();
VSCL=0;
}
bitdata<<=1;
}
}
uchar rdbyt(void){//一字節(jié)讀操作
idata uchar i;
for(i=0;i<7;i++){
VSDA=1;
VSCL=1;
bd0=VSDA;//讀操作時(shí),位流中高字節(jié)在前,所以巧用左移可獲取數(shù)據(jù)
bitdata<<=1;
VSCL=0;
}
VSDA=1;
VSCL=1;
bd0=VSDA;
VSCL=0;
return bitdata;
}
void flashwa(uchar adrh,uchar adrl){//對EEPROM寫存儲地址操作
restart:
iicstart();//產(chǎn)生位起始
wrbyt(flashadw);//寫設(shè)備地址
cack();//檢查從機(jī)應(yīng)答情況
if(error0)
goto restart;//從機(jī)沒應(yīng)答則重發(fā)
wrbyt(adrh);//寫入存儲高字節(jié)地址
cack();
if(error0)
goto restart;
wrbyt(adrl);//寫入存儲第字節(jié)地址
cack();
if(error0){
iicstop();
goto restart;
}//注意地址寫完后,沒有寫位結(jié)束,因而EEPROM一直處于寫入模式
}
void flashwb(uchar dataw, bit end){//對EEPROM寫入數(shù)據(jù)操作
//end控制是否產(chǎn)生位停止,停止當(dāng)前幀,若bit=1,則產(chǎn)生位停止
//若bit=0,則當(dāng)前幀沒有結(jié)束,可繼續(xù)寫入地址,適用于頁操作模式
//值得注意的是要考慮數(shù)據(jù)是否寫入過多,要控制EEPROM換頁操作
//換頁之前要確保已經(jīng)產(chǎn)生位停止操作,否則調(diào)用flashwa()寫地址無效
wrbyt(dataw);
cack();
if(end)
iicstop();
}
uchar flashra(uchar adrh,uchar adrl,bit end){//讀EEPROM地址為adrh-adrl的數(shù)據(jù),且返回值為
//讀取的數(shù)據(jù)值存在內(nèi)在bug,若設(shè)備沒有相應(yīng),則一直處于重發(fā)狀態(tài),相
//當(dāng)于死機(jī),對寫操作也存在此bug若單數(shù)據(jù)讀,則end為1,若多數(shù)據(jù)讀,end為0
uchar i;
restart:
iicstart();
wrbyt(flashadw);//寫入設(shè)備地址+寫控制
cack();
if(error0)
goto restart;
wrbyt(adrh);//寫入存儲高字節(jié)地址
cack();
if(error0){
iicstop();
goto restart;
}
wrbyt(adrl);//寫入存儲低字節(jié)地址
cack();
if(error0){
iicstop();//產(chǎn)生位停止
goto restart;
}
//以上代碼實(shí)質(zhì)上可以直接調(diào)用flashwa(adrh,adrl);不過重寫一遍避免了調(diào)用函數(shù)時(shí)
//參數(shù)傳遞,執(zhí)行效率更高
restart2:
iicstart();//寫完地址,重新發(fā)送起始位
wrbyt(flashadr);//寫入設(shè)備地址+讀控制
cack();
if(error0)
goto restart2;
i=rdbyt();//讀取數(shù)據(jù)
if(end){
mnack();//若當(dāng)前讀取為最后一個(gè)數(shù)據(jù),則發(fā)送NACK給從機(jī),并產(chǎn)生位停止
iicstop();
}
else
mack();//當(dāng)前讀取不是最后一個(gè)數(shù)據(jù),發(fā)送ACK給從機(jī)
return i;
}
uchar flashrb(bit end){//在多字節(jié)讀取模式下,繼續(xù)讀取數(shù)據(jù),若end為1,
//則當(dāng)前操作為最后一個(gè)讀取值
uchar i;
i=rdbyt();
if(end){
mnack();
iicstop();
}
else
mack();
return i;
}
void delay1ms(uint time){//延遲1ms
uint ii;
uint jj;
for (ii=0;ii<time;ii++){
for(jj=0;jj<300;jj++);
}
}
void config (void) {//可以不用
AUXR=0x1a;
} //End of config
void delay1us(){//修改該函數(shù)可以修改對IIC操作的時(shí)鐘頻率
uchar tt;
for(tt=0;tt<3;tt++);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -