📄 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 + -