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

📄 fsk._c

📁 基于mega48单片机编码cmx865芯片驱动程序实现FSK通信模块。
💻 _C
字号:
#include "FSK.h"
/***********************************************************************
*
*		函数名:ModemTxFSK
*		说  明:FSK发送函数
*		入口值:	要读参数的地址
*		返回值:
*		日  期:2006-10-7 10:23
*
***********************************************************************/
void  ModemTxFSK(void)
{
	unsigned char i;
	
	//unsigned char aBuf[13]={0x84,0x0a,0x01,0x55,0x02, 0x03, 0x04,0x05,0x06,0x07,0x08,0x09,0x43};

	//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<13;i++)
	{
		ModemTxByte(aBuf[i]);			// 发送具体数据调用的函数
	}*/
	//Delay1MS(15);
	for(i=0; i<bCmdAns.aBuf[0]; i++)				//将号码存入拨号缓存(aBuf[0]存入DTMF号码长度)
	{
		ModemTxByte(bCmdAns.aBuf[i+1]);			// 发送具体数据调用的函数
	}
	//ModemTxByte(0x55);
	Delay1MS(60);								//保证最后数据发送
	WriteModem(TX_MODE,0);	
//	EIMSK=0x01;
}


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-7
*
***********************************************************************/

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);		
}

void ModemRxByte(void)
{
	unsigned int iTemp;
	unsigned char bFSKValue;
	ciDelay8MS=30;
	fDelay250MS=0;

	while(1)
	{
		if(fDelay250MS)
		{
			fDelay250MS=0;
			return;
		}
		if(!ReadIRQ())          // 读MODEM中断口线IRQ是否有中断来
		{
			iTemp=ReadModem(STATUS);					// 读状态寄存器 //	
			if(iTemp&0x0040)								// 根据读取的状态寄存器的值,查看接收中断
			{
				bFSKValue=(unsigned char)ReadModem(RX_DATA_BYTE);		// 读Recieve Data Register 读取数据 //
			if ((fValidData==3)&&(pWriteFSK<250))
			{	
				aHostTxBuf[pWriteFSK++]=bFSKValue;							
				if (pWriteFSK>249)					// 超过250则停止接收,ccw //
					pWriteFSK=250;
				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 10:23
*
***********************************************************************/
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;
}

/*向MODEM写数据底层函数*/
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();								// 打开中断 //
}

/*底层写函数*/
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()
 *	功	能:初始化CML868芯片
 *
 ***********************************************************************/
 
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();
}

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信号初始化
*		入口值:
*		返回值:
*		日  期:
*
***********************************************************************/
void RxFskInit(void)
{
	fValidData=0;
	pWriteFSK=3;
	ciDelay8MS=0;
	itemp=250;
   	mem_set(aHostTxBuf,0,BUFF_LEN_TX);
}

void InitModem(void)
{
	ResetModem();
	Delay1MS(30);	
	WriteModem(SET_UP,0x1300);//0x1380		
}

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:                   //摘机
		       //fDetectDtmf=1;
			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 + -