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

📄 cmx868.c

📁 cmx868的应用程序 用于电话机的缴费终端的设计 经过调试 可以应用欢迎大家下载
💻 C
字号:
#include "CMX868.h"
#include "Key.h"
#include "Timer.h"
#include "save.h"
#include "I2c.h"
#include "Serial.h"
#include"Lcd.h"

CMXBUFF   cmxBUF;
/**********
#pragma vector=UART0RX_VECTOR
__interrupt  void UART0RXinterrupt(void)
{
	char nChar = U0RXBUF;
        cmxBUF.RBuff[cmxBUF.cRHead] = nChar;
        ++cmxBUF.cRHead;
        if (cmxBUF.cRHead >= CMXRXLEN)
        cmxBUF.cRHead = 0;
	

}
***************/

void TestCMX(void)
{

 uchar i;
 Rest_Buff();
 for(i=0;i<0xff;i++)
 cmxBUF.RBuff[cmxBUF.cRHead++]='0';
 cmxBUF.RBuff[cmxBUF.cRHead++]='|';
}
void Cspi_bytewrite(uchar data)
{
	uchar i;
	CSPICLK_0;
	for(i=0; i<8; i++)
	{
		if((data & BIT7)==BIT7)
			CSPIMO_1;
		else
			CSPIMO_0;
		_NOP();
		CSPICLK_1;
		NOP4;
		CSPICLK_0;
		data <<= 1;

	}
}

//读字节
uchar Cspi_byteread(void)
{
	uchar i,tempdata,tempbit;
	for (i=0; i<8; i++)
	{
		CSPICLK_1;
		_NOP();
		if (CSPIDATA_IN == 0X80)
			tempbit = 1;
		else
			tempbit = 0;
		tempdata = (tempdata << 1) | tempbit;
		CSPICLK_0;
		NOP4;
	}
	return tempdata;
}


void Rest_Buff(void)
{
	cmxBUF.cRHead=0;
	cmxBUF.cRTail=0;
}

void StartFSK()
{   
	P2IE  &= 0XFE;
	P2IFG &= 0XFE;//禁止FSK数据接收
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXGENCTRL_ADDR); //写控制控制寄存器地址
	Cspi_bytewrite(0x11);            //选择外部晶体11.0592M,loopback-off,平衡禁止,
	Cspi_bytewrite(0x41);//选择中断接收
	NOP4;
	CSPI_DIS;
	Delay(100);
	WATCHDOG_CLEAR;
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXTXMODE_ADDR);  //接收模式设置:禁止RX
	Cspi_bytewrite(0x3E);
	Cspi_bytewrite(0X16); 
	NOP4;                           //bell202的逻辑'1'的信号频率为2200
	CSPI_DIS; 
	Delay(0x100);
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXRXMODE_ADDR); //发送模式设置,禁止TX
	Cspi_bytewrite(0x3E);
	Cspi_bytewrite(0X36);           //异步36数据
	NOP4;
	CSPI_DIS;
	msDelay(1);
}


uint CSpi_Read_Int(ulong addr)
{  
	uint data1, data2;
	uint data;
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(addr);           //写低字节地址
	data1 = Cspi_byteread();        //读数据
	data2 = Cspi_byteread();        //读数据
	NOP4;
	CSPI_DIS;
	Delay(100);
	data = ((data1<< 8)&0XFF00)+data2; 
	return data;
}

uchar Read_CPH(uchar  addr)
{
	uchar total;
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(addr);
	total=Cspi_byteread( );
	NOP4;
	CSPI_DIS;
	Delay(100);
	return total;
}

void reset_cbus()
{
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXGENRESET);       //复位芯片操作
	NOP4;
	CSPI_DIS;
	Delay(0x100);          
}

void TX_cmx868(uchar data)
{
	while((CSpi_Read_Int(0XE6)&0x1000)!=0x1000)
	{_NOP();WATCHDOG_CLEAR; }

	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXTXDATA_ADDR);   //接收模式设置:禁止RX
	Cspi_bytewrite(data);     
	NOP4;                             //bell202的逻辑'1'的信号频率为2200
	CSPI_DIS; 
}                                          

void Init_CMX868(void)
{ 

	P6DIR |=0X70;
	P6DIR &=0X7F;
	P6OUT &=0X0F;
	//------------------------------
	P2DIR &=0XFE;// P2.0CMX868中断信号输入
	P2IES |= 0X01;//高到低产生中断
	P2IFG &= 0xFE;//清可疑中断
	P2IE  &= 0xFE;//禁止产生中断
	WATCHDOG_CLEAR;
        NOP4;   
	CSPI_EN; 
	NOP4;
	Cspi_bytewrite(CMXGENRESET);       //复位芯片操作
	NOP4;
	CSPI_DIS;   
	Delay(0x100);                      //每次写一个指令

	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXGENCTRL_ADDR);   //写控制控制寄存器地址
	Cspi_bytewrite(0x13);              //选择外部晶体11.0592M,loopback-off,平衡禁止,
	Cspi_bytewrite(0x40);
	NOP4;
	CSPI_DIS;   
	Delay(0x100); 

	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXRXMODE_ADDR);    //接收模式设置:RX设置为DTMF接收模式
	Cspi_bytewrite(0x00);
	Cspi_bytewrite(0X00);
	NOP4;
	CSPI_DIS;   
	msDelay(10);
}

//摘机
void Hook_On(void)
{
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXGENCTRL_ADDR); //写控制控制寄存器地址
	Cspi_bytewrite(0x11);            //选择外部晶体11.0592M,loopback-off,平衡禁止,
	Cspi_bytewrite(0x40);
	NOP4;
	CSPI_DIS;
        //延时等待拨号音
        msDelay(2000);	//等待1.5s
}

//挂机
void Hook_Off(void) 
{
	CSPI_EN;
	NOP4;
	Cspi_bytewrite(CMXGENCTRL_ADDR);  //写控制控制寄存器地址
	Cspi_bytewrite(0x13);             //选择外部晶体11.0592M,loopback-off,平衡禁止,
	Cspi_bytewrite(0x40);
	NOP4;
	CSPI_DIS;
        msDelay(1500);//等待1.5s
}

//拨号呼叫Sp,并并切换到FSK状态
//返回  0    --- 成功
//      其他 --- 失败
uchar ConnectSp()
{ 
	uchar nChar;
	uchar idx;
	WATCHDOG_CLEAR;
	//每次重新初始化
	Init_CMX868();
	//进行摘机操作
	Hook_On();  
        //开始拨号,05305361944
	for (idx=0;idx<16;idx++)
	{
	    nChar = I2c_Read (ACCESSCODE+idx);
	    if (nChar<'0' || nChar>'9') break;
            DTMF_SENT(nChar=='0'? 10 :nChar-0x30);
	}
	//延时切换至 FSK状态
        msDelay(5000);
        StartFSK();
        P2IE |= 0X01;//打开接收中断
 	//Lcd_Show(0X80, "任意键退出");
 	//idx = 1;
        //while (idx)
       // {
//            nChar = CSpi_Read_Int(CMXSTAT_ADDR) ;
//            if(nChar&0X0040) //接收检测中断
//            {
//                nChar= Read_CPH(CMXRXDATA_ADDR);
//                //调试输出
//                while (TX0BUSY) NOP;
//                U0TXBUF = nChar;
//            }
           // if (GetKey()!=KEYNO) idx=0;
       // }
        //return 1;
        
        
        return 0;
}

//双音多频发送函数
void DTMF_SENT(uchar code)
{
	if(code <= 0x0f)
	{
		CSPI_EN;
		NOP4;
		Cspi_bytewrite(CMXTXMODE_ADDR);   //发送模式设置
		Cspi_bytewrite(0X1E);
		Cspi_bytewrite(0X10+code);        //发送双音多频

		NOP4;
		CSPI_DIS;
		NOP4;	
		msDelay(60);
		CSPI_EN;
		NOP4;
		Cspi_bytewrite(CMXTXMODE_ADDR);                        
		Cspi_bytewrite(0X1E);
		Cspi_bytewrite(0X00);             //停止双音多频
		NOP4;
		CSPI_DIS;	
		msDelay(150);
	}
}

/********CMX868中断输入 P2.0端口********
发送数据的时候屏蔽掉接收中断
接收数据的时候屏蔽掉发送中断
***************************************/
/*************/
#pragma vector=PORT2_VECTOR
__interrupt  void CmxInterrupt(void)
{
	uint status;   //读状态寄存器的情况,判断产生中断的类型
	uchar nChar;
	if((P2IFG&0X01)==0x01)
	{
		status=CSpi_Read_Int(CMXSTAT_ADDR);
		if((status &0X0040)==0X0040) //接收检测中断
		{
                    nChar= Read_CPH(CMXRXDATA_ADDR);
                    cmxBUF.RBuff[cmxBUF.cRHead] = nChar;
                    ++cmxBUF.cRHead;
                    if (cmxBUF.cRHead >= CMXRXLEN)
                            cmxBUF.cRHead = 0;
            
		}
	}
	else if((P2IFG &0X02)==0X02)
	{
	
	
	}
	P2IFG &= 0XFC;
}
/*****************/
/***********************************/
void WaitCMXCharCount(uint cnt)
{
	while (g_WaitTimeOut == FALSE)
	{  
		if (GetKey() == KEYCLEAR)
			g_WaitTimeOut = TRUE;
		else if (CMXGetCount()>=cnt)   
			break;
		WATCHDOG_CLEAR;
	}  
	  
}  
/****************************************/
void WaitCMXUartChar(uchar ch)
{
	uchar  nChar;
	while (g_WaitTimeOut == FALSE)
	{  
		if (GetKey() == KEYCLEAR)
			g_WaitTimeOut = TRUE;
		else
		{
			nChar = CMXReadChar();
			if ( nChar==ch)
				break;
		}
		WATCHDOG_CLEAR;
	}    
}  

//返回缓冲区内字节数
uint CMXGetCount(void)
{
	uint count = 0;
	P2IE &=0XFE;   //禁止中断
	if (cmxBUF.cRHead >= cmxBUF.cRTail)
	{
		count  = cmxBUF.cRHead - cmxBUF.cRTail;
	}else{
		count  = CMXRXLEN + cmxBUF.cRHead - cmxBUF.cRTail;
	}
	P2IE |=0X01;
	return count;
}
//读取缓冲区的中len字节,并且设置m_Uart_State为错误代码
uchar CMXnReadChar( char *dst, uchar len)
{
	uchar count=0,idx;
	P2IE &=0XFE; 
	if (cmxBUF.cRHead >= cmxBUF.cRTail)
	{
		count  = cmxBUF.cRHead - cmxBUF.cRTail;
	}else{
		count  = CMXRXLEN  + cmxBUF.cRHead - cmxBUF.cRTail;
	}
	if (count<len)
	{
		//m_CMX_State = ERR_UART_LESS;
	}
	else
	{
		for (idx=0;idx<len;idx++)
		{
			*(dst+idx) = cmxBUF.RBuff[cmxBUF.cRTail];
			cmxBUF.cRTail = (cmxBUF.cRTail+1)% CMXRXLEN;
		}
	}
	P2IE |=0X01;  
	return count;
}   

//读取一行,'|'结束,返回读取的字符串长度
uchar CMXReadLine( char *pdst, char max)
{
	uchar count = 0,total;
	int idx,off;
	P2IE &=0XFE;
	if (cmxBUF.cRHead != cmxBUF.cRTail)
	{
		//计算有效数据总长度
		if (cmxBUF.cRHead >= cmxBUF.cRTail)
		{
			total  = cmxBUF.cRHead -cmxBUF.cRTail;
		} else{
			total  = CMXRXLEN + cmxBUF.cRHead - cmxBUF.cRTail ;
		}
		//找结束符
		for (idx=0;idx<max-1 && idx<total;idx++)
		{
		        WATCHDOG_CLEAR;
			off = cmxBUF.cRTail + idx;
			if (off >= CMXRXLEN)  off -= CMXRXLEN;
			pdst[idx] = cmxBUF.RBuff[off];
			if (cmxBUF.RBuff[off]=='|')
			{
				count = idx+1;
				pdst[count-1] = 0;
				cmxBUF.cRTail = off + 1;
				if ( cmxBUF.cRTail >= CMXRXLEN) cmxBUF.cRTail =0;
				//增加内容,可以保证"\r\n"结束不影响下一行处理
				//if (cmxBUF.RBuff [cmxBUF.cRTail]=='\n')
				//{
				//  cmxBUF.cRTail += 1;
				//  if ( cmxBUF.cRTail >= CMXRXLEN) cmxBUF.cRTail =0;
				// }
				break;
			}
		}
	}
	P2IE |=0X01; 
	return count;
}

char CMXReadChar(void)
{
	char val='*';
	P2IE &=0XFE; // Disable USART0 RX interrupt
	
	if (cmxBUF.cRHead != cmxBUF.cRTail)
	{
		val = cmxBUF.RBuff[cmxBUF.cRTail++];
		if (cmxBUF.cRTail>=CMXRXLEN) cmxBUF.cRTail = 0;
	}else{
		// m_Uart_State = ERR_UART_EMPTY;
	}
	P2IE |=0X01; 
	return val;
}

uchar CMXReFirst(void)  //读第一段落的内容
{
	uint count = 0,total;
	int off;

	P2IE &=0XFE;             // Disable USART0 RX interrupt
	if (cmxBUF.cRHead != cmxBUF.cRTail)
	{
		//计算有效数据总长度
		if (cmxBUF.cRHead >= cmxBUF.cRTail)
		{
			total  = cmxBUF.cRHead - cmxBUF.cRTail;
		} else{
			total  = CMXRXLEN + cmxBUF.cRHead -cmxBUF.cRTail ;
		}
		//找结束符
		if (total>11)//帧长度至少为7
		{
			if (cmxBUF.RBuff[cmxBUF.cRTail]!='B')
			{
				cmxBUF.cRTail = (cmxBUF.cRTail+1)% CMXRXLEN;
			}else{   
				off = (cmxBUF.cRTail + 1) % CMXRXLEN;
				if (cmxBUF.RBuff[off]!='B')
				{
					cmxBUF.cRTail = (cmxBUF.cRTail+2)% CMXRXLEN;
				}else{
					count=total;
				}
			}
		}
	}
	P2IE |=0X01;
	WATCHDOG_CLEAR;
	return count;
}

//*********读取一桢的数据***********************  
//返回 1 收到完整数据帧
//     0 没有数据或超时或校验错误
uchar ReadOneBlock(void)
{
	uchar nChar;
	uint cmxlength=0;
	uint idx;
	uchar count=0;
	uchar recout=0;
	uchar space=0;
	g_WaitTimeOut = FALSE;//设定超时
	SetTimer(TIMER_TIMEOUT,30000,Do_TimeOut);
	while(g_WaitTimeOut == FALSE)
	{      
	       if (GetKey() == KEYCLEAR)
		g_WaitTimeOut = TRUE;
		nChar= CMXReFirst();
		if(nChar>=11) break;
		WATCHDOG_CLEAR;
	}
	KillTimer(TIMER_TIMEOUT);
	if(g_WaitTimeOut == TRUE)
	{
	 //Lcd_Clear();
	// Lcd_Show(0x80,"通信繁忙无法传输");
	 //Lcd_Show(0x90,"请挂机重拨");
	 //Lcd_Show(0x98,CmdHelp);
	 return recout;
	} 
	for(idx=0;idx<4;idx++)
        {
          if(cmxBUF.RBuff[cmxBUF.cRTail+3+idx]==32)
          space++;
        }
        switch(space)
       {
         case 0:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*1000+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48)*100+(cmxBUF.RBuff[cmxBUF.cRTail+5]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+6]-48));break;
         case 1:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*100+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+5]-48));break;
         case 2:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48));break;
         case 3:cmxlength=(cmxBUF.RBuff[cmxBUF.cRTail+3]-48);break;
         default:break;
        }
      
	g_WaitTimeOut = FALSE;//设定超时
	SetTimer(TIMER_TIMEOUT,60000,Do_TimeOut);
	WaitCMXCharCount(cmxlength+11);   //不精确,还有前面没有计算到的字节数
	KillTimer(TIMER_TIMEOUT);
	if(g_WaitTimeOut == TRUE) return recout;
	else
	recout=1;
	for(idx=0;idx<cmxlength+8;idx++)
	{
	 WATCHDOG_CLEAR;
	 count^=cmxBUF.RBuff[cmxBUF.cRTail+idx];
	}
	if(count==0)	recout=1;
	return recout;
}


uchar ReadDelaiyBlock(void)
{
	uchar nChar;
	uint cmxlength=0;
	uint idx;
	uchar count=0;
	uchar recout=0;
	uchar space=0;
	g_WaitTimeOut = FALSE;//设定超时
	SetTimer(TIMER_TIMEOUT,5000,Do_TimeOut);
	while(g_WaitTimeOut == FALSE)
	{      
	       if (GetKey() == KEYCLEAR)
		g_WaitTimeOut = TRUE;
		nChar= CMXReFirst();
		if(nChar>=11) break;
		WATCHDOG_CLEAR;
	}
	KillTimer(TIMER_TIMEOUT);
	if(g_WaitTimeOut == TRUE)
	{
	 //Lcd_Clear();
	// Lcd_Show(0x80,"通信繁忙无法传输");
	 //Lcd_Show(0x90,"请挂机重拨");
	 //Lcd_Show(0x98,CmdHelp);
	 return recout;
	} 
	for(idx=0;idx<4;idx++)
        {
          if(cmxBUF.RBuff[cmxBUF.cRTail+3+idx]==32)
          space++;
        }
        switch(space)
       {
         case 0:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*1000+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48)*100+(cmxBUF.RBuff[cmxBUF.cRTail+5]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+6]-48));break;
         case 1:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*100+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+5]-48));break;
         case 2:cmxlength=((cmxBUF.RBuff[cmxBUF.cRTail+3]-48)*10+(cmxBUF.RBuff[cmxBUF.cRTail+4]-48));break;
         case 3:cmxlength=(cmxBUF.RBuff[cmxBUF.cRTail+3]-48);break;
         default:break;
        }
      
	g_WaitTimeOut = FALSE;//设定超时
	SetTimer(TIMER_TIMEOUT,60000,Do_TimeOut);
	WaitCMXCharCount(cmxlength+11);   //不精确,还有前面没有计算到的字节数
	KillTimer(TIMER_TIMEOUT);
	if(g_WaitTimeOut == TRUE) return recout;
	for(idx=0;idx<cmxlength+8;idx++)
	{
	 WATCHDOG_CLEAR;
	 count^=cmxBUF.RBuff[cmxBUF.cRTail+idx];
	}
	if(count==0)	recout=1;
	return recout;
}

⌨️ 快捷键说明

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