b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

利用st官网提供usb库的例程,改写鼠标光标的移动

电脑杂谈  发布时间:2021-02-01 05:02:35  来源:网络整理

前言:大多数stm32产品都带有USB2.0全速外设并提供USB开发库。我们可以使用开发库来开发一些USB设备,例如音频设备,大容量存储设备,打印机和人机界面设备等。PC之所以可以识别不同的插件设备,是因为USB已经开发了一套标准协议。插入USB设备后,主机将查询设备信息。查询设备信息后,主机本身查询匹配的驱动程序并加载该驱动程序。计算机中的应用程序可以使用该设备。下面将使用由st官方网站提供的usb库的例程来重写该例程以制作一个usb鼠标设备,并通过连接到stm32开发板的操纵杆控制鼠标光标的移动。

1.硬件设计:

鼠标模拟摇杆

接线图如上图所示。翘板传感器和MCU必须连接到同一电源3.3v。

2.软件设计:1.编程要点:

1.使用stm32标准库执行AD收集;通过检测操纵杆引脚的电压来获得操纵杆的运动。游戏杆的原理是在摇动时改变电位的电阻,从而改变电压。

2.使用USB开发库来了解官方项目例程。

首先,简要说明官方例程的项目文件。从官方网站下载资源并配置项目。您可以参考链接并选择JoyStickMouse项目以打开。尽管您看到许多文件,但其中许多文件都无法参与编译。结构如下:

鼠标模拟摇杆

模拟鼠标键盘控制其他窗口_鼠标模拟摇杆_安卓 手柄摇杆模拟鼠标

2.代码设计:

可以使用官方代码编译,但是硬件配置不是我们想要的,因此我们需要进行一些更改;首先,此官方例程是通过4个按钮模拟鼠标的上下,左右移动。固定移动一定距离;在MCU侧,鼠标的移动信息(例如x轴已移动了多少等)通过4个字节发送给主机,然后主机通过分析接收到的数据做出响应;实际上,每次数据传输时,主机发起查询时,单片机都会做出响应。

我们需要删除官方按钮部分,通过操纵杆传感器模拟鼠标的运动信息,然后首先通过ad电压检测操纵杆传感器,以检测4个方向的运动,然后发送响应数据给主机。

#ifndef __ADC_H
#define __ADC_H	
#include "platform_config.h"
#include 
/*
#define ADC_CH0  0 //通道0
#define ADC_CH1  1 //通道1
#define ADC_CH2  2 //通道2
#define ADC_CH3  3 //通道3
*/
void Adc_GPIO_Config(void); 
void Adc_Config(void);
#endif 

#include "adc.h"
volatile u16 ADC_ConvertedValue[10][3];
void Adc_GPIO_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
	/*使能GPIO和ADC1通道时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	  
 
	/*将PA0设置为模拟输入*/                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	/*将GPIO设置为模拟输入*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	/*将GPIO设置为模拟输入*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	/*将GPIO设置为模拟输入*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
}
void Adc_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure; 
	DMA_InitTypeDef DMA_InitStructure; 
	
	Adc_GPIO_Config();	
        /*72M/6=12,ADC最大时间不能超过14M*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);  
	
	/*将外设 ADC1 的全部寄存器重设为默认值*/
	ADC_DeInit(ADC1); 
        /*ADC工作模式:ADC1和ADC2工作在独立模式*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	
	/*模数转换工作在单通道模式*/
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;	
	/*模数转换工作在单次转换模式*/
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
        /*ADC转换由软件而不是外部触发启动*/	
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	
	/*ADC数据右对齐*/
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	
	/*顺序进行规则转换的ADC通道的数目*/
	ADC_InitStructure.ADC_NbrOfChannel = 3;	
	/*根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器*/   
	ADC_Init(ADC1, &ADC_InitStructure);	
 
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
        /*使能指定的ADC1*/
	ADC_Cmd(ADC1, ENABLE);	
	ADC_DMACmd(ADC1, ENABLE);
	/*重置指定的ADC1的校准寄存器*/
	ADC_ResetCalibration(ADC1);	
	/*获取ADC1重置校准寄存器的状态,设置状态则等待*/
	while(ADC_GetResetCalibrationStatus(ADC1));
	/*开始指定ADC1的校准*/
	ADC_StartCalibration(ADC1);		
        /*获取指定ADC1的校准程序,设置状态则等待*/
	while(ADC_GetCalibrationStatus(ADC1));		
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR); 
	DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&ADC_ConvertedValue; 
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 
	DMA_InitStructure.DMA_BufferSize = 30; 
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 
	DMA_InitStructure.DMA_Priority = DMA_Priority_High; 
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 
		
	DMA_Init(DMA1_Channel1, &DMA_InitStructure); 
	DMA_Cmd(DMA1_Channel1,ENABLE);
}

写完上面两个后,将它们复制到JoyStickMouse目录下的inc和src文件夹中。将adc.c文件和stm32f10x_adc.c添加到项目中,后者位于STM32_USB-FS-Device_Lib_V4.1. 0 \ Libraries \ STM32F10x_StdPeriph_Driver \ src下,因为官方例程不使用adc,因此它们不是在正式项目中添加了该文件。将c文件添加到项目中的操作如图所示,单击并找到要添加的文件:

鼠标模拟摇杆

	Adc_Config();	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);

到目前为止,已经配置了广告收集,PA。0、PA。1、PA.2的电压值将自动收集到ADC_ConvertedValue [10] [3]数组中,并收集10个值将一次为每个频道收集一次。取平均值。然后,下一步是删除官方例程的按钮配置,并根据ADC_ConvertedValue [10] [3]的值判断操纵杆的摇摆方向。

安卓 手柄摇杆模拟鼠标_鼠标模拟摇杆_模拟鼠标键盘控制其他窗口

 /*
  STM_EVAL_PBInit(Button_RIGHT, Mode_GPIO);
  STM_EVAL_PBInit(Button_LEFT, Mode_GPIO);
  STM_EVAL_PBInit(Button_UP, Mode_GPIO);
  STM_EVAL_PBInit(Button_DOWN, Mode_GPIO);
*/

    if ((JoyState() != 0) && (PrevXferComplete))
    {
         Joystick_Send(JoyState());
    }
替换为:
    if(PrevXferComplete){
        JoyState();//继续用原来已有的函数名,等一下找到该函数,更改里面的内容就行
    }				

PrevXferComplete是最后一次交互完成的标志。等到最后一次交互结束。将更改JoyState()函数,以检测操纵杆传感器的状态并发送状态信息,如下所示。

#if 0
uint8_t JoyState(void)
{
   //原来的代码 略...
}
#else //重新写JoyState函数
extern volatile u16 ADC_ConvertedValue[10][3]; 
u16 ConvertedValue[3];
void get_Average(void)//取平均值
{
    u8 i,j;
    int sum;
	
    for(i=0;i<3;i++){
        sum=0;
        for(j=0;j<10;j++){	
            sum+=ADC_ConvertedValue[j][i];
        }
        ConvertedValue[i]=sum/10;
    }
}
#define middle_x  0x07e2
#define middle_y  0x0813
#define idle_press 0x07cd
/*******************************************************************
    说明:采用的12位adc转换器,那么最大的转换值是0xFFF,对应的电压最大3.3v;
最小转换值是0,对应的电压为0v;所以电压值跟转换值的关系就很明显了,当然这里不
需要算出电压值。middle_x、middle_y、idle_press的值是摇杆静态的检测值,我特意
打印出来,可能不同的原件静态值有区别。它们的值大概是在0~0xFFF中间,上下摇动
控制一个电位器,左右摇动控制一个电位器,所以在静态的时候是检测到中间值是合理
的,然后判断检测值相对于静态检测值的的变化趋势可得知摇动的方向。
*********************************************************************/
uint8_t JoyState(void)
{
    uint8_t Mouse_Buffer[4] = {0, 0, 0, 0}; //Mouse_Buffer[4] 数据格式说明看下一段
    int8_t X = 0, Y = 0;
    uint8_t temp1,temp2;
    get_Average();
    /*计算X坐标的偏移*/
    temp1=(ConvertedValue[0]&0xF00)>>8;
    if(temp1<7){ //向左
        X=temp1-7;
    }else if(temp1>8){ //向右
	X=temp1-8;
    }
    /*计算Y坐标的偏移*/
    temp2=(ConvertedValue[1]&0xF00)>>8;
    if(temp2<7){ //向下
	Y=temp2-7;
    }else if(temp2>8){ //向上
	Y=temp2-8;
    }
    /*判断SW按键的状态*/	
    if(ConvertedValue[2]<0x200){
        Mouse_Buffer[0]=0x01; //鼠标的左键点击
    }
   /* prepare buffer to send */
    Mouse_Buffer[1] = X;
    Mouse_Buffer[2] = Y;
  
    /* Reset the control token to inform upper layer that a transfer is ongoing */
    PrevXferComplete = 0;
  
    /* Copy mouse position info in ENDP1 Tx Packet Memory Area*/
    USB_SIL_Write(EP1_IN, Mouse_Buffer, 4);
  
    /* Enable endpoint for transmission */
    SetEPTxValid(ENDP1);
    return 0;
}
#endif

设备发送到主机的信息存储在Mouse_Buffer [4]的四个字节中:

Mouse_Buffer [0]-

| --bit7〜bit3:

| --bit2:1表示按下了中间按钮

| --bit1:1表示右键单击并按

| --bit0:1表示按下了左按钮

Mouse_Buffer [1]-X坐标更改量,负数表示向左移动,正数表示向右移动。使用补码来表示变化量

Mouse_Buffer [2]-Y坐标更改量,负数表示向下移动,正数表示向上移动。使用补码来表示变化量

Mouse_Buffer [3]-滚轮发生变化,负数表示向上滚动,负数表示向下滚动

3.下载验证:

编译修改后的项目,连接J-LINK下载器,然后将程序刻录到开发板中;通过USB-mrico将开发板连接到计算机,计算机将自动识别设备并加载相应的设备。在等待一段时间后,摇动操纵杆以观察鼠标光标在移动,摇动越大,光标移动得越快;否则,速度较慢;摇操纵杆时无响应,检查线路连接是否良好;此外,操纵杆的静态广告转换值可以通过串行端口发送。当然,您需要配置usart外设,然后使用串行端口助手在计算机端接收该值。

遇到的问题:当未拔下J-LINK时,将USB-mrico连接到开发板时,无法识别开发板设备;我必须先拔掉J-LINK。原因暂时未知,可能是我的计算机原因。

到目前为止,自制鼠标设备已经完成;如果您想了解有关官方例程的更多信息,可以参考百度图书馆。

级别是有限的,仅供参考,希望您能就错误和不足之处向我提出建议。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-352289-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 魏安僖王
        魏安僖王

        1后一天蓝屏接近10次气死老子了

      • 曹文湛
        曹文湛

        打倒美帝国主义

      • 长长部澪
        长长部澪

        我就放心了

      热点图片
      拼命载入中...