AVR單片機IO仿真I2C
#define EEP_PORT PORTC //定義是使用PROTC口
#define EEP_DDR DDRC //定義是使用PROTC口
#define SDA 0X10 //定義sda連接的是portd1
#define SCL 0X20 //定義scl連接的是portd0
//#define WP 0X04 //定義wp連接的是portd2
#define EEP_ADD_R 0xa1 //寫I2C從器件地址和讀方式 a0,a1接地
#define EEP_ADD_W 0xa0 //寫I2C從器件地址和寫方式 a0,a1接地
void delay(unsigned int us)
{
while(us--);
}
void eep_init(void)
{
EEP_DDR|= SDA | SCL ;//| WP ;
EEP_PORT|=SDA | SCL ;//| WP ;
}
void send(void)
{
EEP_PORT|=SCL;
asm("nop");
EEP_PORT&=~SCL;
}
/********************************************
內(nèi)部函數(shù),I2C開始
********************************************/
void Start(void)
{
EEP_PORT|=SDA; //sda
EEP_PORT|=SCL; //scl
asm("nop");
EEP_PORT&=~SDA;
asm("nop");
EEP_PORT&=~SCL;
}
/********************************************
內(nèi)部函數(shù),I2C結(jié)束
********************************************/
void Stop(void)
{
EEP_PORT&=~SDA;
EEP_PORT&=~SCL;
asm("nop");
EEP_PORT|=SCL;
asm("nop");
EEP_PORT|=SDA;
asm("nop");
}
/********************************************
內(nèi)部函數(shù),等待ACK
********************************************/
void ACK(void)
{
unsigned char errtime=20;
EEP_PORT|=SDA; //上拉
EEP_DDR&=~SDA; //設(shè)置為輸入口
EEP_PORT|=SCL;
asm("nop");
while(PINC&SDA)
{ errtime--;
if(!errtime)
{
Stop();
EEP_PORT&=~SDA; //超時,給他個離開的理由
}
}
EEP_PORT&=~SCL;
asm("nop");
EEP_DDR|=SDA; //設(shè)置為輸出口
}
/********************************************
內(nèi)部函數(shù).輸出數(shù)據(jù)字節(jié)
********************************************/
void writebyte(unsigned char wdata)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((wdata&0x80)){EEP_PORT|=SDA;}else{EEP_PORT&=~SDA;}
wdata<<=1;
send(); //發(fā)送一個位
}
}
/********************************************
內(nèi)部函數(shù).輸入數(shù)據(jù)
********************************************/
unsigned char Readbyte(void)
{
unsigned char i,bytedata;
EEP_DDR&=~SDA; //設(shè)置為輸入?
for(i=0;i<8;i++)
{
EEP_PORT|=SCL;
bytedata<<=1;
if(PINC&SDA){
bytedata|=0X01;
}else{
bytedata&=~0X01;
}
EEP_PORT&=~SCL;
asm("nop");
}
EEP_DDR|=SDA;
return(bytedata);
}
/********************讀24cxx--外部調(diào)用********************/
unsigned char read_eep(unsigned char add1,unsigned char add2)
{ unsigned char mdata;
Start(); //起始位
writebyte(EEP_ADD_W); //寫eeprom地址+1個寫命令
ACK(); //等待應(yīng)答信號
writebyte(add1); //寫如訪問地址
ACK(); //等待應(yīng)答信號
writebyte(add2); //寫入訪問地址
ACK(); //等待應(yīng)答信號
Start(); //起始位
writebyte(EEP_ADD_R); //寫eeprom地址+1個讀命令
ACK(); //等待應(yīng)答信號
mdata=Readbyte(); //獲取數(shù)據(jù)
Stop(); //發(fā)送停止位置
asm("nop"); //此處延時根據(jù)實際情況,如果不延時,可能會不正常
return(mdata);
}
/********************寫24cxx--外部調(diào)用********************/
void write_eep(unsigned char add1,unsigned char add2,unsigned char udata)
{
//EEP_PORT&=~WP; //關(guān)閉寫保護
Start(); //起始位
writebyte(EEP_ADD_W); //寫eeprom地址+1個寫命令
ACK(); //等待應(yīng)答信號
writebyte(add1); //寫如訪問地址
ACK(); //等待應(yīng)答信號
writebyte(add2); //寫如訪問地址
ACK(); //等待應(yīng)答信號
writebyte(udata); //寫入數(shù)據(jù)
ACK(); //等待應(yīng)答信號
Stop(); //發(fā)送停止位
delay(24000);
//delay_nms(4); //此處延時根據(jù)實際情況,大多EEPROM都需要3毫秒的寫入時間,如果不延時,可能會不正常
//EEP_PORT|=WP; //打開寫保護
}
void main(void)
{
unsigned char tmp;
eep_init();
DDRC|=(1<<0);
PORTC&=~(1<<0);
write_eep(0,2,7);
tmp=read_eep(0,2);
if(tmp==7)
PORTC|=(1<<0);
while(1);
}
評論