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

📄 test.c

📁 电话机的经典高效键盘扫描
💻 C
字号:
//#include <reg52.h>
#include <intrins.h>
#include <STC12.h>
#define   uchar unsigned char   /*宏定义*/	
#define   DIALNUM_LEN  20

sbit P1_7=P1^7;
sbit P1_6=P1^6;
sbit P1_5=P1^5;
sbit P1_4=P1^4;
sbit P1_3=P1^3;
sbit P1_2=P1^2;
sbit P1_1=P1^1;
sbit P1_0=P1^0;	

sbit P2_1=P2^1;
sbit P2_0=P2^0;
sbit HOOK_OFF_IN=P2^4;
sbit P2_6=P2^6;
sbit FREE_HAND=P2^2;
sbit PSTN_CIN=P2^3;
sbit MAN_CIN=P2^7;
sbit USB_CIN=P2^6;
sbit KEYPAD_INT=P3^2;
sbit FSK_R_DATA=P3^4;

sbit P3_0=P3^0;
sbit P3_1=P3^1;
sbit P3_2=P3^2;
sbit P3_3=P3^3;
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_6=P3^6;
sbit P3_7=P3^7;

	uchar i = 0; 
	bit  temp_0 = 0;
	bit  temp_1 = 0;
	bit  temp_2 = 0;
	bit  temp_3 = 0;
	bit  temp_4 = 0;


char dialNum[DIALNUM_LEN];
uchar  SumNum = 0;
uchar index = 0;
uchar ch;
uchar record = 0;
uchar temp;
uchar GetKey;
uchar key_test =0x00 ;
void dial(uchar dialNum);
void dial_all_num(void);
void dial_dtmf(void);
void send_char_com(uchar ch);
void delay(unsigned int n);	
void dial_pause(void);
uchar scan(void);



void init_serialcomm()
{
	SCON=0x50;	//SCON:serial mode 1,8-bit UART,enable ucvr	  设置成串口1方式
	TMOD|=0x20;	//TMOD:timer 1,mode 2,8-bit reload 波特率发生器T1工作在模式2上

//	SMOD=0
	IP=0X10;		//串口优先级为1
    PCON|=0x00;	  //	波特率翻倍设置
	TH1 = 0xFC;  //3.579545 external osc
	IE|=0x90;	//Enable Serial Interrupt
	TR1=1;		//timer 1 run
	
}
void init_interruptcomm()
{
	IT0 = 0; //	 INI0 低电平有效
	IT1 = 0; //	 INI1 低电平有效
	IE|=0x81; //Enable INI0 Interrup
	IE|=0x84; //Enable INI1 Interrup
}


//INI0中断
void Int0_Routine(void) interrupt 0
{
	if(IE0 == 1) {	  //INT0中断请求标志位,进入中断执行时,硬件清0
		EX0 = 0;	   //关闭中断
		delay(500);	  //1000
		GetKey = scan();
		delay(500);		   //1000
		if(GetKey == scan())
		{		 
			if(ch != 0X00 )
			{
	    		send_char_com(GetKey);
			} 
		}
		delay(50000);	//must delay 1500000,防止按一次键两次进入中断				
		EX0 = 1;		  //打开中断
		//delay(1000);//add just now		  
    }
}



//向串口发送一个字符
void send_char_com(uchar ch)
{	
	SBUF = ch;
    while(TI==0);
	TI=0;
}

//向串口发送一个字符串

void send_char_string(void)
{	
	uchar i;
	for(i=0;i<SumNum;i++)
	{
		SBUF = dialNum[i];
	    while(TI==0);
		TI=0;
	}

}

//串口接收中断 
 
  
void serial() interrupt 4 using 3		//字符串!ASCD1234$以'!'开始,以'$'结束
{
	
	if(RI)
	{ 
		RI=0;
		ch = SBUF;
		
		if(ch=='$') 
	   {
	 		record=1;
			SumNum = index;
		 	index=0;
	 	}
		else if(ch=='!') 
		{ 
			record = 0;
			index=0;
			SumNum =0;
		}
		else 
		{ 
			record = 0;
			dialNum[index++] = ch;

		}	
		if(record)
		{
		//	send_char_string();
			dial_all_num();	
			SumNum = 0 ;
			record = 0;	
		}
    }



} 
  	

void uart_test(void)
{ 
	if(record)  
	{
			//send_char_string();

			//dial_all_num();	
		//	send_char_string();


			
		SumNum = 0 ;
		record = 0;			
	}
 }																								
																							


void delay(unsigned int n)
{
    unsigned i;
	i=0;
    while(i<n)i++;
}
//各行键盘扫描
void port(p1m0)
{   
 	uchar chTest; 
    P1=0;
	P1M0=p1m0;
	P1M1=0X00;
    switch(p1m0)
	{
	   	 case 0X7C:{P1_1=1;	delay(100); ch=P1;	   //500
		            switch(ch){
		 				   case 0x42: chTest = 'U';break;
						   case 0x22: chTest = '1';break;
						   case 0x12: chTest = '5';break;
						   case 0x0A: chTest = '8';break;
						   case 0x06: chTest = '0';break;
						   default:break;	
						      } 
					 break;	}
         case 0X7A:{ P1_2=1;delay(100); ch=P1;
		 			switch(ch){
		 				   case 0x44: chTest = 'V';break;
						   case 0x24: chTest = '2';break;
						   case 0x14: chTest = '6';break;
						   case 0x0C: chTest = '9';break;
						   case 0x06: chTest = 'F';break;
						   default:break;	
						      }  
					 break;	}
		 case 0X76:{ P1_3=1;delay(100); ch=P1;
		 			switch(ch){
		 				   case 0x48: chTest = 'W';break;
						   case 0x28: chTest = '3';break;
						   case 0x18: chTest = '7';break;
						   case 0x0C: chTest = '*';break;
						   case 0x0A: chTest = '#';break;
						   default:break;	
						      }
					 break;  }
		 case 0X6E:{ P1_4=1;delay(100);ch=P1;
		 			switch(ch){
		 				   case 0x50: chTest = 'X';break;
						   case 0x30: chTest = '4';break;
						   case 0x18: chTest = 'F';break;
						   case 0x14: chTest = 'M';break;
						   case 0x12: chTest = 'R';break;
						   default:break;	
						      } 
					 break; }
		 case 0X5E: {P1_5=1;delay(100);ch=P1;
		 			switch(ch){
		 				   case 0x60: chTest = 'F';break;
						   case 0x30: chTest = 'F';break;
						   case 0x28: chTest = 'H';break;
						   case 0x24: chTest = 'I';break;
						   case 0x22: chTest = 'F';break;
						   default:break;	
						      } 
					 break;}
		 case 0X3E:{ P1_6=1;delay(100);ch=P1; 
		 			switch(ch){
		 				   case 0x60: chTest = 'K';break;
						   case 0x50: chTest = 'L';break;
						   case 0x48: chTest = 'F';break;
						   case 0x44: chTest = 'F';break;
						   case 0x42: chTest = 'N';break;
						   default:break;
						      } 
					 break; }	 
	}	 
//	P1M0=p1m0;
//	P1M1=0X00;
//	delay(1000);  //must need 按键反应调试这个,delay 2ms
//	ch=P1;
	P1M0=0x00;	//将P1口都置成双向口  这两句位置必须放这里,放scan里也会死机
	P1 = 0XFF;	 //为下次中断作准备,放这里能确保P1	的1到6口置高
	if(ch!=0x02&&ch!=0x04&&ch!=0x08&&ch!=0x10&&ch!=0x20&&ch!=0x40) 	   //有键按下  
	{  
		key_test = chTest ;
	}	 

}

uchar scan(void)	   //键盘扫描
{
		 
		 key_test = 0;
    	 port(0X7C); 
		 port(0X7A); 
		 port(0X76); 
		 port(0X6E);
		 port(0X5E);
		 port(0X3E);   	
		 return key_test; 
}
void clk_down(void)
{
    P2_0=1;	 
	P2_0=0;
}
void clk_up(void)
{	 
	P2_0=1;
}

void dial_all_num(void)
{
	uchar n;
	
	  for(n=0;n<SumNum;n++)
	  {
			dial( dialNum[n]);	//产生DTMF波形,但会一直存在,不会自动中止
		 	delay(10000);	//有一定的延时,需要
		 	dial_pause();		 //dtmf波形中止
		  
	  }	
}

void dial(uchar dial_num){
  	 P1_7=0;	 //CE
	 clk_up();
	 switch(dial_num){
	       case '1':temp =0X01;dial_dtmf();break;	
		   case '2':temp =0X02;dial_dtmf();break;
		   case '3':temp =0X03;dial_dtmf();break;	
		   case '4':temp =0X04;dial_dtmf();break;
		   case '5':temp =0X05;dial_dtmf();break;
		   case '6':temp =0X06;dial_dtmf();break;
		   case '7':temp =0X07;dial_dtmf();break;
		   case '8':temp =0X08;dial_dtmf();break;
		   case '9':temp =0X09;dial_dtmf();break;	
		   case '0':temp =0X0A;dial_dtmf();break;
		   case '*':temp =0X0B;dial_dtmf();break;
		   case '#':temp =0X0C;dial_dtmf();break;
		   case 'A':temp =0X0D;dial_dtmf();break;	
		   case 'B':temp =0X0E;dial_dtmf();break;
		   case 'C':temp =0X0F;dial_dtmf();break;	
		   case 'D':temp =0X00;dial_dtmf();break;
		   default:	temp =0XFF;dial_dtmf();break;   
	 }
}

void dial_dtmf(void){
	
	uchar TEMP;
	for(i=0;i<5;i++){
		TEMP = temp & 0X01;
		if(TEMP == 0X01){
		 	switch(i){	
		 	 case 0:temp_0 =1;break;	
		     case 1:temp_1 =1;break;
		     case 2:temp_2 =1;break;
		     case 3:temp_3 =1;break;
			 case 4:temp_4 =1;break;	
		    }
		} else {
		   switch(i){	
		 	 case 0:temp_0 =0;break;	
		     case 1:temp_1 =0;break;
		     case 2:temp_2 =0;break;
		     case 3:temp_3 =0;break;
			 case 4:temp_4 =0;break;	
		    }
		}
		temp = temp >> 1;
	}
	for(i=0;i<10;i++) {      //	   缩短或延长所拨号码的时间间隔
  	 			 P2_1=temp_0;																	;
				 clk_down();
	  			 P2_1=temp_0;
    			 P2_1=temp_1;
				 clk_down();
	  			 P2_1=temp_1;
				 P2_1=temp_2;
				 clk_down();
	 			 P2_1=temp_2;
				 P2_1=temp_3;
				 clk_down();
	  			 P2_1=temp_3;	
				 P2_1=temp_4;
				 clk_down();
	  			 P2_1=temp_4;
				 }
				 clk_up();
				 delay(100000);//缩短或延长拨号按键音
}

void dial_pause(void)		//中止DTMF波形
{	 for(i=0;i<10;i++) {
	  P2_1=1;																	;
	  clk_down();
	  P2_1=1;															
      P2_1=1;
	  clk_down();
	  P2_1=1;
	  P2_1=1;
	  clk_down();
	  P2_1=1;
	  P2_1=1;
	  clk_down();
	  P2_1=1;	
	  P2_1=1;
	  clk_down();
	  P2_1=1;
	  }
	  clk_up();
	  P1_7=1;	//CE			 
	 delay(100000);
}



void main(void)
{  
    init_serialcomm();
	init_interruptcomm();
    FREE_HAND=0;   //置低,前级电路运放
    PSTN_CIN=0;
    MAN_CIN=0;	
	  
	P3M0=0X98;	 	  //下面3句测试SM8200  P3M0=0X98;
 	P3M1=0X00;		//P3_7,P3_4,P3_3为输入,P3_5I/O
	P3_5=0;		

 	P1 = 0XFF;   //为响应中断作准备
	P2M0=0X10;	  //P2_4及HOOK_OFF_IN为高阻输入
	P2M1=0X00;

   while(1)
	{
	
		if(HOOK_OFF_IN==0){ 				//0下1上
	 		delay(4000000000);	
	 		if(HOOK_OFF_IN==1){ send_char_com('I');  }		 //话机弹起
		}		 
		if(HOOK_OFF_IN==1){ 
			
	 		delay(4000000000);	
	 		if(HOOK_OFF_IN==0){ send_char_com('H');}//话机按下
		}  
	
	 // scan();
	}  
	   	 
	  
}

⌨️ 快捷键说明

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