www.pudn.com > fm31256.rar > 020_SMBus.c


#include "020_SmBus.h" 
#include "C8051F020.H" 
#include "020_IO_PORT.H" 
#include  
 
bit			  GBV_smbus_wr;					//读写控制位 
unsigned char GCV_slave_addr;				//从机地址 
unsigned char GCV_slave_subaddr_num;		//从机子地址数 
unsigned  int GIV_slave_subaddr;			//从机子地址 
unsigned char GCV_slave_data_num;			//从机数据长度 
unsigned char xdata *GPV_slave_data_array;	//读写数据指针 
 
//读写FRAM函数 
void fram_wr_fun(bit 		   B_wr,			//读写控制位 
			 	 unsigned int  subaddr, 		//读写从机子地址 
			 	 unsigned char length_of_data, 	//数据长度 
				 unsigned char *P_to_wr_array)	//读写指针 
{ 
	GBV_smbus_wr = B_wr; 
	GIV_slave_subaddr = subaddr; 
	GCV_slave_data_num = length_of_data; 
	GPV_slave_data_array = P_to_wr_array; 
 
	GCV_slave_addr = 0xa0; 
	GCV_slave_subaddr_num = 2; 
	STO = 0; 
	STA = 1; 
} 
 
//读写WDT_RTC函数 
void wdt_rtc_wr_fun(bit 		  B_wr,				//读写控制位 
				 	unsigned int  subaddr, 			//读写从地址 
			 		unsigned char length_of_data, 	//数据长度 
				 	unsigned char *P_to_wr_array)	//读写指针 
{ 
	GBV_smbus_wr = B_wr; 
	GIV_slave_subaddr = subaddr; 
	GCV_slave_data_num = length_of_data; 
	GPV_slave_data_array = P_to_wr_array; 
 
	GCV_slave_addr = 0xd0; 
	GCV_slave_subaddr_num = 1; 
	STO = 0; 
	STA = 1;	 
} 
 
void SMBUS_ISR(void)    interrupt 7 
{ 
	#define	SEND_STA				0X08 
	#define SEND_RE_STA				0X10 
	#define SEND_ADDR_W_REC_ACK		0X18 
	#define SEND_ADDR_W_REC_NACK	0X20 
	#define SEND_DATA_REC_ACK		0X28 
	#define SEND_DATA_REC_NACK		0X30 
	#define COMPETE_FAIL			0X38 
	#define SEND_ADDR_R_REC_ACK		0X40 
	#define SEND_ADDR_R_REC_NACK	0X48 
	#define REC_DATA_SEND_ACK		0X50 
	#define REC_DATA_SEND_NACK		0X58 
 
	SBUF0 = SMB0STA; 
 
	switch(SMB0STA) 
	{ 
		//08 起始位已发出,清除STA,然后判断条件相应发出读或写地址,送入SMB0DAT 
		case SEND_STA: 
		{ 
			STA = 0; 
			//发送从机+读写地址 
			if(!GBV_smbus_wr) 
		    {SMB0DAT = GCV_slave_addr; 
			 } 
			else  
			  {SMB0DAT=	GCV_slave_addr|0x01; 
			   } 
 
			SI = 0; 
			break; 
		} 
		//10 重复起始位已发出,清除STA,然后判断条件相应发出读或写地址,送入SMB0DAT 
		case SEND_RE_STA: 
		{ 
			STA = 0; 
			SMB0DAT = GCV_slave_addr; 
			SI = 0; 
			break; 
		} 
		//18 写地址已发送并收到应答,相应送出从地址或者数据到SMB0DAT,或者停止传输或者重复起始 
		case SEND_ADDR_W_REC_ACK: 
		{ 
			 
			//如果从机子地址为2位,则先发送高位,子地址数减1 
			if (GCV_slave_subaddr_num >= 2) 
			{ 
				GCV_slave_subaddr_num = 1; 
				SMB0DAT = (unsigned char)(GIV_slave_subaddr >> 8); 
			} 
			//如果从机子地址为1位,则发送低位即,子地址数减1 
			else if (GCV_slave_subaddr_num == 1) 
			{ 
				GCV_slave_subaddr_num = 0; 
				SMB0DAT = (unsigned char)GIV_slave_subaddr; 
			} 
			//没有子地址,则结束传输操作 
			else 
			{ 
				STO = 1; 
				STA = 0; 
				_nop_(); 
			} 
 
			SI = 0; 
			break; 
		} 
		//20 写地址已发送并收到非应答,发送重复起始位或者结束本次传输 
		case SEND_ADDR_W_REC_NACK: 
		{ 
			//结束本次传输 
			STO = 1; 
			STA = 0; 
			SI = 0; 
			break; 
		} 
		//28 数据已发送并收到应答,发送下个数据或者停止传输或者重复起始条件。 
		case SEND_DATA_REC_ACK: 
		{ 
			//两种可能:写操作写出子地址,读操作写出子地址 
 
			//为1则为读操作 
			if (GBV_smbus_wr) 
			{ 
				//如果从机子地址为1位,则发送低位即,子地址数减1 
				if (GCV_slave_subaddr_num == 1) 
				{ 
					GCV_slave_subaddr_num = 0; 
					SMB0DAT = (unsigned char)GIV_slave_subaddr; 
				} 
				//从机子地址发送完毕,则开始发送重复起始位 
				else 
				{ 
					//STO = 1; 
					//STA = 1; 
					//从机地址变读 
					GCV_slave_addr |= 0x01; 
					//重复起始 
					SMB0CN |= 0X30; 
				} 
			} 
			//否则为写操作 
			else 
			{ 
				//如果从机子地址为1位,则发送低位即,子地址数减1 
				if (GCV_slave_subaddr_num == 1) 
				{ 
					GCV_slave_subaddr_num = 0; 
					SMB0DAT = (unsigned char)GIV_slave_subaddr; 
				} 
				//从机子地址发送完毕,则开始发送字节 
				else if (GCV_slave_data_num > 0) 
				{	 
					SMB0DAT = *GPV_slave_data_array; 
					GCV_slave_data_num--; 
					GPV_slave_data_array++; 
				} 
				//数据发送完毕,则结束传输过程 
				else 
				{ 
					STO = 1; 
					STA = 0; 
					_nop_(); 
				} 
			} 
			SI = 0; 
			break; 
		} 
		//30 数据已发送并收到非应答,停止传输或者重复起始条件。 
		case SEND_DATA_REC_NACK: 
		{ 
			//结束本次传输 
			STO = 1; 
			SI = 0; 
			break; 
		} 
		//38 竞争失败,保存当前数据 
		case COMPETE_FAIL: 
		{ 
			_nop_(); 
			SI = 0; 
			break; 
		} 
		//40 读地址已发送并收到应答,如果只接收1个字节,则AA位清0,否则等待接收数据 
		case SEND_ADDR_R_REC_ACK: 
		{ 
			//如果只接收1个字节,则AA位清0,否则AA置1,允许应答 
			if (GCV_slave_data_num == 1) 
			{	 
				AA = 0; 
			} 
			else 
			{ 
				AA = 1; 
			} 
 
			SI = 0; 
			break; 
		} 
		//48 读地址已发送并收到非应答,发送重复起始位或者结束本次传输 
		case SEND_ADDR_R_REC_NACK: 
		{ 
			//结束本次传输操作 
			STO = 1; 
			STA = 0; 
			SI = 0; 
			break; 
		} 
		//50 数据字节已收到并已发送完毕应答,读回SMB0DAT,等待下个字节,并判断,下个字节如果为最后一个字节,则AA位清0 
		case REC_DATA_SEND_ACK: 
		{ 
			if (GCV_slave_data_num > 0) 
			{ 
				//读取数据 
				*GPV_slave_data_array = SMB0DAT; 
				GPV_slave_data_array++; 
				GCV_slave_data_num--; 
				//下个字节如果为最后一个字节,则AA位清0 
				if (GCV_slave_data_num == 1) 
				{ 
					AA = 0; 
				} 
			} 
			else 
			{ 
				//结束传输 
				STO = 1; 
				STA = 0;	 
			} 
 
			SI = 0; 
			break; 
		} 
		//58 数据字节已收到并已发送完毕非应答,则结束传输 
		case REC_DATA_SEND_NACK: 
		{ 
			_nop_(); 
			//读取数据 
			*GPV_slave_data_array = SMB0DAT; 
			//结束传输 
			STO = 1; 
			STA = 0; 
			SI = 0; 
			break; 
		} 
 
		default: 
		{ 
			//结束传输 
			STO = 1; 
			SI = 0; 
			break; 
		} 
	} 
}