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