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

📄 drive.c

📁 使用51单片机开发的一个集团电话系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************
name:Drive.h
author:RPJ
version:V0.1
description:
单独的外部扫描和驱动模块
***************************/
#include "reg52.h"
#include "absacc.h"
#include "clock.h"
#include "define.h"

#include "drive.h"

#define GLOBALS
#include "variable.h"





/*******************************
name:Micro_Switch_8816(unchar Ext_No,unchar Channel_X,unchar Open)
input:Ext_No,Channel_X,Open
output:none
description:
通过合并用户号,绳路号和开关状态,向8816写入控制数据
绳路号是3456位
用户号是012位
控制状态是7位
开关选通有时间,注意停留
******************************/
void Micro_Switch_8816(unchar Ext_No,unchar Channel_X,unchar Open)
{
unchar data Group,Param;

	Group = Ext_No/8;
	Param = Ext_No%8;
	Param &= 0x0f;
	Channel_X &= 0x0f;
	Channel_X <<= 3;
	Param |=Channel_X;
	if(Open)
	{
		Param |=0x80;
	}
	XBYTE[(Addr_8816_Data)] = Param;
	switch(Group)
	{
		case 0:
			Control_8816A = 0;
			Control_8816B = 0;
			SelecEN_8816 = 0;
			break;
		case 1:
			Control_8816A = 1;
			Control_8816B = 0;
			SelecEN_8816 = 0;			
			break;
		case 2:
			Control_8816A = 0;
			Control_8816B = 1;
			SelecEN_8816 = 0;			
			break;
		case 3:
			Control_8816A = 1;
			Control_8816B = 1;
			SelecEN_8816 = 0;			
			break;
		default:
			break;
	}
	SelecEN_8816 = 1;
}
/*************************************
name: init_8816_ext
*************************************/
void Init_8816(void)
{
unchar data i,j;

	SelecEN_8816 = 1;
	for(i=0;i<32;i++)
	{
		for(j=0;j<16;j++)
		{
			Micro_Switch_8816(i,j,0);
		}
	}
}
/*************************************
name: init_ext_port
*************************************/
void Init_RC_Port(void)
{
unchar data i;

	for(i=0;i<4;i++)
	{
		Ext_Group[i].SCN = 0xff;		//默认初始化都是挂机
		Ext_Group[i].LL = 0xff;			//默认初始化都是挂机
		Ext_Group[i].AP = 0;
		Ext_Group[i].LAP = 0;
		Ext_Group[i].DTMF_ST = 0;
		Ext_Group[i].DTMF_Data[0] = 0;
		Ext_Group[i].DTMF_Data[1] = 0;
		Ext_Group[i].DTMF_Data[2] = 0;
		Ext_Group[i].DTMF_Data[3] = 0;
		Ext_Group[i].Ext_Ring_ST = 0;
		XBYTE[(Addr_EXT_Drive+i*Addr_Offset)] = Ext_Group[i].Ext_Ring_ST;
	}
	
}

/***************************************
subroutine name: Micro_Scan_8870(void)
input variable:       group
output variable:    /
description:           scan 8870 decoder.
查询8870的解码状态,如果持续是1就等待,继续查询
如果8870前次是1,本次是0,表示有一个解码完成
就读取数据再分析(数据已经定时读出了)
注意:由于是模拟交换,存在拨号的号码串号的情况,
特别是在用户听拨号音等待拨号时候,所以听拨号音的
用户同时褡裢在一起的,每个收号器都能受到其中一个
拨号,为了有效防止串号的出现,使用了一定的处理方式。
***************************************/
void Micro_Scan_8870(void)
{
unchar data Ext_No,temp,INT_ST;
unchar data i,point;

/****************DECODER ST***************/
	point = SLEC_Point;
	INT_ST = Ext_Group[point].DTMF_ST;
/*****************************************/
	//if(INT_ST)
		//INT_ST = 0;
	for(i=0;i<4;i++)
	{
		Ext_Group[point].DTMF_Data[i] = XBYTE[(Addr_DTMF_Data+i*Addr_Offset)];
	}
			
	for(i=0;i<8;i++)
	{
		Read_8870ST();
		Ext_No = i*4+point;
		if( Ext_No >= TAL_EXT_PORT )
		{
			break;
		}
		if( (Ext_Param[Ext_No].RecDTMF_En & 0xf0) == 0 )
		{
			Ext_Param[Ext_No].RecDTMF_En = 0;
			INT_ST>>=1;
			continue;
		}
		if(  INT_ST&0x01 )
		{
			if(Ext_Param[Ext_No].Ext_State == state1_DailNo )
			{//如果当前用户是听拨号音,需要立即关闭
				Micro_Switch_8816(Ext_No,BUSY_Channel, 0);
				Ext_Timer[Ext_No].Counter_Pause++;
				if( Ext_Timer[Ext_No].Counter_Pause <= 1 )
				{
					INT_ST>>=1;
					continue;
				}
			}
			
			Ext_Param[Ext_No].RecDTMF_En &= 0xf0;
			Ext_Param[Ext_No].RecDTMF_En |= MT8870_EnOut;//have tone input when decorder finish
				
			if( i%2 )
			{	
				temp = Ext_Group[point].DTMF_Data[i/2] & 0xf0;
				temp >>= 4;					
				Ext_Param[Ext_No].RecDTMF_Data = Exchang_CIDData(temp);
			}
			else
			{
				temp = Ext_Group[point].DTMF_Data[i/2] & 0x0f;
				Ext_Param[Ext_No].RecDTMF_Data = Exchang_CIDData(temp);
			}
		}
		else
		{
			if( Ext_Timer[Ext_No].Counter_Pause <= 1 )
			{
				if(Ext_Param[Ext_No].Ext_State == state1_DailNo )
				{//如果当前用户是听拨号音,但是只收到一个号码,需要重新开启拨号音
					Micro_Switch_8816(Ext_No,BUSY_Channel, 1);
					Ext_Timer[Ext_No].Counter_Pause = 0;
					INT_ST>>=1;
					continue;
				}
			}
			Ext_Timer[Ext_No].Counter_Pause = 0;
			
			if( (Ext_Param[Ext_No].RecDTMF_En & 0x0f) == MT8870_EnOut)
			{
				Ext_Param[Ext_No].RecDTMF_En &= 0xf0;
				Ext_Param[Ext_No].RecDTMF_En |= MT8870_NoOut;//no tone input when decorder finish
				Ext_Param[Ext_No].Ext_EVENT = event3_ExtRecDtmf;
				Ext_Param[Ext_No].Ext_RecDtmf_List[Ext_Timer[Ext_No].Counter_Rec_DTMF++] = Ext_Param[Ext_No].RecDTMF_Data;
				MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No, 
					WP_EVENT, TAL_EVENT, BufSize);
				//用户进入收到DTMF信号事件		
			}
		}	
		INT_ST>>=1;
	}

	Ext_Group[point].DTMF_ST= 0;
	Ext_Group[point].SCN= XBYTE[(Addr_EXT_State+point*Addr_Offset)];
}
/***************************************
subroutine name: Exchang_CIDData
input variable:       Num
output variable:    num(new)
description:           calculte the data value for dtmf.
***************************************/
unchar Exchang_CIDData(unchar Num)
{
	if( Num == 0 )
	{
		Num = 0x0f;
		return Num;
	}
	if( Num == 0x0a )
	{
		Num = 0;
		return Num;
	}
	else
	{
		return Num;
	}
}
/***************************************
subroutine name: EXT_StateScan
input variable:       ext_group/0 or 1
output variable:    /
description:           scan ext hook off / on,when hook on the decorder shut off,or trun on.
***************************************/
void EXT_StateScan(unchar group)
{
unchar data Ext_No,i,flashtemp;
unchar data GROUP_ST_ANAL,GROUP_ST_NEW;

	GROUP_ST_NEW = Ext_Group[group].SCN;
	GROUP_ST_NEW |=  Ext_Group[group].Ext_Ring_ST;
	GROUP_ST_ANAL=GROUP_ST_NEW^Ext_Group[group].LL;
	
	for(i=0;i<8;i++)
	{
		Ext_No = group * 8+i;
		if( Ext_No > TAL_EXT_PORT )
		{
			break;
		}

		if( Ext_Param[Ext_No].Flag_Signal == 0x61 )
		{
			Ext_Group[group].SCN |= (1<<i);//保证初始态为1
			Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_ON;
			continue;
		}//由于在用户振铃期间OFFHOOK信号有低出现,必须屏蔽该段时间
		
		if( GROUP_ST_ANAL & 0x01 )
		{
			if((GROUP_ST_NEW & 0x01)==0)//如果用户是摘机
			{
				if( Ext_Param[Ext_No].Ext_State == state7_TalkFrom )
				{
					if(Ext_Timer[Ext_No].Counter_HK>=EXT_SCAN_ON+Flash_Scan_Start)//大于60ms
					{
						if(Ext_Timer[Ext_No].Counter_HK<=EXT_SCAN_ON+Flash_Scan_End)//小于180ms
						{
							Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
							Ext_Param[Ext_No].Ext_EVENT = event17_ExtFlash;
							MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No, 
								WP_EVENT, TAL_EVENT, BufSize);
							goto Next_Ext;
							//用户进入闪断事件;//400~800ms,flash 在60~180ms
						}
					}
				}
			}
			Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_ON;
			if( EXT_SCAN_PRI )
				Ext_Timer[Ext_No].Counter_HK++;
			else
				goto NO_PRI;
		}
		else
		{
			if( Ext_Timer[Ext_No].Counter_HK >EXT_SCAN_ON)
			{
				flashtemp = 0;
				if( Ext_Param[Ext_No].Ext_State == state7_TalkFrom )
				{
					if( GROUP_ST_NEW & 0x01 )
					{
						flashtemp = Flash_Scan_End;
					}
				}//只分析挂机的时候的情况,摘机不管了

				if( Ext_Timer[Ext_No].Counter_HK >(EXT_SCAN_LEN+flashtemp) )
				{
NO_PRI:			if( GROUP_ST_NEW & 0x01 )
					{
						Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
						Ext_Param[Ext_No].Ext_EVENT = event2_ExtHookOff;
						MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No, 
							WP_EVENT, TAL_EVENT, BufSize);
						//用户进入挂机事件;
					}
					else
					{
						Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
						Ext_Param[Ext_No].Ext_EVENT = event1_ExtHookOn;
						MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No, 
							WP_EVENT, TAL_EVENT, BufSize);
						//用户进入摘机事件;
					}			
				}
				else
				{
					Ext_Timer[Ext_No].Counter_HK++;				
				}
			}
			else
			{//由于出现一段时间后发现用户不能使用,所以要查询摘机然后直接挂
				Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
			}
		}
Next_Ext:		
		GROUP_ST_NEW >>=  1;
		GROUP_ST_ANAL >>= 1;
	}
	Ext_Group[group].LL = Ext_Group[group].SCN;
}

/***************************************
subroutine name: Control_4052
input variable:       /
output variable:    /
description:           selec the point to control the anolog switch.
实际的使用中出现了解码信号滞后,所以控制点
要停留处理
同时注意,由于PLD的控制后4052控制信号是反的,
1表示低电平,0表示高电平,所以:
A=1,B=1,实际选通Y0
A=0,B=1,实际选通Y1
A=1,B=0,实际选通Y2
A=0,B=0,实际选通Y3
***************************************/
void Control_4052(void)
{
	SLEC_Point++;
	SLEC_Point &= 0x03;
	switch(SLEC_Point)
	{
		case 0:
			Control_4052A= 0;
			Control_4052B= 1;
			break;
		case 1:
			Control_4052A = 1;
			Control_4052B = 0;
			break;
		case 2:
			Control_4052A = 0;
			Control_4052B = 0;
			break;
		case 3:
			Control_4052A = 1;
			Control_4052B = 1;
			break;
		default:
			break;
	}
}
/*************************
name:Ext_Timer_Reset(unchar Ext_No)
input:Ext_No
output:/
description:
将用户所有计数参数复位
*************************/
void Ext_Timer_Reset(unchar Ext_No)
{
	Ext_Timer[Ext_No].Counter_HK = 0;				//所有计数器归0
	Ext_Timer[Ext_No].Counter_Signal = 0;
	Ext_Timer[Ext_No].Counter_Pause = 0;
	Ext_Timer[Ext_No].Counter_Rec_DTMF = 0;
}
/*************************
name:Ext_Param_Reset(unchar Ext_No)
input:Ext_No
output:/
description:
将用户所有参数复位
*************************/
void Ext_Param_Reset(unchar Ext_No)
{
unchar data i;

	Ext_Param[Ext_No].Num_Call_Other = 0xff;		//主叫浮空
	Ext_Param[Ext_No].Num_Call_Me = 0xff;			//被叫浮空
	i = Ext_Param[Ext_No].Num_Switch_Cable&0x0f;
	if(i<TAL_CABLE)
		Micro_Switch_8816(Ext_No, i, 0);
	Ext_Param[Ext_No].Num_Switch_Cable = 0xff;		//绳路浮空
	Ext_Param[Ext_No].RecDTMF_Data = 0xff;			//接收的数据浮空
	Ext_Param[Ext_No].RecDTMF_En = MT8870_NoRec;	//收号器不可用
	Ext_Param[Ext_No].Ext_EVENT = 0xff;			//用户事件浮空
	Ext_Param[Ext_No].Ext_State = state0_Free;		//改变用户状态
	Ext_Param[Ext_No].Flag_Signal = 0;				//改变用户状态
	for(i=0;i<12;i++)
	{
		Ext_Param[Ext_No].Ext_RecDtmf_List[i] = 0;
	}
	Ext_Param[Ext_No].Num_MeetGroup = 0xff;
	Ext_Param[Ext_No].Temp_Troop_Call = 0;			//改变用户群呼状态
}

/******************************
Name:OPEN_EXT_Signal(unchar Ext_No,unchar Listen)
input:Ext_No,Signal_Type
output:none
description:
Signal_Type说明
听信号音				1
听忙音				2

⌨️ 快捷键说明

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