PC鼠标示例源代码: 1. 主文件: /*****************************Copyright (c)*************** ************;** 日期: 2005.5.10;** 描述: PC鼠标,本程序也通过调试,仅供参考。;** 实验内容: 利用点阵显示鼠标当前按下的按键和移动的方向与距离;** 适用机型: AT89S52********************************************************************/ #include "Com.h"#include "Display.h"/******************************************************* 名称: 初始化运行环境 功能: 初始化各寄存器与端口状态 参数: 无 返回值:无********************************************************/ void Init_device(void) { EA=1; EX1=1; //允许外部中断1 TL0=0xf0; //置定时器初值0x3CB0 中断时间为25ms TH0=0xd8; TMOD=0x01; //设定定时器/计数器0工作方式为1 ET0=0x01; //允许全局中断,允许定时器/计数器0溢出中断 PX1=1; //设置中断优先级 PT0=0; TR0=0x01; //启动定时器/计数器0 } /******************************************************* 名称: 主函数 功能: 应用程序入口 参数: 无 返回值:无*******************************************************/ void main(){ Init_device(); //调用初始化模块 Send_data(0xF4); //使能鼠标,允许鼠标发送数据 do{ }while(Temp_Buffer!=0xFA); ChoiceData(char_P); //显示鼠标点 while(1) { ProcessData(); //调用数据处理模块 } } 2. 头文件Com.h: /****************************Copyright (c)**************** *************;** 文件名: com.h;** 功能: 数据处理头文件,接收和处理鼠标发送到主机的数据;** 发送对鼠标的控制命令;** 包含头文件: at89x52.h 芯片功能模块定义 ********************************************************************/ #include <at89x52.h>/************************************************************/ sbit Data_Line=P3^5; //数据线P3_5 sbit Clock_Line=P3^3; //时钟线P3_3 /***********************定义位变量***************************/ unsigned char bdata Temp_Buffer; //接收字节 sbit D_Buf0=Temp_Buffer^0; //Temp_Buffer第0位 sbit D_Buf1=Temp_Buffer^1; sbit D_Buf2=Temp_Buffer^2; sbit D_Buf3=Temp_Buffer^3; sbit D_Buf4=Temp_Buffer^4; sbit D_Buf5=Temp_Buffer^5; sbit D_Buf6=Temp_Buffer^6; sbit D_Buf7=Temp_Buffer^7; //Temp_Buffer第7位0 /************************************************************/ unsigned char Buffer[11]; //接收位数据缓冲区 unsigned char Rec_ptr=0x00; //接收数据指针 unsigned char Rec_data=0xFF; //接收数据 unsigned char Data_Buf[3]; //接收鼠标数据缓冲区 unsigned char Buffer_ptr=0x00; //缓冲区指针 unsigned char Data_ptr=0; //数据处理指针 /******************************************************* 名称: 延时模块 功能: 软件延时 参数: unsigned int count 延时长度 返回值:无 *******************************************************/ void Delay(unsigned int count) { unsigned char j,k; unsigned int i; for(i=0;i<count;i++) for(j=0;j<10;j++) for(k=0;k<120;k++) ; } /******************************************************* 名称: 发送模块 功能: 发送一个字节的控制命令 参数: unsigned char dat 控制命令 返回值:无 *******************************************************/ //发送一个字符 void Send_data(unsigned char dat) { unsigned char ptr; TR0=0; //关闭定时器 EX1=0; //关闭外部中断1 ACC=dat; //将要发送的数据放入A寄存器 Clock_Line=0; //拉低时钟线 Delay(30); //延时100ms以上 Data_Line=0; //拉低数据线 Delay(2); Clock_Line=1; //释放时钟线 for(ptr=0;ptr<=7;ptr++) //低位在前,一次发送8个数据位 { do{ }while(Clock_Line==1); //等待设备释放时钟线 Data_Line=(dat>>ptr)&0x01; //发送数据位 do{ }while(Clock_Line==0); //等待设备拉低时钟线 } do{ }while(Clock_Line==1); Data_Line=~P; //发送校验位,奇校验 do{ }while(Clock_Line==0); do{ }while(Clock_Line==1); Data_Line=1; //发送停止位 do{ }while(Clock_Line==0); do{ }while(Clock_Line==1); do{ }while(Clock_Line==0); EX1=1; //打开外部中断1 TR0=1; //打开定时器中断 } /******************************************************* 名称: 奇偶校验模块 功能: 对接收到的数据进行奇偶校验 参数: 无 返回值:校验正确 1 校验错误 0 *******************************************************/ unsigned char Checkout(void) { ACC=Temp_Buffer; if(~P==Buffer[9]) return 1; else return 0; } /******************************************************* 名称: 组合数据模块 功能: 将接收到的数据为组合成数据 参数: 无 返回值:无 *******************************************************/ void CombinData(void) { /*********将接收到的各位赋值给Temp_Buffer对应的位***********/ D_Buf0=Buffer[1]; D_Buf1=Buffer[2]; D_Buf2=Buffer[3]; D_Buf3=Buffer[4]; D_Buf4=Buffer[5]; D_Buf5=Buffer[6]; D_Buf6=Buffer[7]; D_Buf7=Buffer[8]; /************************************************************/ if(Checkout()) //如果校验正确 { if(Data_ptr<=2) //将鼠标发送的3字节信号分别存入缓冲区 Data_Buf[Data_ptr++]=Temp_Buffer; else { Data_Buf[0]=Temp_Buffer; Data_ptr=1; } } } /******************************************************* 名称: 外部中断1服务程序 功能: 接收鼠标发送到主机的各个数据位 参数: 无 返回值:无 *******************************************************/ void ReceiveData(void) interrupt 0 { if(Rec_ptr<=10) { do{ }while(Clock_Line==0); //等待设备拉高时钟线 Buffer[Rec_ptr++]=Data_Line; //接收数据 } else { CombinData(); //组合接收到的数据 do{ }while(Clock_Line==0); //等待设备拉高时钟线 Buffer[0]=Data_Line; //接收数据 Rec_ptr=0x01; } } <!--[if !supportLists]-->3. <!--[endif]-->头文件pointdisplay.h: /***************************Copyright (c)***************** ************ ;** 文件名: pointdisplay.h ;** 功能: 点阵显示头文件,在点阵模块上显示图形 ;** 含头文件: intrins.h Keil内部函数头文件 ********************************************************************/ #include <intrins.h> /*******************点阵显示数据字符编码*****************************/ //鼠标移动点 const unsigned char code char_P[8]={0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00}; //鼠标左键被按下 const unsigned char code char_L[8]={0x00,0x24,0x14,0x8C,0x97,0xF4,0x94,0x84}; //鼠标中键被按下 const unsigned char code char_M[8]={0x00,0x3C,0x24,0xFF,0xFF,0x24,0x3C,0x00}; //鼠标右键被按下 Const unsigned char code char_R[8]={0x00,0x24,0x14,0xEC, 0xA7,0xA4,0xA4,0xE4}; //多个按键被按下 const unsigned char code char_S[8]={0xFF,0xFF,0xFF,0xE7,0xF7,0xFF,0xFF,0xFF}; //---------------------------------扫描位数组---------------------------------- const unsigned char Row_Control[8]={0xFE,0xFD,0xFB,0xF7, 0xEF,0xDF,0xBF,0x7F}; unsigned char send_data[8]; //发送数据缓冲区 //鼠标移动数据缓冲区 unsigned char move_data[8]={0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00}; unsigned char ptr_send=0x00; //发送数据指针 unsigned char ptr_con1=0x00; //扫描指针 unsigned char button_L; //左键标志 unsigned char button_R; //右键标志 unsigned char button_M; //中键标志 unsigned char length_X; //横向位移 unsigned char length_Y; //纵向位移 unsigned char flag_Y; //横向移动标志 左移为1,右移为0 unsigned char flag_X; //纵向移动标志 下移位1,上移为0 unsigned char X_Lmove; //横向左移距离 unsigned char Y_Umove; //横向右移距离 unsigned char X_Rmove; //纵向上移距离 unsigned char Y_Dmove; //纵向下移距离 /***********************定义位变量***************************/ unsigned char bdata BitData; //控制信息字节 sbit B_dat0=BitData^0; //BitData第0位 sbit B_dat1=BitData^1; sbit B_dat2=BitData^2; sbit B_dat3=BitData^3; sbit B_dat4=BitData^4; sbit B_dat5=BitData^5; sbit B_dat6=BitData^6; sbit B_dat7=BitData^7; //BitData第7位 /************************************************************/ /******************************************************* 名称: 显示数据模块 功能: 将要显示的数据送到点阵模块显示 P1_5 控制线 P1_6 数据线 P1_7 时钟线 参数: unsigned char s_bit 扫描列控制 unsigned char s_data 显示数据 返回值:无 *******************************************************/ void DisplayData(unsigned char s_bit,unsigned char s_data) { unsigned char m,n; P1_5=0x00; //拉低时钟线和控制线抑制发送 P1_7=0x00; for(m=0;m<=7;m++) //从低位到高位按位发送数据 { P1_6=(s_bit<<m)&0x80; P1_7=0x01; //拉高时钟线允许发送 P1_7=0x00; //拉低时钟线抑制发送 } for(n=0;n<=7;n++) { P1_6=(s_data<<n)&0x80; P1_7=0x01; P1_7=0x00; } P1_5=0x01; //拉高控制线将移位寄存器送点阵显示 P1_5=0x00; //拉底控制线锁存数据 } /******************************************************* 名称: 选取显示图形数据模块 功能: 选取显示图形对应的数据 参数: unsigned char *ptr 图形对应数组的数组名 返回值:无 *******************************************************/ void ChoiceData(unsigned char *ptr) reentrant { unsigned char temp; for(temp=0x00;temp<=0x07;temp++) { send_data[temp]=*(ptr+temp); } } /******************************************************* 名称: 取数模块 功能: 依次从数组中取出要显示的数据 参数: 无 返回值:unsigned char setdata 要显示的数据 *******************************************************/ unsigned char LeftSet(void) { unsigned char setdata; if(ptr_send<=7) { setdata=send_data[ptr_send]; ptr_send++; } else { setdata=send_data[0]; ptr_send=0x01; } return setdata; //返回取得的数据 } /******************************************************* 名称: 扫描控制模块 功能: 控制扫描的列 参数: 无 返回值:unsigned char setbit 当前扫描的列 *******************************************************/ unsigned char RowScan(void) { unsigned char setbit; if(ptr_con1<=7) { setbit=Row_Control[ptr_con1]; ptr_con1++; } else { setbit=Row_Control[0]; ptr_con1=0x01; } return setbit; //返回扫描的列 } /******************************************************* 名称: 移动控制模块 功能: 在点阵显示模块上移动显示数据 参数: 无 返回值:unsigned char mode 模块模式 0---左移 1---右移 2---上移 3---下移 unsigned char step 移动距离 *******************************************************/ void Move(unsigned char mode,unsigned char step) { unsigned char i,j; unsigned char temp[8]; for(i=0;i<=7;i++) //将要移动的数据放入移动缓冲区 send_data[i]=move_data[i]; switch(mode) { case 0: //左移 j=0; for(i=0;i<=7;i++) //保存显示数据 temp[i]=send_data[i]; for(i=0;i<=7-step;i++) //左移step位 send_data[i]=send_data[i+step]; for(i=8-step;i<=7;i++) //将移出的数据存回 send_data[i]=temp[j++]; break; case 1: //右移 j=8-step; for(i=0;i<=7;i++) temp[i]=send_data[i]; for(i=7;i>=step;i--) send_data[i]=send_data[i-step]; for(i=0;i<step;i++) send_data[i]=temp[j++]; break; case 2: //上移 for(i=0;i<7;i++) //将每列数据循环移动step位 send_data[i]=_cror_(send_data[i],step); break; case 3: for(i=0;i<7;i++) //下移 send_data[i]=_crol_(send_data[i],step); break; default: break; } for(i=0;i<=7;i++) //将移动后的数据放入移动数据缓冲区 move_data[i]=send_data[i]; } /******************************************************* 名称: 数据处理模块 功能: 处理接收到的数据 参数: 无 返回值:无 *******************************************************/ void ProcessData() { unsigned char temp; BitData=Data_Buf[1]; button_L=B_dat0; button_R=B_dat1; button_M=B_dat2; flag_X=B_dat4; flag_Y=B_dat5; length_X=Data_Buf[2]; length_Y=Data_Buf[0]; if(button_L+button_R+button_M==0) //没有键被按下 { ChoiceData(move_data); if(Data_Buf[0]+Data_Buf[2]!=0) //如果位移不为0 { if(flag_X) //左移 { temp=256-length_X; //取位移绝对值 X_Rmove+=temp/4; //每4个单位为1毫米,取位移毫米 if(flag_Y) //上移 { temp=256-length_Y; //取位移绝对值 Y_Dmove+=temp/4; //每4个单位为1毫米,取位移毫米 } else //下移 { Y_Umove+=length_Y/4; } } else //右移 { X_Lmove+=length_X/4; //每4个单位为1毫米,取位移毫米 if(flag_Y) { temp=256-length_Y; Y_Dmove+=temp/4; } else { Y_Umove+=length_Y/4; } } Data_Buf[0]=0; //清空位移 Data_Buf[2]=0; } } else //有键被按下 { if(button_L+button_M+button_R==1) { if(button_L==1) ChoiceData(char_L); //左键被按下 else if(button_R==1) ChoiceData(char_R); //右键被按下 else ChoiceData(char_M); //中键被按下 } else ChoiceData(char_S); //多个键被按下 } } /******************************************************* 名称: 定时器中断服务模块 功能: 显示图形 参数: 无 返回值:无 *******************************************************/ void TimerOver(void) interrupt 1 { DisplayData(RowScan(),LeftSet()); //显示点阵图形 if(X_Lmove>=1) //如果鼠标左移大于等于1毫米 { Move(1,1); //左移一个单位 X_Lmove=0; //清除左移长度 } if(X_Rmove>=1) //如果鼠标右移大于等于1毫米 { Move(0,1); X_Rmove=0; } if(Y_Umove>=1) //如果鼠标上移大于等于1毫米 { Move(2,1); Y_Umove=0; } if(Y_Dmove>=3) //如果鼠标下移大于等于1毫米 { Move(3,1); Y_Dmove=0; } TL0=0x78; //重置定时器初值0xFCB0 TH0=0xEC; }

评论