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

📄 fsk.c

📁 基于mega48单片机编码cmx865芯片驱动程序实现FSK通信模块。
💻 C
字号:
#include "FSK.h"
/***********************************************************************
*
*		函数名:ModemTxFSK
*		说  明:FSK发送函数
*		入口值:无
*		返回值:无
*		日  期:2006-10-7 10:23
*
***********************************************************************/
void  ModemTxFSK(void)
{
	unsigned char i;
	EIMSK=0x00;							
	ResetModem();									// 初始化MODEM
		
	Delay1MS(32);
					
	WriteModem(SET_UP,0x1348);					// 置General Control Register  发送中断使能1348
			
	Delay1MS(32);
	
	WriteModem(TX_MODE,0x3018);					//连续发送0101(0x5018)
	
	Delay1MS(100);	
	WriteModem(TX_MODE,0x3016);					// 置Transmit Mode Register发送连续的1(0x503B)5016
					// 发送连续的1的个数通过延时时间来控制
	Delay1MS(40);	

	// 发送完同步字符之后,置Transmit Mode Register来发送具体数据
	WriteModem(TX_MODE,0x3036);					// 置Transmit Mode Register发送具体数据0x5036
	
	for(i=0; i<bCmdAns.aBuf[0]; i++)					//将号码存入拨号缓存(aBuf[0]存入DTMF号码长度)
	{
		ModemTxByte(bCmdAns.aBuf[i+1]);			// 发送具体数据调用的函数
	}
	Delay1MS(60);									//保证最后数据发送
	WriteModem(TX_MODE,0);	
	EIMSK=0x01;
}

/***********************************************************************
*
*		函数名:ModemTxFSK
*		说  明:FSK发送一个字节函数
*		入口值:发送1字节具体数据
*		返回值:true or false
*		日  期:2006-10-7 10:23
*
***********************************************************************/
unsigned char ModemTxByte(unsigned char bByte)
{
	unsigned int iTemp;
	WriteModem(TX_DATA_BYTE,bByte);							// 向 Transmit Data Register 写数据数据
	fDelay1MS1=0;
	FSKDelay1MS1=32;
	while(1)
	{
		if(fDelay1MS1)
		{	
			return FALSE;
		}
		if(!ReadIRQ())										// 读MODEM中断口线IRQ是否有中断来
		{
			iTemp=ReadModem(STATUS);	
			// 有中断来,即读状态控制寄存器(Status Register)
			if(((iTemp&0x0800)!=0)||((iTemp&0x1000)!=0))	// 通过读取Status Register的值来判断一个字节数据是否发送完毕
			{
				while(!ReadIRQ())							// 发送完毕以后重新检验中断口线IRQ是否为高(因为中断来时IRQ口线被置为低,一旦读取了Status寄存器以后,IRQ口线就会被重新置为高,等待下一个中断)
				{
					FSKDelay1MS2=32;
					fDelay1MS2=0;
					if(fDelay1MS2)							// 此处是对MODEM出错的控制
						break;
				}
				return TRUE;
			}
		}
	}
}

/***********************************************************************
*
*		函数名:ModemRxFSK
*		说  明:FSK接收函数寄存器控制字设置
*		入口值:无
*		返回值:无
*		日  期:2006-10-8
*
***********************************************************************/

void  ModemRxFSK(void)
{
	unsigned char bRxByte;
	// 初始化MODEM
	ResetModem();
	WriteModem(SET_UP,0x1341);					// 置General Control Register  接收中断使能1341

	WriteModem(RX_MODE,0x3836);					// 置Recieve Mode Register 接收数据5036
//	ModemRxByte();
//	WriteModem(RX_MODE,0);		
}

/***********************************************************************
*
*		函数名:ModemRxByte
*		说  明:FSK接收数据函数
*		入口值:无
*		返回值:无
*		日  期:2006-10-8
*
***********************************************************************/
void ModemRxByte(void)
{
	unsigned int iTemp;
	unsigned char bFSKValue;
		iTemp=ReadModem(STATUS);					// 读状态寄存器 //	
		if(iTemp&0x0040)								// 根据读取的状态寄存器的值,查看接收中断
		{
			bFSKValue=(unsigned char)ReadModem(RX_DATA_BYTE);		// 读Recieve Data Register 读取数据 //
		if ((fValidData==3)&&(pWriteFSK<240))
		{	
			aHostTxBuf[pWriteFSK++]=bFSKValue;							
			if (pWriteFSK>239)							// 超过240则停止接收 //
				pWriteFSK=240;
			if(pWriteFSK==(aHostTxBuf[4]+6))			// 收完之后等待收下一串数据
			{	
				fFSKRecEnd=1;	
				fValidData=0;
				return;
			}
		}			
		else
		{ 
			if((fValidData==0)&&(bFSKValue==0x55))		//去掉同步码后开始计数
			{		
				fValidData=1;
			}
			else if((fValidData==1)&&(bFSKValue==0xff))
			{
				fValidData=2;
			}
			else if((fValidData==2)&&(bFSKValue==0x84))
			{
				fValidData=3;
				aHostTxBuf[3]=bFSKValue;
				pWriteFSK++;
			}
		}
	}
}


/***********************************************************************
*
*		函数名:ReadModem
*		说  明:对C_BUS口读操作
*		入口值:	要读参数的地址
*		返回值:要读参数的值
*		日  期:2006-10-7 
*
***********************************************************************/
unsigned int ReadModem(unsigned char term)
{
	unsigned char i,j,bDataNum;
	unsigned int iRecBuf,temp;
	unsigned int temp1=0;
	
	CLI(); 							// 禁止中断 //
	PORTD&=0x7F;					// MODEM片选CS口置低(pd7=0)csn=0;	
	CBusData(term,8);				// 先写入要读参数的地址 //
	iRecBuf=0;						// 接收数据缓冲区准备 //

	if(term==RX_DATA_BYTE)		// Receive Data Register //
	{
		bDataNum=8;
		temp=0x80;
	}
	else
	{
		bDataNum=16;
		temp=0x8000;
	}
	PORTB&=0xFD;					// 将位时钟线置低电平,开始接收 //
	for(i=0;i<bDataNum;i++)			// 循环接收8BIT的数据 //
	{
		PORTB|=0x02;				// 将位时钟线置高电平,表示一个位接收完毕 //
		temp1=PINB&0x01;
		if(temp1)						//pb0(RDATA)
		{
			iRecBuf|=temp;			// 接收数据线上的数据 //
		}
		temp>>=1;
		PORTB&=0xFD;				// 将位时钟线置低电平,开始接收 //
	}
	PORTD|=0x80;					// 发送完以后MODEM片选CS口置高(pd7=1)csn=1;
	SEI();
	return iRecBuf;
}

/***********************************************************************
*
*		函数名:ReadModem
*		说  明:向MODEM写数据底层函数
*		入口值:要写参数的地址、参数的值
*		返回值:无
*		日  期:2006-10-8 
*
***********************************************************************/
void WriteModem(unsigned int cbusAddr,unsigned int cbusData)
{
	CLI(); 								// 禁止中断 //
	PORTD&=0x7F;						// MODEM片选CS口置低(pd7=0)csn=0;	
	CBusData(cbusAddr,8);				// 写入地址 //
	if(cbusAddr==TX_DATA_BYTE)		// Transmit Data Register //
		CBusData(cbusData,8);			// 写入数据(8位) //
	else
		CBusData(cbusData,16);			// 写入数据(16位) //
	PORTD|=0x80;						// 发送完以后MODEM片选CS口置高(pd7=1)csn=1;	
	SEI();								// 打开中断 //
}

/***********************************************************************
*
*		函数名:CBusData
*		说  明:底层写函数
*		入口值:要写参数的地址、参数的值
*		返回值:无
*		日  期:2006-10-8 
*
***********************************************************************/
void CBusData(unsigned int bData,unsigned char number)
{
	unsigned char  i;
	unsigned int iTemp;
								
	if(number==8)
		iTemp=0x80;
	else
		iTemp=0x8000;
	for(i=0;i<number;i++)
	{
		PORTB&=0xFD;						// MODEM 时钟口线SCLK(sclk=0;pb1=0)
		if(bData&iTemp)						// 位数据的发送 //
		{
			PORTB|=0x04;					// MODEM 的COMD(CDATA=1;PB2=1)
		}
		else
		{
			PORTB&=0xFB;					//CDATA=0;
		}
		PORTB|=0x02;						//SCLK=1;
	       iTemp>>=1;
	}
}

/***********************************************************************
 *
 *	函数名:ResetModem
 *	说  明:初始化CMX865芯片
 *	入口值:无
*	返回值:无
*	日  期:2006-10-8 
 ***********************************************************************/
void ResetModem(void)
{
	CLI(); 
	PORTD&=0x7F;					// MODEM片选CS口置低(pd7=0)csn=0;	
	CBusData(GENERAL_RESET,8);
	PORTD|=0x80;					// 发送完以后MODEM片选CS口置高(pd7=1)csn=1;	
	SEI();
}

/***********************************************************************
 *
 *	函数名:Dial
 *	说  明:DTMF拨号函数
 *	入口值:无
*	返回值:无
*	日  期:2006-10-10 
 ***********************************************************************/
void Dial (void)
{
	unsigned char i,bDtmf,j;
	LINE_DATA *p;
	p=&aLineData;
	switch(p->bDailWord){
		case 0x10:
			if(!p->fDelay10MS2)		// 等并模拟负载后延时拨号时间到
				return;
			p->bDailWord=0x11;
			break;

		case 0x11:
			//FSKSendFlag=1;(87880077)
			ResetModem();
			Delay1MS(500);
			for(i=0; i<bCmdAns.aBuf[0]; i++)	//将号码存入拨号缓存(aBuf[0]存入DTMF号码长度)
			{
				bDtmf=bCmdAns.aBuf[i+1];
				Delay1MS(32);
	                      ResetModem();
				Delay1MS(120);
				WriteModem(SET_UP,0x1100);
	                     
				Delay1MS(50);
				
				WriteModem(TX_MODE,(0x1E10+bDtmf));		// 通过设置Transmit Mode Register 来往MODEM送号

				Delay1MS(80);
			
				WriteModem(TX_MODE,0);					// 停止拨号 //	
			}
			//FSKSendFlag=0;
			pWriteFSK=3;
			ModemRxFSK();				//中断函数内接收
			p->bDailWord=0x12;
			break;
		default:
			break;
	}
}

/***********************************************************************
*
*		函数名:ReadIRQ
*		说  明:对MODEM中断口线操作
*		入口值:
*		返回值:口线为低返回0;为高返回1
*		日  期:2006-09-28 
*
***********************************************************************/
unsigned char ReadIRQ(void)
{
	unsigned char bTemp;
	bTemp=PIND&0x04;			//PD2
	if (bTemp)
		return 1;
	else
		return 0;
}

/***********************************************************************
*
*		函数名:RxFskInit
*		说  明:接收FSK信号初始化
*		入口值:无
*		返回值:无
*		日  期:2006-09-28 
*
***********************************************************************/
void RxFskInit(void)
{
	fValidData=0;
	pWriteFSK=3;
	ciDelay8MS=0;
	itemp=250;
   	mem_set(aHostTxBuf,0,BUFF_LEN_TX);
}

/***********************************************************************
*
*		函数名:InitModem
*		说  明:初始化Modem
*		入口值:无
*		返回值:无
*		日  期:2006-10-07 
*
***********************************************************************/
void InitModem(void)
{
	ResetModem();
	Delay1MS(30);	
	WriteModem(SET_UP,0x1300);	
}

/***********************************************************************
*
*		函数名:CheckLineState
*		说  明:线路状态检测
*		入口值:无
*		返回值:无
*		日  期:2006-10-17 
*
***********************************************************************/
void CheckLineState (void)
{
	/*LINE_DATA *p;
	 p=&aLineData;
	 fDetectRing=0;
	 fDetectLost=0;
	switch(p->bStatusWord)                        // 设置在不同的线路状态,检测的项目 //
	{	
		case LINE_IDLE:
			fDetectRing=1;
			//fDetectLost=0;					// 待机时并不并线,故无需检测脱线 //
			break;
		case LINE_OFFHOOK:                   //摘机
			fDetectLost=1;
			break;
	}
	//检测脱线
	if(!fDetectLost);
	else if(PIND&0x08)					// 脱线 //PD3=1
	{	
		p->cbLineOk=0;				
		if(p->cbLineLost>=60)
		{								// 脱线产生时间120ms秒 //
			p->fLineLost=1;
			p->cbLineLost=60;
			p->fLineOk=0;
		}
		else
		{
			++p->cbLineLost;
		}
	}
	else
	{	
		p->cbLineLost=0;
		if (p->cbLineOk>=30)
		{
			p->fLineLost=0;
			p->fLineOk=1;
			p->cbLineOk=30;
		}
		else
		{
			++p->cbLineOk;
		}
	}

	// 检测振铃 //
 	if(!fDetectRing);							// 在10毫秒定时器的中将它清过零//
       else if((PIND&0x10)==0x00)				// 检测振铃,ZLDET 振铃状态 //PD4=0
       	{	
       		p->ciRingStop=0;                   				
      		if (++p->ciRingStart>30)
      		{
			p->fRingOn=1;
			p->cbRingTimes2=1;
			p->ciRingStart=30;
      		}
    	}
       else
    	{        
    		p->ciRingStart=0;  
    		if ((++p->ciRingStop>30)&&(p->cbRingTimes2==1))
    		{
    	       		p->fRingOff=1;
    	       		p->cbRingTimes2=0;
    	       		p->ciRingStop=30;
    		}
    	}*/
}

⌨️ 快捷键说明

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