⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iic.h

📁 主要用C8051F02X单片机的开发与应用
💻 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 + -