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

📄 inout.c

📁 电力载波抄表系统里的电力载波采集器,采集数据再通过RS485向主站发送.
💻 C
📖 第 1 页 / 共 2 页
字号:
{
	unsigned int	addr;
	unsigned char	w_wait;

	v_IntRunFlag	= c_FMSet;
	safeCheck();
	
	addr		= EEPROMAddr;

reStart:
	GIE	= 0;						//关闭中断
	_FMWP		= 0;				//使能写入

	for(w_wait=0; w_wait<64; w_wait++)
	{
		I2CStart();

		if(_TRUE == I2CByteTX(0xa0))	//发送器件地址
		{
			break;
		}
		I2CStop();
		Delay1msx(1);
	}

	if(w_wait >= 64)
	{
		_FMWP	= 1;
		GIE		= 1;
		return	_FALSE;
	}
	
	if(_FALSE == I2CByteTX((unsigned char)(addr/0x100)))//发送逻辑地址,高字节
	{
		_FMWP	= 1;
		GIE	= 1;							//中断
		return	_FALSE;
	}
	if(_FALSE == I2CByteTX((unsigned char)(addr)))		//发送逻辑地址,低字节
	{
		_FMWP	= 1;
		GIE	= 1;							//中断
		return	_FALSE;
	}
	
	//发送数据
	while(n--)
	{
		ClrWdt();
		
		if(_FALSE == I2CByteTX(data))
		{
			_FMWP	= 1;
			GIE	= 1;							//中断
			return _FALSE;
		}
		
		addr++;							//地址标志+1,判断是否跨越边界
		if((addr%c_eepage) == 0)
		{
			break;						//结束本次写入循环,跨页处理
		}
	}
	
	//停止位
	I2CStop();
	GIE	= 1;						//中断
	
	if(n != 0xff)
	{
		goto	reStart;
	}
	_FMWP	= 1;
	return	_TRUE;
}

//从EEPROM(MC24LC256)中读取一串数放入内存中
//////////////////////////////////////////
//	get string from external rom
//////////////////////////////////////////
unsigned char
getStrFM(bank2 unsigned char *dec, unsigned int EEPROMAddr, unsigned char n)
{
	//_EEPROMWP	= 1;					//禁止写入
	GIE	= 0;							//关闭中断
	I2CStart();

	if(_FALSE == I2CByteTX(0xA0))		//发送器件地址
										//24LC256的器件地址是0xA0(A0,A1,A2都为0的情况)
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	if(_FALSE == I2CByteTX((unsigned char)(EEPROMAddr/0x100)))	//发送逻辑地址,高字节
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	if(_FALSE == I2CByteTX((unsigned char)(EEPROMAddr)))		//发送逻辑地址,低字节
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	I2CStart();	

	if(_FALSE == I2CByteTX(0xA0 | 0b00000001))					//发送器件地址
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}
	
	while(n--)
	{
		ClrWdt();
		
		*dec++	= I2CByteRX();
		if(n != 0)
		{
			I2CACK();
		}
	}
	
	I2CNOACK();
	I2CStop();
	GIE	= 1;						//中断
	return	_TRUE;
}

unsigned char
getStrFMlow(unsigned char *dec, unsigned int EEPROMAddr, unsigned char n)
{
	//_EEPROMWP	= 1;					//禁止写入
	GIE	= 0;							//关闭中断
	I2CStart();

	if(_FALSE == I2CByteTX(0xA0))		//发送器件地址
										//24LC256的器件地址是0xA0(A0,A1,A2都为0的情况)
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	if(_FALSE == I2CByteTX((unsigned char)(EEPROMAddr/0x100)))	//发送逻辑地址,高字节
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	if(_FALSE == I2CByteTX((unsigned char)(EEPROMAddr)))		//发送逻辑地址,低字节
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}

	I2CStart();	

	if(_FALSE == I2CByteTX(0xA0 | 0b00000001))					//发送器件地址
	{
		GIE	= 1;							//中断
		return	_FALSE;
	}
	
	while(n--)
	{
		ClrWdt();
		
		*dec++	= I2CByteRX();
		if(n != 0)
		{
			I2CACK();
		}
	}
	
	I2CNOACK();
	I2CStop();
	GIE	= 1;							//中断
	return	_TRUE;
}
///////////////////////////////////////
//	对外部EEPROM的
//	I2C byte tx
//	要求入口SCL = 0
//	先发送高位	___
//	SCL__/  \__/...\_
//	程序出口SCL = 0
///////////////////////////////////////
unsigned char I2CByteTX(unsigned char byte)
{
	unsigned char loop;
	loop		= 8;
	
	_TRISFMSDA	= 0;
	
	while(loop--)
	{
		if(byte & 0b10000000)				//获取高位状态
		{
			_FMSDA	= 1;
		}
		else
		{
			_FMSDA	= 0;
		}
		
		I2CDelay();
		
		_FMSCL		= 1;
		
		I2CDelay();
		_FMSCL		= 0;
		byte		<<= 1;
		//I2CDelay();
	};
	
	//等待ACK
	_TRISFMSDA	= 1;				//输入态
	_FMSCL		= 1;
	I2CDelay();
	if(_FMSDA == 1)
	{
		_FMSCL	= 1;
		return	_FALSE;
	}
	_FMSCL	= 0;
	I2CDelay();
	return	_TRUE;
}

///////////////////////////////////////
//I2C byte rx
///////////////////////////////////////
unsigned char I2CByteRX(void)
{
	unsigned char byte;
	unsigned char loop;
	loop	= 8;
	_TRISFMSDA	= 1;
	
	do
	{
		byte	<<= 1;						//最低位被置零

		_FMSCL	= 1;
		I2CDelay();
		if(_FMSDA == 1)
		{
			byte	|= 0b00000001;
		}

		_FMSCL	= 0;
		I2CDelay();
		loop--;
	} while(loop > 0);

	return	byte;		
}
///////////////////////////////////////
//					   ______
// Send start bit	FMSDA >4us \_____
//					   ___________
//					SCL	      	  \__
///////////////////////////////////////
void I2CStart(void)
{
	_FMSCL			= 1;

	_FMSDA		= 1;				//先设电平,再设输入输出状态,
	_TRISFMSDA	= 0;

	I2CDelay();	
	_FMSDA		= 0;

	I2CDelay();
	_FMSCL			= 0;
	
	//I2CDelay();
}

///////////////////////////////////////
//I2C stop
//				____
//	FMSDA	_______/
//		____________
//	SCL	
///////////////////////////////////////
void I2CStop(void)
{
	_TRISFMSDA	= 0;

	_FMSDA		= 0;
	I2CDelay();
	_FMSCL			= 1;	
	I2CDelay();	
	//_FMSDA		= 1;
	_TRISFMSDA	= 1;
	I2CDelay();
	_TRISFMSDA	= 1;		//把FMSDA引脚置为输入态

}

///////////////////////////////////////
//////////byte acknowledge
// FMSDA _______
//		 __
// SCL _/  \_
///////////////////////////////////////
 void I2CACK(void)
{
	_TRISFMSDA	= 0;
	
	_FMSDA		= 0;
    I2CDelay();
	_FMSCL			= 1;
	I2CDelay();
	_FMSCL			= 0;
	
	I2CDelay();	
}

///////////////////////////////////////
// byte no acknowledge
//		______
// FMSDA 
//		 __
// SCL _/  \_
///////////////////////////////////////
 void I2CNOACK(void)
{
	_TRISFMSDA	= 0;
	
	_FMSDA		= 1;
	I2CDelay();
	_FMSCL		= 1;
	I2CDelay();
	_FMSCL		= 0;
	I2CDelay();	
}

/////////////delay 400k//////////
void I2CDelay(void)
{
	Nop();
	Nop();
	Nop();
	Nop();
}

/*************************************
*	时钟相关操作
*	时钟芯片 RX8025
*	地址有区别,在高四位(0~F)
*	因为8025两次操作之间不能小于500ms延时,所以特殊处理
*	软件时钟秒不为零,直接写入
*	为零主循环中判断后再写入
*	put string to RX8025
***************************************/
unsigned char
putStrRTC(unsigned char Addr, bank2 unsigned char *src, unsigned char n)
{
	v_IntRunFlag	= c_putStrRTC;
	safeCheck();

	v_ssCont		= 59;		//保证修改时钟,可以马上刷新时间参数
	
	GIE	= 0;					//关闭中断
	RTCStart();
	
	if(_FALSE == RTCByteTX(c_RTCSlaveAddr & 0b11111110))	//发送器件地址,bit0 = 0是写
	{
		GIE	= 1;				//使能中断
		return	_FALSE;
	}
	
	if(_FALSE == RTCByteTX(Addr<<4))						//发送逻辑地址
	{
		GIE	= 1;				//使能中断
		return	_FALSE;
	}
	
	//发送数据
	while(n--)
	{
		ClrWdt();
		
		if(_FALSE == RTCByteTX(*src++))
		{
			GIE	= 1;			//使能中断
			return _FALSE;
		}
	}
	
	//停止位
	RTCStop();
	GIE	= 1;					//使能中断
	return	_TRUE;
}
unsigned char
putStrRTClow(unsigned char Addr, unsigned char *src, unsigned char n)
{
	v_IntRunFlag	= c_putStrRTC;
	safeCheck();

	v_ssCont		= 59;		//保证修改时钟,可以马上刷新时间参数
	
	GIE	= 0;					//关闭中断
	RTCStart();
	
	if(_FALSE == RTCByteTX(c_RTCSlaveAddr & 0b11111110))	//发送器件地址,bit0 = 0是写
	{
		GIE	= 1;				//使能中断
		return	_FALSE;
	}
	
	if(_FALSE == RTCByteTX(Addr<<4))						//发送逻辑地址
	{
		GIE	= 1;				//使能中断
		return	_FALSE;
	}
	
	//发送数据
	while(n--)
	{
		ClrWdt();
		
		if(_FALSE == RTCByteTX(*src++))
		{
			GIE	= 1;			//使能中断
			return _FALSE;
		}
	}
	
	//停止位
	RTCStop();
	GIE	= 1;					//使能中断
	return	_TRUE;
}

///////////////////////////////////////
// 	get string from RX8025
//	固定读取模式,从0x0f开始,顺序读取
//	例如:地址0x01 的数据应该是第3个字节,第一个是0x0f,第二个是0x00
///////////////////////////////////////
unsigned char
getStrRTC(bank2 unsigned char *dec, unsigned char Addr, unsigned char n)
{
	unsigned char	len;								//计数扔掉几字节
	RTCStart();
	
	if(_FALSE == RTCByteTX(c_RTCSlaveAddr))				//发送器件地址,默认就是读取
	{
		return	_FALSE;
	}
	
	len		= Addr + 1;									//地址Addr前有Addr+1个无效字节
	while(len--)
	{
		RTCByteRX();									//只读不存
		RTCACK();
	}
	
	while(n--)
	{
		*dec++	= RTCByteRX();							//有效数据
		if(n!=0)
		{
			RTCACK();
		}
	}
	
	RTCNOACK();
	RTCStop();
	return	_TRUE;
}
unsigned char
getStrRTClow(unsigned char *dec, unsigned char Addr, unsigned char n)
{
	unsigned char	len;								//计数扔掉几字节
	RTCStart();
	
	if(_FALSE == RTCByteTX(c_RTCSlaveAddr))				//发送器件地址,默认就是读取
	{
		return	_FALSE;
	}
	
	len		= Addr + 1;									//地址Addr前有Addr+1个无效字节
	while(len--)
	{
		RTCByteRX();									//只读不存
		RTCACK();
	}
	
	while(n--)
	{
		*dec++	= RTCByteRX();							//有效数据
		if(n!=0)
		{
			RTCACK();
		}
	}
	
	RTCNOACK();
	RTCStop();
	return	_TRUE;
}
///////////////////////////////////////
//	I2C byte tx
//	要求入口SCL = 0
//	先发送高位	  __
//	SCL__/  \__/...\_
//	程序出口SCL = 0
///////////////////////////////////////
unsigned char RTCByteTX(unsigned char byte)
{
	unsigned char loop;
	loop		= 8;
	
	_RTCTRISSDA	= 0;
	_RTCTRISSCL	= 0;
	
	do
	{
		if(byte & 0b10000000)				//获取高位状态
		{
			_RTCFMSDA	= 1;
		}
		else
		{
			_RTCFMSDA	= 0;
		}
		
		I2CDelay();
		
		_RTCSCL		= 1;
		
		I2CDelay();
		_RTCSCL		= 0;
		byte		<<= 1;
	
		I2CDelay();
		loop--;
		
	} while(loop > 0);
	
	//等待ACK
	_RTCSCL		= 1;	
	_RTCTRISSDA	= 1;				//输入态
	I2CDelay();
	if(_RTCFMSDA == 1)
	{
		_RTCSCL	= 1;
		return	_FALSE;
	}
	_RTCSCL	= 0;
	I2CDelay();
	return	_TRUE;
}

/////////////////////////////////////
//I2C byte rx
/////////////////////////////////////
unsigned char RTCByteRX(void)
{
	unsigned char byte;
	unsigned char loop;
	loop	= 8;
	_RTCTRISSDA	= 1;
	_RTCTRISSCL	= 0;
	
	do
	{
		byte	<<= 1;
		
		I2CDelay();
		_RTCSCL	= 1;
		I2CDelay();
		if(_RTCFMSDA == 1)
		{
			byte	|= 0b00000001;
		}

		_RTCSCL	= 0;
		loop--;
	} while(loop > 0);
	
	I2CDelay();
	return	byte;		
}
///////////////////////////////////////
//					   	  ______
// Send start bit	RTCFMSDA >4us \_____
//					       ___________
//					RTCSCL	      	  \__
///////////////////////////////////////
void RTCStart(void)
{
	_RTCTRISSDA	= 0;
	_RTCTRISSCL	= 0;
	
	_RTCSCL		= 1;
	_RTCFMSDA		= 1;
	
	I2CDelay();
	
	_RTCFMSDA		= 0;
	
	I2CDelay();
	
	_RTCSCL		= 0;
	
	I2CDelay();
}

///////////////////////////////////////
//RTC stop
//	     			____
//	RTCFMSDA	_______/
//			____________
//	RTCSCL	
///////////////////////////////////////
void RTCStop(void)
{
	_RTCTRISSDA	= 0;
	_RTCTRISSCL	= 0;
	
	_RTCSCL		= 1;
	_RTCFMSDA		= 0;
		
	I2CDelay();
	_RTCFMSDA		= 1;
	I2CDelay();

	_RTCTRISSDA	= 1;	//把FMSDA引脚置为输入态

}

///////////////////////////////////////
//////////// byte acknowledge
// FMSDA _______
//		 __
// SCL _/  \_
///////////////////////////////////////
 void RTCACK(void)
{
	_RTCTRISSDA	= 0;
	_RTCTRISSCL	= 0;
	
	_RTCFMSDA		= 0;
	I2CDelay();
	_RTCSCL		= 1;
	I2CDelay();
	_RTCSCL		= 0;
	I2CDelay();	
}
///////////////////////////////////////
//////////byte acknowledge
// FMSDA _______
//		 __
// SCL _/  \_
///////////////////////////////////////
 void RTCNOACK(void)
{
	_RTCTRISSDA	= 0;
	_RTCTRISSCL	= 0;
	
	_RTCFMSDA		= 1;
	I2CDelay();
	_RTCSCL		= 1;
	I2CDelay();
	_RTCSCL		= 0;
	I2CDelay();	
}



⌨️ 快捷键说明

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