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

📄 编辑1.c

📁 38键小键盘程序,可以实现大小键盘的切换工作,并且接收命令和液晶显示
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <reg51.h>
#include <intrins.h>
#include <string.h>
#include  "Scod.h"

///////////////////////////////////////////////////////////////////
sbit DATA=P3^4;     //用p3.3做数据线控制口(小键盘)
sbit CLK =P3^2;     //用p3.2做时钟线控制口(小键盘)
sbit Key_Data=P3^5; //定义接受标准键盘引脚控制口(数据线)
sbit Key_CLK=P3^3;  //定义接受标准键盘引脚控制口(时钟线,外部中断1)
sbit inhibit=P1^3; //定义专用键盘和标准PS2键盘控制转换(P4.3)
///////////////////////////////////////////////////////////////////
sbit a1 = P1^1;     //用p4.1做语音控制口1
sbit a2 = P1^2;     //用p4.1做语音控制口2
//////////////////////////////////////////////////////////////////
sbit buzzer = P0^1;   //用p0.1做蜂鸣器控制口
//////////////////////////////////////////////////////////////////
sbit atxtflag  = P1^0; //用p4.0做AT/XT控制口(拨码开关)
sbit bit1_6flag = P3^6; //用p3.6做1bit/6bit清除控制口(拨码开关)
sbit numberflag = P3^7; //用p3.7做液晶显示数字和*号控制口(拨码开关)
//////////////////////液晶控制位及数据接口/////////////////////////
sbit LCM_RS=P2^5;
sbit LCM_RW=P2^6;//定义LCD引脚
sbit LCM_E =P2^7;
#define LCM_Data  P0
sbit Busy = P0^7; //用于检测LCM状态字中的Busy标识
//#define Busy   0x80 //用于检测LCD状态字中的Busy标识    
///////////////////////////////////////////////////////////////////
#define uchar unsigned char 
#define uint  unsigned int 
///////////////////////////////////////////////////////////////////
////////////////////////////键盘扫描定义///////////////////////////
sbit line1  P2^0;
sbit line2  P2^1;
sbit line3  P2^2;
sbit line4  P2^3;
sbit line5  P2^4;  //定义列线
sbit hang1  P1^0;
sbit hang2  P1^1;
sbit hang3  P1^2;
sbit hang4  P1^3;
sbit hang5  P1^4;
sbit hang6  P1^5;
sbit hang7  P1^6;
sbit hang8  P1^7; //定义行线

unsigned char keyvartab[8][5]={'A','B','C','D','E',
                               'F','G','H','I','J',
                               'K','L','M','N','O',
                               'P','Q','R','S','T',
                               '1','2','3','U','V',
                               '4','5','6','W','X',
                               '7','8','9',' ',' ',
                               '~','0','!','Y','Z'
                                };
////////////////////////////////////////////////////////////////////
void LCMInit(void);
unsigned char ReadStatusLCM(void);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);

void Delay5Ms(void);
void Delay400Ms(void);
void delay(unsigned  int N);
/////////////////////////////////////////////////////////////////////
void Decode(unsigned char ScanCode);
/////////////////////////////////////////////////////////////////////
void numbertocode(void);
void initkeyvariable(void);
unsigned char readkeyvar(void);
unsigned char parity(unsigned char x);
void SEND_byte(unsigned char byte_data);
/////////////////////////////////////////////////////////////////////
unsigned char code cdle_net[] = {"    WELCOME!    "}; 
unsigned char code email[] = {"we do our best!"};  //字符以ASCII码存储,不需要转换
unsigned char code Cls[] = {"                "};   //清显示
/////////////////////////////////////////////////////////////////////
static unsigned char IntNum = 0; //中断次数计数
static unsigned char KeyV; //键值
static unsigned char DisNum = 0; //显示用指针
static unsigned char Key_UP=0, Ctrl = 0;//Key_UP是键松开标识,Ctrl是Ctrl键按下标识
static unsigned char BF = 0; //标识是否有字符被收到
static unsigned char biaozhiflag = 0;//表示小键盘已经有键按下标志位
/////////////////////////////////////////////////////////////////////
/////////////////////////延时子函数开始//////////////////////////////
//5ms延时函数
void Delay5Ms(void)
{
	unsigned int TempCyc =5552;
	while(TempCyc--);
}
/////////////////////////////////////////////////////////////////////
//400ms延时函数
void Delay400Ms(void)
{
	unsigned char TempCycA = 5;
	unsigned int TempCycB;
	while(TempCycA--)
		{
			TempCycB=7269;
			while(TempCycB--);
		};
}
// 函数功能:延时子程序,实现(16*N+24)us的延时 
// 系统采用11.0592MHz的时钟时,延时满足要求,其它情况需要改动
void delay(unsigned  int N)  
{
  int i; 
  for(i=0;i<N;i++);
}
/////////////////////////延时子函数结束//////////////////////////////
/////////////////////////////////////////////////////////////////////
//////////////////////////1602-LCD驱动程序开始///////////////////////
//写数据函数
void WriteDataLCM(unsigned char WDLCM) 
{
	ReadStatusLCM(); //检测忙
	LCM_Data = (WDLCM&0xf0)|(P0&0x0f); 
	//LCM_Data = WDLCM;
	LCM_RS = 1;
	LCM_RW = 0;
	LCM_E = 1; //若晶振速度太高可以在这后加小的延时
	LCM_E = 0; //延时
	LCM_E = 0;
	LCM_Data = ((WDLCM<<4)&0xf0)|(P0&0x0f);
	LCM_RS = 1;
	LCM_RW = 0;
	LCM_E = 1; //若晶振速度太高可以在这后加小的延时
	LCM_E = 0; //延时
	LCM_E = 0; 

}
/////////////////////////////////////////////////////////////////////
//写指令函数
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
	if (BuysC) ReadStatusLCM(); //根据需要检测忙
	LCM_Data = (WDLCM&0xf0)|(P0&0x0f);
	//LCM_Data = WCLCM;
	LCM_RS = 0;
	LCM_RW = 0;	
	LCM_E = 1;
	LCM_E = 0;
	LCM_E = 0;	
	LCM_Data = ((WDLCM<<4)&0xf0)|(P0&0x0f);
	LCM_RS = 0;
	LCM_RW = 0;
	LCM_E = 1; //若晶振速度太高可以在这后加小的延时
	LCM_E = 0; //延时
	LCM_E = 0; 
}
/////////////////////////////////////////////////////////////////////
//读状态函数
unsigned char ReadStatusLCM(void)
{ 
	Busy = 1;
	//LCM_Data = 0xF0; 
	LCM_RS = 0;
	LCM_RW = 1;
	LCM_E = 1;
	LCM_E = 0;
	LCM_E = 0;
	while (Busy & 0x01); //检测忙信号
	//while (LCM_Data & Busy); //检测忙信号
	return(Busy);
}
/////////////////////////////////////////////////////////////////////
//初始化函数
void LCMInit(void) //LCM初始化
{
	LCM_Data = 0xff;
	Delay5Ms(); 
	WriteCommandLCM(0x30,0); //三次显示模式设置,不检测忙信号
	Delay5Ms(); 
	WriteCommandLCM(0x30,0);
	Delay5Ms(); 
	WriteCommandLCM(0x30,0);
	Delay5Ms(); 
	WriteCommandLCM(0x02,0);
	Delay5Ms(); 
	WriteCommandLCM(0x28,0); //三次显示模式设置,不检测忙信号
	Delay5Ms(); 
	WriteCommandLCM(0x28,0);
	Delay5Ms(); 
	WriteCommandLCM(0x28,0);
	Delay5Ms(); 

	WriteCommandLCM(0x28,1); //显示模式设置,开始要求每次检测忙信号
	//WriteCommandLCM(0x08,1); //关闭显示
	WriteCommandLCM(0x0C,1); //关闭显示
	WriteCommandLCM(0x01,1); //显示清屏
	WriteCommandLCM(0x06,1); // 显示光标移动设置
	WriteCommandLCM(0x0F,1); // 显示开及光标设置
}
/////////////////////////////////////////////////////////////////////
//按指定位置显示一个字符函数
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
	X |= 0x80; //算出指令码
	WriteCommandLCM(X, 1); //发命令字
	WriteDataLCM(DData); //发数据
}
/////////////////////////////////////////////////////////////////////
//按指定位置显示一串字符函数
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
	unsigned char ListLength;

  ListLength = 0;
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	while (DData[ListLength]!= '\0') //若到达字串尾则退出, zhao-(所以的字符码都大于(>0X19),字符串末为00,停止显示)
		{
			if (X <= 0xF) //X坐标应小于0xF
				{
					DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
					ListLength++;
					X++;
				}
		}
}
//////////////////////////1602-LCD驱动程序结束///////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////接收大键盘命令开始//////////////////////////////
//接收标准键盘扫描码命令函数
void Keyboard_out(void) interrupt 2
{
	if ((IntNum > 0) && (IntNum < 9))
		{			
			KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
			if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位
		}
	IntNum++;
	while (!Key_CLK); //等待PS/2CLK拉高

	if (IntNum > 10)
		{
			IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
			BF = 1; //标识有字符输入完了
			EA = 0; //关中断等显示完后再开中断 (注:如这里不用BF和关中断直接调Decode()则所Decode中所调用的所有函数要声明为再入函数)
		}
}
/////////////////////////////////////////////////////////////////////
//解码扫描码函数
void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
{
	unsigned char TempCyc,i,j;//secondrow_0bit_error,在移行时,第一行的第一位在第一次移行正确,以后总是不变(错误)
	unsigned char  secondrow_buf[16];

	if (!Key_UP)        //当键盘松开时,zhao-  (key_UP,shift,IntNum,DisNum,BF初值为0)
		{
			switch (ScanCode)
				{
					case 0xF0 :	// 当收到0xF0,Key_UP置1表示断码开始
						Key_UP = 1;
					break;
         if(atxtflag==1)
         	{
					  case 0x14 :	//  ATCtrl
						Ctrl = 1;
					}
					else
					{
						case 0x1D :	//  XTCtrl
						Ctrl = 2;
          }
          break;
					default:	
					 if(!Ctrl)	//如果Ctrl没按下
							{
							if(atxtflag==1)
							{		
							  //for (TempCyc = 0;(ATunshift[TempCyc][0]!=ScanCode)&&(TempCyc<48); TempCyc++); //查表显示
                   //UnShifted[TempCyc][0], 键值表,对应的显示字符,UnShifted[TempCyc][1]
								   // if(ATunshift[TempCyc][0] == ScanCode) 
							        // { 
							         	if((ScanCode==0x01)||(ScanCode==0x09)) 
							         		{
							         			a1 = 1;
        		                a1 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
							         		} 
 									        else if((ScanCode==0x78)||(ScanCode==0x07))
 									        {
 									        	a2 = 1;
        		                a2 = 0;
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms();   
													 }
											//  }//结束if(ATunshift[TempCyc][0] == ScanCode) 
							      }//结束if(atxtflag==1)							      
							  else
							  	{
							  	//for (TempCyc = 0;(XTunshift[TempCyc][0]!=ScanCode)&&(TempCyc<48); TempCyc++); //查表显示
                   //UnShifted[TempCyc][0], 键值表,对应的显示字符,UnShifted[TempCyc][1]
								    //if(XTunshift[TempCyc][0] == ScanCode) 
							         //{ 
							         	if((ScanCode==0x43)||(ScanCode==0x44)) 
							         		{
							         			a1 = 1;
        		                a1 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
							         		} 
 									        else if((ScanCode==0x57)||(ScanCode==0x58))
 									        {
 									        	a2 = 1;
        		                a2 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms();  
													 }	     
							         //} //结束 if(XTunshift[TempCyc][0] == ScanCode) 
							      } //结束if(atxtflag==0)
							    } //结束if(!Ctrl)	
						    else  //按下Ctrl
							    {
							    	if(Ctrl == 1)
							    	{	
							    			//for (TempCyc = 0;(ATaddshift[TempCyc][0]!=ScanCode)&&(TempCyc<6); TempCyc++); //查表显示
                        //UnShifted[TempCyc][0], 键值表,对应的显示字符,UnShifted[TempCyc][1]
								       // if(ATaddshift[TempCyc][0] == ScanCode) 
							          // { 
							         	  if((ScanCode==0x79)||(ScanCode==0x55)||(ScanCode==0x12)) 
							         		 {
							         			a1 = 1;
        		                a1 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
							         		 } 
 									         else if((ScanCode==0x7B)||(ScanCode==0x4E||(ScanCode==0x59)))
 									         {
 									        	a2 = 1;
        		                a2 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
													 }
											  // } //结束if(ATaddshift[TempCyc][0] == ScanCode) 
							        } //结束if(Ctrl == 1)
							        else if(Ctrl == 2)
							        {
							        	//for (TempCyc = 0;(XTaddshift[TempCyc][0]!=ScanCode)&&(TempCyc<6); TempCyc++); //查表显示
                        //UnShifted[TempCyc][0], 键值表,对应的显示字符,UnShifted[TempCyc][1]
								        //if(XTaddshift[TempCyc][0] == ScanCode) 
							          // { 
							         	  if((ScanCode==0x4E)||(ScanCode==0x0D)||(ScanCode==0x2A)) 
							         		 {
							         			a1 = 1;
        		                a1 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
							         		 } 
 									         else if((ScanCode==0x4A)||(ScanCode==0x0C)||(ScanCode==0x36))
 									         {
 									        	a2 = 1;
        		                a2 = 0;
        		                buzzer = 1;
        		                Delay5Ms();
        		                buzzer = 0;
        		                Delay5Ms(); 
        		                buzzer = 1;
        		                Delay5Ms(); 
        		                buzzer = 0;
        		                Delay5Ms(); 
													 }
											  // }//结束if(XTaddshift[TempCyc][0] == ScanCode)
							        } //结束if(Ctrl == 2)
							      } ////结束Ctrl按下
							      break;  
                 } //结束switch (ScanCode)
                 biaozhiflag = 1;
              }  //结束if (!Key_UP)
   else
   {	
			Key_UP = 0;
			switch (ScanCode) //当键松开时不处理判码
				{
					case 0x14 :	// ATCTRL编码
					Ctrl = 0;
					break;

					case 0x1D :	// XTCTRL编码
					Ctrl = 0;
					break;
				}
		 }
	BF = 0; //标识字符处理完了
} 
/////////////////////////接收大键盘命令处理完成//////////////////////
/////////////////////////////////////////////////////////////////////
// 函数名称: CAL_jiaoyan
// 函数功能: 计算校验位
//bit CAL_jiaoyan(unsigned char byte_data)
//{ 
//}
/////////////////////////////////////////////////////////////////////
//////////////////////////小键盘扫描驱动程序开始/////////////////////
//计算校验函数
unsigned char parity(unsigned char x)
{
  x^=x;
  if(P)return(1);
  else return(0);
}

/*unsigned char parity2(unsigned int x){
#pragma asm
  mov a,r7
  xrl ar6,a
#pragma endasm
  if(P)return(1);
  else return(0);
}*/
/////////////////////////////////////////////////////////////////////
//发送小键盘一个字节数据函数
void SEND_byte(unsigned char byte_data)
{
   unsigned char i,temp;
   if(CLK==0)       //时钟线为低
   temp=byte_data;
   CLK=1;
   DATA=0;
   delay(0);
   CLK=0;           //发送起始位
   for(i=0;i<8;i++)
   {
         delay(0);
         CLK=1;  
   DATA=(temp&0x01);  //发送数据
   byte_data=byte_data>>1;  
   delay(0);
   CLK=0; 
    }
   delay(0);
   CLK=1;  
   DATA=parity(temp); //发送校验位
   delay(0);
   CLK=0; 
   delay(0);
   CLK=1;  
   DATA=1;            //发送结束位
   delay(0);
   CLK=0;  
   }
///////////////////////////////////////////////////////////////////////////  
//初始化端口函数
void initkeyvariable(void)
{
   P1=0x00;
   //P1=0xFF;
   P2=0x00;
}
//获取键值函数
/*unsigned char readkeyvar(void)
{
   unsigned char i,j;
   unsigned char x;
   unsigned char x1;
   unsigned char key_date;
   key_date = P1;
   x = P2;
   key_date &= 0xff;
   if(key_date!=0xff)
    {
     {
     if(key_date==0xfe)x1=0;
     else if(key_date==0xfd)x1=1;
     else if(key_date==0xfb)x1=2;
     else if(key_date==0xf7)x1=3;
     else if(key_date==0x7f)x1=4;
     else if(key_date==0xbf)x1=5;
     else if(key_date==0xdf)x1=6;
     else if(key_date==0xef)x1=7;				
     else {return 0x20;}
     }
     P2 = 0x1f;
     x = P2; 
     x &= 0x1f;
     if(x!=0x1f)
     {
     if(x==0x1e)i=0;
     else if(x==0x1d)i=1;
     else if(x==0x1b)i=2;
     else if(x==0x17)i=3;
     else if(x==0x0f)i=4;				

⌨️ 快捷键说明

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