USB鼠标的实现(实验第六讲)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
.
12
主要代码完成了,下面完善一些细节
USB鼠标的实现
实验第六讲
.
1
前言
在前面的实验中,我们已经完成了一个USB 鼠标的枚举过程,但是我们自制的这个设备 目前还无法真正实现一个鼠标的功能
在这次实验中,我们完成要实现这个鼠标的 最后一些步骤
.
2
鼠标的实现原理(按键驱动部分)
在这个USB鼠标中,我们用开发板上面的8个 按键模拟鼠标的各个功能,实现鼠标的移动 和按键的单击与双击
按键的驱动属于单片机的内容,代码随课件 一起提供给大家,文件名为KEY.C和KEY.H
按键驱动通过几个全局变量将按键事件提供给 其它函数使用
.
3
鼠标的实现(报告部分)
上次实验中,我们知道,HID设备是通过报告来和主 机交互数据
例如当我们的鼠标发生了一个事件,比如左键单击, 那么就需要向主机发送一个报告
//我们不需要KEY1~KEY6按键改变的信息,所以先将它们清0 KeyUp &=~(KEY1|KEY2|KEY3|KEY4|KEY5|KEY6); KeyDown &=~(KEY1|KEY2|KEY3|KEY4|KEY5|KEY6);
//如果有按键按住,并且不是KEY7、KEY8(左、右键) //或者KEY7、KEY8任何一个键有变动的话,则需要返回报告
if(ConfigValue!=0) //如果已经设置为非0的配置,则可以返回报告数据 { if(!Ep1InIsBusy) //如果端点1输入没有处于忙状态,则可以发送数据 { KeyCanChange=0; //禁止按键扫描 if(KeyUp||KeyDown||KeyPress) //如果有按键事件发生 { SendReport(); //则返回报告 } KeyCanChange=1; //允许按键扫描 } }
.
10
if((KeyPress&(~(KEY7|KEY8)))||KeyUp||KeyDown) { if(KeyPress & KEY1) //如果KEY1按住,则光标需要左移,即X轴为负值。 { Buf[1]=-1; //这里一次往左移动一个单位。 } if(KeyPress & KEY2) //如果KEY2按住,则光标需要右移,即X轴为正值。 { Buf[1]=1; //这里一次往右移动一个单位。 } if(KeyPress & KEY3) //如果KEY3按住,则光标需要上移,即Y轴为负值。 { Buf[2]=-1; //这里一次往上移动一个单位。 } if(KeyPress & KEY4) //如果KEY4按住,则光标需要下移,即Y轴为正值。 { Buf[2]=1; //这里一次往下移动一个单位。 } if(KeyPress & KEY5) //如果KEY5按住,则滚轮下滚,即滚轮值为负。 { Buf[3]=-1; //这里一次往下滚动一个单位。 }
.
6
在复位中断处理中添加对标志的重 置语句
void UsbBusReset(void) { #ifdef DEBUG0 Prints("USB总线复位。\r\n"); #endif Ep1InIsBusy=0; //复位后端点1输入缓冲区空闲。 }
.
7
在main.c里面,主循环体中,判断有中断发生后,增加 一个判断是否返回报告
.
11
if(KeyPress & KEY6) //如果KEY6按住,则滚轮上滚,既滚轮值为正 { Buf[3]=1; //这里一次往上滚动一个单位。 } if(KeyPress & KEY7) //鼠标左键 { Buf[0]|=0x01; //D0为鼠标左键 } if(KeyPress & KEY8) //鼠标右键 { Buf[0]|=0x02; //D1为鼠标右键 } //报告准备好了,通过端点1返回,长度为4字节。 D12WriteEndpointBuffer(3,4,Buf); Ep1InIsBusy=1; //设置端点忙标志。 } //记得清除KeyUp和KeyDown KeyUp=0; KeyDown=0; }
按照上次课程中写的报告描述符的规范,这个报告 是4个字节
第一字节的低3位用来表示按键是否按下 第二字节表示X轴的改变量 第三字节表示Y轴的改变量 第四字节表示滚轮的改变量
.
4
当设备需要向主机传送数据时,我们需要准备好一 个报告并且将它发送出去
报告不是随时都能返回的,只有在设置非0配置之 后,才能将数据写到端点1中返回,如何知道已经进 行设备配置了呢?可以增加一个变量ConfigValue, 初始化为0,在收到设置配置请求后,将配置值赋 给它,如果是非0的配置,就可以返回报告了
.
8
下面我们编写一个SendReport()函数来实 现发送报告这个功能,这个函数放在main.c 文件里面
SendReport()函数根据当前的按键情况来 返回报告,当前的按键情况由我们在KEY.C 中定义的几个全局变量确定
.
9
SendReport()函数代码
void SendReport(void) { //需要返回的4字节报告的缓冲 //Buf[0]的D0就是左键,D1就是右键,D2就是中键(这里没有) //Buf[1]为X轴,Buf[2]为Y轴,Buf[3]为滚轮 uint8 Buf[4]={0,0,0,0};
发送报告到端点1之前,需要检查端点1是否处于忙 状态,即里面是否有数据未发送出去.为此增加一个 Ep1InIsBusy的标志,来决定端点1输入缓冲是否空 闲.设备复位后,Ep1InIsBusy置为0
.
Biblioteka Baidu
5
根据Ep1InIsBusy的要求将端点1输 入中断处理函数完善
void UsbEp1In(void) { #ifdef DEBUG0 Prints("USB端点1输入中断。\r\n"); #endif //读最后发送状态,这将清除端点1输入的中断标志位 D12ReadEndpointLastStatus(3); //端点1输入处于空闲状态 Ep1InIsBusy=0; }