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

📄 or100.c

📁 用STC单片机实现光发射机的自动增益控制
💻 C
字号:

/*************************************************************************
 * Vers	     Date		              Changes
 * ----	  ----------   ---------------------------------------------------*
 * v1.0   2008-10-19              main.c 主程序及入口
 * ************************************************************************/

//#define DEBUG



//#include <STC12C5410.H>
#include <myheadfile.h>
//#include <math.h>


//常数定义



//**************** 全局变量,以'_G'为后缀 *******************
unsigned char idata netlayer_buff_G[BUFF_MAX_LENTH];		//既做下行网络层接收BUFFER,又做擦写EEPROM时的BUFFER
unsigned char seriers_flag_G;			//在串口中断中设置,只有在接收到正确的MAC包后才设置为有效ON,否则设为ERROR或OFF
unsigned char sample_data_G[CHANEL_SUM];	//平均后的采样值,输入光功率1 = AD[0];输入光功率1 = AD[1]

struct {		//变量区,共21字节,详见《单向光接收机数据结构》
	unsigned int work_statue;	//当前工作状态
	unsigned char else_preset;	//其它设置
	unsigned char else_statue;	//其它状态
	
	float temperature;		//设备温度
	float optical_power1;		//第1路接收光功率
	float optical_power2;
	float level_rf1;			//第1路RF输出电平
	char attenuation1;			//第1路输出衰减量
	float level_rf2;
	char attenuation2;
	float level_rf3;
	char attenuation3;
	float level_rf4;
	char attenuation4;
	
	float p24v_supply1;
	float p5v_supply1;
	float n5v_supply1;
	float p3v_supply1;
	float p24v_supply2;
	float p5v_supply2;
	float n5v_supply2;
	float p3v_supply2;

	} value_G;


//****************************************************


extern void   Initital(void);			//初始化
extern unsigned char Adc8Filt(unsigned char, unsigned char);	//ADC和平均
//extern unsigned char Safeguard(unsigned char);
extern unsigned char Check8Alarm(float,float);

extern unsigned char RdConst8Value(void);
extern unsigned char RdSet(void);
extern unsigned char WriteValue(void);
extern unsigned char ResetDefault(void);
extern void AckIllegal(unsigned char);
extern void AckWrCom(unsigned char);
extern float ByteReversal(float);
//extern unsigned char Rd_DS1820(void);
extern unsigned char GetTemperature(unsigned char);

extern unsigned char code ReserveValue[];


signed char OpticalPowerDetect(unsigned char);
unsigned char OpPowDetect_mW(unsigned char);
void OpticalAgc(signed char);
void Display(signed char);
unsigned char RfLevel(unsigned char);

/*************************************************************************/
/*任务定义:main()                                                       */
/*功能描述: 入口,主循环                                                */
/*    主循环任务                                                         */
/*************************************************************************/

main()
{

//union { float flt; unsigned char bytes[4]; } float2byte ;
unsigned char i,count;
unsigned char temp,tempeX2_avr;		//平均后的温度(未对从DS1820采样值做除2处理)
//union{ unsigned char tempeX2[2]; unsigned int union2tempe; } tempe_un;
signed char temp_s;

	Initital();
		seriers_flag_G = 0x0;		//未收到任何下传的数据包

		value_G.work_statue = 0x0000;//当前状态
		value_G.else_statue = 0x00;	//其它状态
		value_G.else_preset = 0x00;	//其它设置

//-------------------以下为未实现的参数的处理,为固定值-------------------------		
		value_G.optical_power2 = 0.0;	//第2路输入光功率(mW)为最低
/*		float2byte.bytes[3] = ReserveValue[0];	//RF输出电平是保留值
		float2byte.bytes[2] = ReserveValue[1];	//存在保留量里的数据没有倒序,所以这里要倒序
		float2byte.bytes[1] = ReserveValue[2];
		float2byte.bytes[0] = ReserveValue[3];
		value_G.level_rf1 = float2byte.flt;		//包括位倒序,
		value_G.level_rf2 = value_G.level_rf1; */
		value_G.level_rf3 = 0.0;		//本光接收机是两路输出的,所以3、4路为0
		value_G.level_rf4 = 0.0;
		value_G.attenuation1 = ReserveValue[4];	//RF输出衰减是保留值
		value_G.attenuation2 = value_G.attenuation1;
		value_G.attenuation3 = 0.0;
		value_G.attenuation4 = 0.0;
		value_G.p3v_supply1 = 0.0;		//ByteReversal(3.3);
		value_G.p3v_supply2 = value_G.p3v_supply1;
		value_G.n5v_supply1 = 0.0;
		value_G.n5v_supply2 = value_G.n5v_supply1;
		value_G.p5v_supply2 = 0.0;
		value_G.p24v_supply2 = 0.0;
		
		
//--------------------------------------------

	while(1)
	{
// measure execute clock of below code
  		for(i = 0; i < CHANEL_SUM; i++)  sample_data_G[i] = Adc8Filt(sample_data_G[i], i);		//ADC并平均
  		////8个采样通道,+24V电源=AD[0],温度=AD[1];P2口电平=AD[2],P1口电平=AD[3],+5V电源=AD[4];空=AD[5],AD[6];第1路输入光功率=AD[7],
			/* ----以浮点格式存贮到变量区中---- */
		value_G.p5v_supply1 = ByteReversal(sample_data_G[4]*0.0391);
		value_G.p24v_supply1 = ByteReversal(sample_data_G[0]*0.1172);


		temp = RfLevel(sample_data_G[3]);
		value_G.level_rf1 = ByteReversal(temp*1.0);
		temp = RfLevel(sample_data_G[2]);
		value_G.level_rf2 = ByteReversal(temp*1.0);

		temp_s = OpticalPowerDetect(sample_data_G[7]);	//输入光功率(dBm)
		Display(temp_s);
		OpticalAgc(temp_s);
		if(temp_s<-80)
		{
			value_G.work_statue = value_G.work_statue | 0x4;	//如果输入光功率小于-8dBm则认为不正常
			value_G.optical_power1 = 0.0;
		}
		else
		{
			value_G.work_statue = value_G.work_statue & (~0x4);		//输入光功率正常
			temp = OpPowDetect_mW(sample_data_G[7]);		//计算输入光功率mW
			value_G.optical_power1 = ByteReversal(temp/10.0);
		}
	//-----------------------------------------------------
		count = count+1;
		if(count==0)		//每采样一次温度最大要750ms,所以以下代码不必每次都执行
		{
			temp = GetTemperature(sample_data_G[1]);//Rd_DS1820();
			if(temp>10 && temp<99)
			{
				tempeX2_avr = (tempeX2_avr + temp)/2;		//从DS1820中读取温度,平均
				value_G.temperature = ByteReversal(tempeX2_avr*1.0);
			}
			
		}
	//---------------------------------------------------
		
		if(COVER_DETECT)  value_G.work_statue = value_G.work_statue | 0x2;		//开盖状态检测
		else value_G.work_statue = value_G.work_statue & (~0x2);
//			value_G.else_status = Status();					//除采样值以外的其它工作状态(比如某些开关量)的检查更新
// measure execute clock of upward code




/**************************************************************************/
		if(seriers_flag_G!=OK && seriers_flag_G!=0x00)		//如果超时或者校验错
		{
			AckIllegal(seriers_flag_G);		//上传MAC层错误的响应
			seriers_flag_G=0x00;
		}
		
		if(seriers_flag_G==OK)    //如果上位机发来了给自己的有效指令,MAC层已经在串口中断中剥去,netlayer_buff_G只剩下网络层
		{
/*下行网络层包结构:command+offset+lenth+(write_data) */

			seriers_flag_G=0x00;
			switch(netlayer_buff_G[0])		// command
			{
				case 0x01: //读常量
				case 0x02: //读变量
					i = RdConst8Value();
					if(i==FAULS) AckIllegal(0x14);         //上传网络层超界错误的响应
					break;
				case 0x03:	//写变量
					i = WriteValue();
					AckWrCom(i);
					break;
				case 0x04: //读控制量
					i = RdSet();
					if(i==FAULS) AckIllegal(0x14);         //上传网络层超界错误的响应
					break;					
				case 0x05: //写控制量
					if(netlayer_buff_G[1]==0x0&&netlayer_buff_G[3]==0x55)
					{
						i = ResetDefault();		//恢复出厂默认设置
						AckWrCom(i);
					}
					else
					{						//对"其它设置"、“输出RF衰减”等的写
						i = RIGHT;			//目前预留,直接返回正确
						AckWrCom(i);
					}

					break;
				default:    AckIllegal(0x11);         //非法指令则上传网络层错误的响应
			}

		}
	}
}





/*************************************************************************/
/*任务定义:串口中断                                                       */
/*输入:无                               */
/*输出:seriers_flag_G, OK:收到正确MAC层数据, 0x1:错误A5, 0x2:校验错误, 0x4:其它MAC错误  */
/*算法:*/
/* 接收包结构为:同步(1byte)+MAC地址(1byte)+长度(1byte)+净负荷(n byte)+校验(1byte) */
//返回:netlayer_buff_G中存有网络层的数据,seriers_flag_G:=0表示没有接收到数据,=OK表示接收到MAC层正确的数据,其它:MAC层错误
/*************************************************************************/

void SER_int() interrupt 4 using 2
{
	static unsigned char state_mathine = 0x0;
	static unsigned char check_sum = 0x0, lenth_MAC = 0x0, index = 0x0, flagA5_bit = 0;
	
	unsigned char recv_data;
	unsigned char temp;

	if (RI)
	{
		RI = 0;	
		recv_data = SBUF;

		if(TF0==1)					//如果这时定时器已经溢出,则说明已经超时,强行进入初始状态
		{
			TF0=0;
			TH0 = TIMER0_OV;
			state_mathine = 0x0;					//错误并返回到初始状态
		}

		switch(state_mathine)
		{
			case 0x0:				//起始接收,初始状态
				if(recv_data == 0xA5)
				{
					state_mathine = 0x1;
					check_sum = 0x0;
					flagA5_bit = 0;
					seriers_flag_G = 0x0;
					index = 0x0;
					TH0 = TIMER0_OV;
					TR0 = 1;				// 启动超时计数器
				}							// 否则什么也不做,仍然保持在等待接收同步头状态
				break;
			
			case 0x1:				//已经收到同步头,MAC地址比较
				TH0 = TIMER0_OV;					// 重置超时计数器
				if(recv_data != 0xA5)		//如果不再是0xA5,表示真正有效数据开始,接收的是MAC地址
				{
					temp = SELF_MAC_ADDR ;		//获取本机MAC地址
					if(recv_data == temp)			//如果地址相符
					{
						state_mathine = 0x2;
						check_sum += recv_data;			//累加校验和
//						flagA5_bit = 0;
//						seriers_flag_G = 0x0;
//						index = 0x0;
					}
					else
					{
						state_mathine = 0x0;			//地址不符,不是呼叫本机,回到初始状态
//						check_sum = 0;
//						flagA5_bit = 0;
						seriers_flag_G = 0x0;
//						index = 0x0;
						TR0 = 0;
					}
				}							// 如果还是0xA5则什么也不做,仍然保持在等待接收有效数据状态
				break;

			case 0x2:				//地址符合后,取长度
				TH0 = TIMER0_OV;									// 重置超时计数器
											// 长度不可能是A5,所以不用做A5判别,即使是A5,也会在长度是否超长判别时剔除
				if(recv_data > BUFF_MAX_LENTH)			//如果长度超过缓冲区的长度
				{
					state_mathine = 0x0;				//错误并返回到初始状态
					check_sum = 0;
					flagA5_bit = 0;
					seriers_flag_G = 0x3;				//超长错误
					index = 0x0;
					TR0 = 0;
				}
				else
				{
					state_mathine = 0x3;
					check_sum += recv_data;				//累加校验和
					flagA5_bit = 0;						//清标记
					seriers_flag_G = 0x0;
					index = 0x0;
					lenth_MAC = recv_data;				//获取长度
				}
				break;
				
			case 0x3:				//取出长度后,按长度取网络层数据
				TH0 = TIMER0_OV;									// 重置超时计数器
				if(flagA5_bit == 1 && recv_data != 0xA5)	//如果之前收到的是A5而且新收到的不是A5
				{
					state_mathine = 0x0;					//错误并返回到初始状态
					check_sum = 0;
					flagA5_bit = 0;
					seriers_flag_G = 0x1;						//A5错误
					index = 0x0;
					TR0 = 0;
				}
								
				else if(flagA5_bit==0 && recv_data == 0xA5)	//如果收到A5而且是第一个A5
						flagA5_bit = 1;						//设标记,仍然保持当前的状态,准备接收下一个A5
				else		//其它情况(收到A5而且是第二个A5,或者根本不是A5)
				{
					check_sum += recv_data;				//累加校验和
					flagA5_bit = 0;						//清标记
					seriers_flag_G = 0x0;
					netlayer_buff_G[index] = recv_data;				//获取数据
					index++;
					state_mathine = (index == lenth_MAC) ? 0x4 : 0x3;	//如果没取完网络层数据则仍然保持目前状态
				}
				break;
				
			case 0x4:				//取完网络层数据后,比较校验和
				TH0 = TIMER0_OV;									// 重置超时计数器
				if(flagA5_bit == 1 && recv_data != 0xA5)	//如果之前收到的是A5而且新收到的不是A5
				{
					state_mathine = 0x0;					//错误并返回到初始状态
					check_sum = 0;
					flagA5_bit = 0;
					seriers_flag_G = 0x1;						//A5错误
					index = 0x0;
					TR0 = 0;
				}
								
				else if(flagA5_bit==0 && recv_data == 0xA5)	//如果收到A5而且是第一个A5
						flagA5_bit = 1;						//设标记,仍然保持当前的状态,准备接收下一个A5
				else									//其它情况(收到A5而且是第二个A5,或者根本不是A5)
				{
					state_mathine = 0x0;
					flagA5_bit = 0;						//清标记
					recv_data = -recv_data;				//获取校验和
#ifdef DEBUG
					seriers_flag_G = OK;
#else
					seriers_flag_G = (check_sum == recv_data) ? OK : 0x02;	//校验错误
#endif
					check_sum = 0;
					index = 0;
					TR0 = 0;
				}
				break;
				
			default :				//其它情况
				state_mathine = 0x0;					//错误并返回到初始状态
				check_sum = 0;
				flagA5_bit = 0;
				seriers_flag_G = 0x4;						//其它错误
				index = 0x0;
				TR0 = 0;
				break;
		
		}
	}

}

⌨️ 快捷键说明

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