由于JoyStickMouse例程是与官方评估板配套的,与我们设计的开拓板引脚的定义有可能不一样,以是才会导致PC鼠标无法正常受开拓板按键的掌握。如果你想将厂家发布的例程运用到自己的开拓平台上,必须按照引脚的定义进行相应修正。那么详细该当修正哪些地方呢?我们前辈入main主函数,初步理解一下JoyStickMouse例程的代码实行流程,相应的源代码如清单9.1所示。
清单9.1 main主函数

main主函数一开始调用了几个初始化函数(暂时不用理会,后续会详细讲解)后,就进入了while去世循环。个中,Joystick_Send函数实现给主机发送数据的功能,而是否发送数据则取决于JoyState函数的返回值以及PreXferComplete变量(后述)。JoyState函数用来获取轻触按键的状态,它的详细实现在hw_config.c源文件中,相应的源代码如清单9.2所示,相应的hw_config.h头文件如清单9.3所示。
\r\r清单9.2 JoyState函数
\r\r \r\r \r\r清单9.3 hw_config.h头文件
\r\r \r\r从清单9.2中可以看到,JoyState函数内部利用预编译指令定义了不同平台对应的按键读取代码,如果你定义了USE_STM32373C_EVAL或USE_STM32303C_EVAL宏,编译器会编译所有#else分支后面的语句,相反则编译if分支后面的语句。前面已经提过,JoyStickMouse例程只定义了宏USE_STM3210B_EVAL,因此编译器会编译所有#if分支语句。为方便读者更轻松地进行源代码阅读,本书后续均删除源代码中不会被实行的预处理指令,整理后的JoyState函数如清单9.4所示(为节省篇幅,代码须要修正的地方会提示在注释部分,后续会详述详细的修正方法)。
\r\r清单9.4 整理后的JoyState函数
\r\r \r\rButton_RIGHT、Button_LEFT、Button_UP、Button_DOWN分别用来唯一标识某个按键,它们被定义在stm32_eval_legacy.h头文件(所有适配层都会包含该头文件),如清单9.5所示。
\r\r清单9.5 stm32_eval_legacy.h头文件(部分)
\r\r \r\r从清单9.5中可以看到,前述4个按键标识符又分别被定义为BUTTON_RIGHT、BUTTON_LEFT、BUTTON_UP、BUTTON_DOWN,它们被声明在适配层stm3210b_eval.h头文件中,相应的源代码如清单9.6所示。
\r\r清单9.6 stm3210b_eval.h头文件(部分)
\r\r \r\r \r\r \r\r从清单9.6中可以看到,上、下、左、右4个按键分别被授予了唯一的数字进行标记,并且以列举常量的办法被定义,清单9.4中的STM_EVAL_PBGetState函数则根据传入的唯一数字进行相应按键状态的读取与返回操作,该函数被定义在stm3210b_eval.c源文件中,相应的源代码如清单9.7所示。
\r\r清单9.7 stm3210b_eval.c源文件(部分)
\r\r \r\r \r\r \r\r从清单9.7中可以看到,STM_EVAL_PBGetState函数中调用了读取引脚位状态的GPIO_ReadInputDataBit函数,须要传入后者的“GPIO外设基地址与引脚位信息”被统一保存在数组BUTTON_PORT与BUTTON_PIN中。也便是说,适配层将所有利用到的GPIO外设基地址、引脚位、总线时钟、中断线等信息都定义为宏,然后用数组将这些信息分类存储(例如,数组BUTTON_PORT用于保存GPIO外设基地址。数组BUTTON_PIN用于保存引脚位,数组BUTTON_CLK用于保存总线时钟掌握位,数组BUTTON_EXTI_LINE用于保存引脚对应的中断线,其他以此类推),这样就可以利用唯一标识符从不同数组中得到某个引脚的所有信息。我们以Button_Right为例给出了相应按键引脚信息的获取流程,如图9.1所示。
\r\r \r\r图9.1 Button_Right对应的引脚获取流程
\r\r也便是说,官方例程中实现右移功能的按键对应单片机的引脚PE0。相应地,我们也可以查到上、下、左移按键对应的引脚分别为PD8、PD14、PE1。由于这4个引脚都不在我们方案的IO引脚中(见表4.2),以是目前开拓板掌握PC鼠标的功能是不正常的。
\r\r我们自己的开拓板上有7个按键可供给用,假设现在决定利用K1~K4分别实现下、右、左、上移的功能,相应的引脚方案如图9.2所示。在源代码方面,首先须要将清单9.6中4个按键干系信息的宏定义按注释后面的语句修正。当然,有些宏定义并没有利用到(如中断线、中断源等),但为了源代码的完全性,我们仍旧给出了所有的修正语句。
\r\r还有什么地方须要修正呢?我们再次回到JoyState函数中,第一条if语句是读取“右移”按键的状态,并且加了一个“非”逻辑运算符,这意味着:官方评估板配套的游戏杆按键是低有效的(空闲状态下为高电平)。那么理论上,官方例程该当会将按键干系的引脚初始化为“上拉输入”模式(如果评估板已经外接了上拉电阻,也可以初始化为“悬空输入”模式),这一点我们可以通过剖析main主函数中的Set_System函数来验证,相应的源代码如清单9.8所示。
\r\r \r\r图9.2 引脚方案
\r\r清单9.8 Set_System函数
\r\r \r\r我们只须要关注个中调用的STM_EVAL_PBInit函数(其定义见清单9.7),它根据指定的按键唯一标识符与配置模式(Mode_GPIO代表普通引脚,Mode_EXTI代表外部中断输入,其定义见清单9.5)进行初始化。详细来讲,从函数一开始就通过前述数组查找的办法,使能了指定引脚对应GPIO外设的总线时钟,并且将它们设置为“悬空输入”模式,这也就意味着:官方评估板上的按键均有额外的上拉电阻(其他语句只有在将GPIO设置初始化为外部中断输入时利用到,暂时可不予理会)。
\r\r由于我们开拓板上的按键采取高有效的办法连接(默认为低电平),而且没有外接下拉电阻,以是还须要做两件事。其一,该当在清单9.7的STM_EVAL_PBInit函数中将引脚模式初始化为下拉输入模式(GPIO_Mode_IPD),这样才能够使所有按键在初始化后就坚持低电平(空闲状态)。其二,该当将JoyState函数(清单9.4)中所有if语句中的非逻辑运算符“!
”去掉。这也就意味着在空闲状态(低电平)下,JoyState函数将返回状态0,也就相称于关照运用程序:此时没有按键被按下。如果不修正判断逻辑,就会涌现前述体验游戏操纵杆设备时“PC鼠标总会不受控地往右移”的征象,由于在原来的逻辑下,空闲状态(低电平)是有效电平,而JoyState函数读取到第一个右移按键有效后就直接返回(不再实行剩下的代码),以是PC鼠标才会一贯右移。
总体上,如果利用自己的STM32单片机开拓板实现JoyStickMouse例程,则须要确认以下三点。其一,变动数组BUTTON_PORT与BUTTON_PIN中各引脚信息的详细定义(其他是可选的);其二,对按键的输入引脚进行初始化,使它们默认处于无效状态(也便是变动STM_EVAL_PBInit函数中引脚的初始化模式),详细取决于开拓板上的按键连接办法;其三,变动JoyState函数中止定读取状态的逻辑(高电平还是低电平有效)。当然,纵然利用的开拓平台并不是基于STM32单片机,这三点同样也是成功实现官方例程的修正思路。
\r\r当按照前述三点变动之后,再重新编译项目并将STM3210B-EVAL.hex文件下载到开拓板中,你就可以通过按键K1~K4正常掌握PC鼠标移动方向了,是不是很大略。恭喜!
你人生中的第一个USB设备已经开拓完成了!