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

📄 inout.c

📁 电力载波抄表系统里的电力载波采集器,采集数据再通过RS485向主站发送.
💻 C
📖 第 1 页 / 共 2 页
字号:
// general input/output dispose

//中断实现载波红外接收
void interrupt isr(void)
{
	static bank1 unsigned char byte, loop, CS;
	static bank1 unsigned char frameCS;
	
	if((TMR1IE) && (TMR1IF))
	{
		TMR1H	+= c_10MsTimeH;				//timer1每10ms中断一次
		TMR1IF	= 0;
		v_msCont++;							//系统定时
		Buff485Mark.otc++;					//485接收超时
		BuffPLCMark.otc++;
	}

	if((RBIE) && (RBIF))
	{
		//RB电平变化中断
		if(_RXD == 0)						//先判断载波
		{
			T2CON		= c_T2con9600;		//默认载波接收
			v_RecPort	= c_Port_Plc;		//标志接收端口
			
			//载波接收
		
			TMR2	= c_SimBaud*3/4;		//延时1/4 bit开始采样
			TMR2IF	= 0;
			TMR2ON	= 1;					//开始计时				
			
			while(TMR2IF == 0)
			{}								//等待时间到达
			TMR2IF	= 0;

			if(_RXD == 1)					//再次判断起始位
			{
				NOP();
				goto	IntErr;				//接收错误
			}
			//开始接收数据
			loop	= 8;
			CS		= 0;					//用于计算校验位
			while(loop--)
			{
				byte	>>= 1;				
				while(TMR2IF == 0)
				{}							//等待时间到达
				TMR2IF	= 0;
				
				if(_RXD == 1)
				{
					byte	|= 0b10000000;	//置1
					CS++;
				}
			}
			
			//校验位检测
			while(TMR2IF == 0)
			{}								//延时1bit
			TMR2IF	= 0;
							_PLCRXD	= 0;
				_PLCRXD	= 1;
			if(_RXD == 1)
			{
				if((CS & 0b00000001) != 1)
				{
					goto	IntErr;
				}
			}
			else
			{
				if((CS & 0b00000001) != 0)
				goto	IntErr;
			}

			//判断停止位
//			while(TMR2IF == 0)
//			{}								//延时1bit
//			TMR2IF	= 0;
//			if(_RXD == 1)
//			{
				goto IntDataSave;
//			}
//			else
//			{
//				goto IntErr;
//			}
		}
		else if(_IrfTXD == 0)
		{
			if((BuffPLCMark.Sta != c_Free) && (v_RecPort == c_Port_Plc))
			{
				goto	IntReturn;
			}
			
			T2CON		= c_T2con1200;		//红外接收波特率
			v_RecPort	= c_Port_Irf;		//标志接收端口
			
			//红外接收
			TMR2	= c_SimBaud*3/4;		//延时1/4 bit开始采样
			TMR2IF	= 0;			
			TMR2ON	= 1;					//开始计时
			
			while(TMR2IF == 0)
			{}								//等待时间到达
			TMR2IF	= 0;
			
			if(_IrfTXD == 1)				//再次判断起始位
			{
				goto	IntErr;				//接收错误
			}
			//开始接收数据
			loop	= 8;
			CS		= 0;					//用于计算校验位
			while(loop--)
			{
				byte	>>= 1;				
				while(TMR2IF == 0)
				{}							//等待时间到达
				TMR2IF	= 0;
				if(_IrfTXD == 1)
				{
					byte	|= 0b10000000;	//置1
					CS++;
				}
			}
			
			//校验位检测
			while(TMR2IF == 0)
			{}								//延时1bit
			TMR2IF	= 0;
			
			if(_IrfTXD == 1)
			{
				if((CS & 0b00000001) != 1)
				{
					goto	IntErr;
				}
			}
			else
			{
				if((CS & 0b00000001) != 0)
				goto	IntErr;
			}

			//判断停止位
			while(TMR2IF == 0)
			{}								//延时1bit
			TMR2IF	= 0;
			if(_IrfTXD == 1)
			{
				goto IntDataSave;
			}
			else
			{
				goto IntErr;
			}
		}
		else
		{
			goto	IntReturn;
		}
		
		//数据放入缓冲区
IntDataSave:
		if(BuffPLCMark.Sta == c_Free)
		{
			if(byte != 0x68)
			{
				goto	IntErr;				//扔掉无效字符
			}
		}
		
		if(BuffPLCMark.ptr>=(BuffPLC+c_BuffMax))//防止溢出
		{
			goto IntErr;
		}
		
		BuffPLCMark.otc	= 0;				//用于判断字节间超时
		*BuffPLCMark.ptr++ 	=	byte;		//保存数据
		BuffPLCMark.len++;					//数据长度+1
		BuffPLCMark.Sta		= c_RecNow;		//接收状态
		
		if(BuffPLCMark.len < c_OffsetL+1)
		{
			goto	IntReturn;				//正常返回
		}
		
		if(BuffPLCMark.len == c_OffsetL+1)
		{
			if(0x68 == BuffPLC[c_Offset68_2])
			{
				v_PLClen	= byte + 2;		//645数据长度
				goto	IntReturn;
			}
			goto		IntErr;
		}
		else
		{
			//数据域按长度接收
			if(--v_PLClen == 0)
			{
				BuffPLCMark.Sta	= c_RecEnd;
				frameCS			= 0;
			}
			goto	IntReturn;
		}
IntErr:
	BuffPLCMark.len	= 0;
	BuffPLCMark.ptr	= BuffPLC;
	BuffPLCMark.Sta	= c_Free;
	frameCS			= 0;
	_Show485	= 0;
	
IntReturn:
	asm("movf	_PORTB, w");		//清除标志位
	asm("movf	_PORTB, w");		//清除标志位
	RBIF	= 0;	
	}
}
//485缓冲区检测
void Buff485Rec(void)
{
	unsigned char byte;
	static unsigned char frame485CS;
	
	if(Buff485Mark.Sta == c_Send)		//正在发送退出
	{
		return;
	}
	
	if(OERR)				//错误检测
	{
		CREN	= 0;
		CREN	= 1;
		asm("movf _RCREG, w");
		asm("movf _RCREG, w");
	}
	
	if(RCIF == 0)	return;				//没有接收
	
//	_Show485		= 1;				//数据指示灯
	byte			= RCREG;
	
	if(Buff485Mark.Sta == c_WaitRec)
	{
		if(byte != 0x68)
		{
			frame485CS		= 0;
			Buff485Mark.ptr	= Buff485;
			Buff485Mark.len	= 0;
			
//			_Show485		= 0;
			return;						//扔掉无效字符
		}
	}

	if(Buff485Mark.ptr>=(Buff485+c_BuffMax-6))	//防止溢出
	{
		goto Buff485RecErr;
	}
	
	Buff485Mark.otc	= 0;				//用于判断字节间延时
	Buff485Mark.Sta		= c_RecNow;
	*Buff485Mark.ptr++	= byte;
	frame485CS			+= byte;
	Buff485Mark.len++;
	
	if(Buff485Mark.len < c_OffsetL+1)
	{
		goto	Buff485RecEnd;			//正常返回
	}
	
	else if((0x68 != Buff485[0]) || (0x68 != Buff485[c_Offset68_2]))
	{
		goto	Buff485RecErr;
	}
	
	if(Buff485Mark.len == c_OffsetL+1)
	{
		v_485len	= byte + 2;				//645数据长度
	}
	else
	{
		//数据域按长度接收
		if(0 == --v_485len)
		{
			Buff485Mark.Sta	= c_RecEnd;
			_Show485	= 0;
		}
	}
	
Buff485RecEnd:
	//
	return;
		
Buff485RecErr:
	Buff485Mark.ptr	= Buff485;
	Buff485Mark.Sta	= c_Free;
	frame485CS		= 0;
	highmemset(Buff485, 0x00, c_BuffMax);
	Delay1msx(300u);						//异常延时300ms后再通信
}

//载波数据发送
void BuffPLCSend(void)
{
	if(BuffPLCMark.Sta == c_Send)
	{
		if(v_RecPort == c_Port_Plc)
		{
			putCharPLC(*BuffPLCMark.ptr);
		}
		else if(v_RecPort == c_Port_Irf)
		{
			putCharIrf(*BuffPLCMark.ptr);
		}
		BuffPLCMark.ptr++;
		if(--BuffPLCMark.len == 0)
		{
			BuffPLCMark.Sta	= c_Free;
			BuffPLCMark.ptr		= BuffPLC;
		}	
	}
}

//485数据发送
void Buff485Send(void)
{
	if(TRMT == 0) return;	//上一字节没有发送完,退出
	
	if(Buff485Mark.Sta == c_Send)
	{
//		_Show485		= 1;			//485通信指示

		TXSTA	= c_TXsta;				//设置485通信参数
		RCSTA	= c_RCsta;
		if(_frame_07 == v_frame_mark)
		{
			SPBRG = c_Baud_2400;
		}
		else
		{
			SPBRG = c_Baud_1200;
		}
		
		//处理前导符fe
		if(Buff485Mark.feCont!= 0)
		{
			if(Buff485Mark.feCont > 2)	//判断防止过大
			{
				Buff485Mark.feCont = 2;	//默认2
			}
			//发送fe
			TX9D		= 1;			//偶校验位1
			TXREG		= 0xfe;			//发送fe
			Buff485Mark.feCont--;
			return;
		}

		//处理645帧
		if(EvenParity(*Buff485Mark.ptr))//计算偶校验位
		{
			TX9D	= 1;
		}
		else
		{
			TX9D	= 0;
		}
		
		TXREG	= *Buff485Mark.ptr;
		Buff485Mark.ptr++;
		Buff485Mark.otc	= 0;		
		
		if(--Buff485Mark.len == 0)
		{
			Buff485Mark.Sta	= c_WaitRec;	//等待接收
			Buff485Mark.ptr	= Buff485;
			CREN			= 0;
			CREN			= 1;
			asm("movf _RCREG, w");
			asm("movf _RCREG, w");
		}

//		_Show485		= 0;					//485通信指示
	}
}

//////////////////////////////////////////
////put one byte to PLC
////intput		byte
//////////////////////////////////////////
void putCharPLC(unsigned char byte)
{
	unsigned char 	loop	= 8;
	unsigned char	ver 	= 0;
	
	GIE	= 0;						//关闭中断
	_Show485		= 1;			//通信指示
	
	T2CON	= c_T2con9600;			//设置发送波特率

	TMR2	= 0;					//延时1bit开始发送
	TMR2IF	= 0;			
	TMR2ON	= 1;					//开始计时

	while(TMR2IF == 0)
	{;}								//等待时间到达
	TMR2IF	= 0;

	//start	bit
	_PLCRXD	= 0;					//起始位
	while(TMR2IF == 0)
	{;}								//等待时间到达
	TMR2IF	= 0;	
	
	//data bit
	while(loop--)
	{
		if(byte & 0b00000001)
		{
			_PLCRXD	= 1;
			ver++;					//校验
		}
		else
		{
			_PLCRXD	= 0;
		}
		while(TMR2IF == 0)
		{;}							//等待时间到达
		TMR2IF	= 0;
		byte	>>= 1;				//数据右移
	}
	
	//parity bit
	if(ver & 0b00000001)
	{
		_PLCRXD	= 1;
	}
	else
	{
		_PLCRXD	= 0;
	}
	while(TMR2IF == 0)
	{}								//等待时间到达
	TMR2IF	= 0;


	_Show485		= 0;			//通信指示
	GIE	= 1;						//打开中断
	
	//tail bit
	_PLCRXD	= 1;
	
	while(TMR2IF == 0)
	{;}								//等待时间到达
	TMR2IF	= 0;
}
//////////////////////////////////////////
////put one byte to infrared
////intput		byte
//////////////////////////////////////////
void putCharIrf(unsigned char byte)
{
	unsigned char 	loop	= 8;
	unsigned char	ver 	= 0;
	
	GIE	= 0;						//关闭中断	
	T2CON	= 	c_T2con38kHz;		//enable timer2
	CCP1CON	= 0x0f & c_CCP1con;		//enable PWM out
	
	Delay1200bit();

	//start	bit
	_IrfRXD	= 0;					//起始位
	
	Delay1200bit();					//等待时间到达
	
	//data bit
	while(loop--)
	{
		if(byte & 0b00000001)
		{
			_IrfRXD	= 1;
			ver++;					//校验
		}
		else
		{
			_IrfRXD	= 0;
		}
		Delay1200bit();
		byte	>>= 1;				//数据右移
	}
	
	//parity bit
	if(ver & 0b00000001)
	{
		_IrfRXD	= 1;
	}
	else
	{
		_IrfRXD	= 0;
	}
	Delay1200bit();
	
	//tail bit
	_IrfRXD	= 1;

	asm("movf	_PORTB, w");		//清除标志位
	asm("movf	_PORTB, w");		//清除标志位
	RBIF	= 0;	
	
	
	GIE		= 1;					//打开中断
	
	Delay1200bit();

	CCP1CON	= 0xf0 & c_CCP1con;		//close PWM out

}
//把内存中的一串数写入EEPROM(MC24LC256)
//////////////////////////////////////////
//	put string to external EEPROM
//////////////////////////////////////////
unsigned char
putStrFM(unsigned int EEPROMAddr, bank2 unsigned char *src, unsigned char n)
{
	unsigned char	w_wait;
	v_IntRunFlag	= c_putStrFM;
	safeCheck();
	

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

unsigned char
putStrFMlow(unsigned int EEPROMAddr, unsigned char *src, unsigned char n)		//n不能大于64
{
	unsigned char w_wait;

	v_IntRunFlag	= c_putStrFM;
	safeCheck();
	
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)(EEPROMAddr/0x100)))	//发送逻辑地址,高字节
	{
		_FMWP	= 1;
		GIE	= 1;							//中断
		return	_FALSE;
	}
	if(_FALSE == I2CByteTX((unsigned char)(EEPROMAddr)))	//发送逻辑地址,低字节
	{
		_FMWP	= 1;
		GIE	= 1;							//中断
		return	_FALSE;
	}
	
	//发送数据
	while(n--)
	{
		ClrWdt();
		
		if(_FALSE == I2CByteTX(*src++))
		{
			_FMWP	= 1;
			GIE	= 1;							//中断
			return _FALSE;
		}
		
		EEPROMAddr++;					//地址标志+1,判断是否跨越边界
		if((EEPROMAddr%c_eepage) == 0)
		{
			break;						//结束本次写入循环,跨页处理
		}
	}
	
	//停止位
	I2CStop();
	GIE	= 1;						//中断

	if(n != 0xff)
	{
		goto	reStart;
	}
	_FMWP	= 1;
	return	_TRUE;
}
//////////////////////////////////////////
//	外部存储器,一定区域写入相同数据
//////////////////////////////////////////
unsigned char
FMSet(unsigned int EEPROMAddr, unsigned char data, unsigned char n)

⌨️ 快捷键说明

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