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

📄 020_smbus.c

📁 基于C8051F020单片机的
💻 C
字号:
#include "020_SmBus.h"
#include "C8051F020.H"
#include "020_IO_PORT.H"
#include <intrins.h>

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;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -