OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2067|回复: 0

《STM32F407 探索者开发指南》第六十七章 USB鼠标键盘(Host)实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2023-9-28 18:08:44 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-9-28 18:08 编辑

第六十七章 USB鼠标键盘(Host)实验
1)实验平台:正点原子探索者STM32F407开发板

2) 章节摘自【正点原子】STM32F407开发指南 V1.1

3)购买链接:https://detail.tmall.com/item.htm?id=609294673401

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/stm32/zdyz_stm32f407_explorerV3.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)STM32技术交流QQ群:151941872

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章我们介绍如何使用STM32F407的USB HOST来驱动USB鼠标/键盘。
本章分为如下几个小节:
67.1 USB鼠标键盘简介
67.2 硬件设计
67.3 程序设计
67.4 下载验证

67.1 USB鼠标键盘简介
传统的鼠标和键盘是采用PS/2接口和电脑通信的,但是现在PS/2接口在电脑上逐渐消失,所以现在越来越多的鼠标键盘采用的是USB接口,而不是PS/2接口的了。

USB鼠标键盘属于USB HID设备。USB HID即:Human Interface Device(人机交互设备)的缩写,键盘、鼠标与游戏杆等都属于此类设备。不过HID设备并不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。关于USB HID的知识,我们这里就不详细介绍了,请大家自行百度学习。

我们直接移植官方的USB HID例程,官方例程路径:8,STM32参考资料 à 1,STM32CubeF4固件包 à STM32Cube_FW_F4_V1.26.0à Projects à STM324xG_EVALà Applications à USB_Host à HID_Standalone,该例程支持USB鼠标和键盘等USB HID设备,本章我们将移植这个例程到我们的开发板上。

67.2 硬件设计
1. 例程功能
本实验代码,开机的时候先显示一些提示信息,然后初始化USB HOST,并不断轮询。当检测到USB鼠标/键盘的插入后,显示设备类型,并显示设备输入数据:
如果是USB鼠标:将显示鼠标移动的坐标(X,Y坐标),滚轮滚动数值(Z坐标)以及按键(左中右)。
如果是USB键盘:将显示键盘输入的数字/字母等内容(不是所有按键都支持,部分按键没有做解码支持,比如F1~F12)。

2. 硬件资源
1)LED灯
    LED0 – PF9
LED1 – PF10
2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)
3)正点原子2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
4)norflash(本例程使用的是W25Q128,连接在SPI1)
5)外部SRAM芯片,通过FSMC驱动
6)USB_HOST接口(D-/D+连接在PA11/PA12上)

67.3 程序设计
67.3.1 程序流程图
                              
image002.png
图67.3.1.1 USB鼠标键盘实验(Host)程序流程图

67.3.2 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。

本实验,我们在上一个实验的基础上修改,对照官方HID例子,然后,我们在工程里面添加USB HID相关代码,如图67.3.2.1所示:     
image003.png
图67.3.2.1 USB鼠标键盘工程分组

上图工程分组中的Middlewares/USB_CORE和Middlewares/USB_CLASS分组下的.c文件,直接拷贝ST官方USB HOST库。我们重点介绍下USB_APP里面的usbh_hid_mouse.c和usbh_processs文件,usbh_process文件是我们自己写的demo文件,usbh_hid_mouse.c文件拷贝自ST官方例程,但是ST官方例程对鼠标的支持不好(兼容性差,不支持滚轮等),我们重写了该文件,下面介绍这两个文件和main.c。

1. USB驱动代码
usbh_hid_mouse.h,首先介绍usbh_hid_mouse.h里面定义的一个结构体,具体如下:
  1. /* 鼠标信息结构体*/
  2. typedef struct _HID_MOUSE_Info
  3. {
  4.   uint8_t             x;            /* x轴增量(强制转换成signed char后使用)*/
  5.   uint8_t             y;            /* y轴增量(强制转换成signed char后使用)*/
  6.   uint8_t             z;            /* z轴增量(强制转换成signed char后使用)*/
  7.   uint8_t             button;      /* 将buttons修改为button, 存储按键状态 */
  8. }
  9. HID_MOUSE_Info_TypeDef;
复制代码
HID_MOUSE_Info_TypeDef结构体中,成员x和y表示鼠标的横向/纵向移动的增量值,成员z表示鼠标的滚轮的滚动增量值。button的bit0、bit1、bit2分别表示鼠标的:左键、右键和滚轮键的按下状态。我们通过这个结构体,就可以获得当前鼠标的输入状态。

usbh_hid_mouse.c,总共有三个函数,首先介绍的是USBH鼠标初始化函数,其定义如下:
  1. /* 鼠标信息(坐标+按钮状态)*/
  2. HID_MOUSE_Info_TypeDef    mouse_info;
  3. /* 鼠标上报数据长度,最多HID_QUEUE_SIZE个字节*/
  4. uint8_t mouse_report_data[HID_QUEUE_SIZE];
  5. /**
  6. *@brief        USBH 鼠标初始化
  7. *@param        phost            :USBH句柄指针
  8. *@retval       USB状态
  9. *  @arg        USBH_OK(0)      , 正常;
  10. *  @arg        USBH_BUSY(1)    , 忙;
  11. *  @arg        其他              , 失败;
  12. */
  13. USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost)
  14. {
  15.    HID_HandleTypeDef *HID_Handle =
  16. (HID_HandleTypeDef *) phost->pActiveClass->pData;
  17.    mouse_info.x = 0;
  18.    mouse_info.y = 0;
  19.    mouse_info.button = 0;
  20.     if (HID_Handle->length > sizeof(mouse_report_data))
  21.     {
  22.        HID_Handle->length = sizeof(mouse_report_data);
  23.     }
  24.    HID_Handle->pData = (uint8_t *)mouse_report_data;
  25.    USBH_HID_FifoInit(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE);
  26.     return USBH_OK;
  27. }
复制代码
USBH_HID_MouseInit函数,用于初始化鼠标,指定USB鼠标输出数据的缓存,初始化FIFO等,该函数在USBH_HID_Process函数里面被调用。

接下来介绍的是USBH获取鼠标信息函数,其定义如下:
  1. /**
  2. *@brief        USBH 获取鼠标信息
  3. *@param        phost       : USBH句柄指针
  4. *@retval       鼠标信息(HID_MOUSE_Info_TypeDef)
  5. */
  6. HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost)
  7. {
  8.     if (USBH_HID_MouseDecode(phost) == USBH_OK)
  9.     {
  10.        return &mouse_info;
  11.     }
  12.     else
  13.     {
  14.        return NULL;
  15.     }
  16. }
复制代码
USBH_HID_GetMouseInfo函数,用于获取鼠标信息,通过USBH_HID_MouseDecode函数获取当前鼠标传回来的数据。该函数在USB_Demo函数里面被调用。

最后介绍的是USBH 鼠标数据解析函数,其定义如下:
  1. /**
  2. *@brief        USBH 鼠标数据解析函数
  3. *@param        phost            :USBH句柄指针
  4. *@retval       USB状态
  5. *  @arg        USBH_OK(0)      , 正常;
  6. *  @arg        USBH_BUSY(1)    , 忙;
  7. *  @arg        其他              , 失败;
  8. */
  9. USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost)
  10. {
  11. HID_HandleTypeDef *HID_Handle =
  12. (HID_HandleTypeDef *) phost->pActiveClass->pData;
  13.     if (HID_Handle->length == 0)return USBH_FAIL;
  14. if (USBH_HID_FifoRead(&HID_Handle->fifo, &mouse_report_data,
  15. HID_Handle->length) == HID_Handle->length) /* 读取FIFO */
  16.     {
  17.        mouse_info.button =mouse_report_data[0];
  18.        mouse_info.x       = mouse_report_data[1];
  19.        mouse_info.y       = mouse_report_data[2];
  20.        mouse_info.z       = mouse_report_data[3];
  21.        return USBH_OK;
  22.     }
  23.     return   USBH_FAIL;
  24. }
复制代码
USBH_HID_MouseDecode函数,用于解析USB HOST获取到的USB鼠标数据,并存放到mouse_info结构体里面。该函数被USBH_HID_GetMouseInfo函数调用。

2. usbh_process.c代码
  1. USBH_HandleTypeDef hUSBHost;   /* USB Host处理结构体 */
  2. /* 应用状态结构体类型定义 */
  3. typedef enum
  4. {
  5.    APPLICATION_IDLE = 0,        /* 挂起状态 */
  6.    APPLICATION_DISCONNECT,      /* 断开连接 */
  7.    APPLICATION_START,           /* 应用开始(连接上了) */
  8.    APPLICATION_READY,           /* 准备完成(可以执行相关应用代码了) */
  9.    APPLICATION_RUNNING,         /* 运行中 */
  10. }HID_ApplicationTypeDef;
  11. extern HID_MOUSE_Info_TypeDef mouse_info;
  12. HID_ApplicationTypeDef App_State = APPLICATION_IDLE;
  13. uint8_t g_usb_first_plugin_flag = 0; /* USB第一次插入标志,如果为1,说明是第一次插入 */
  14. /**
  15. *@brief        USB信息显示
  16. *@param        msg     : 信息类型
  17. *  @arg                  0, USB无连接
  18. *  @arg                  1, USB键盘
  19. *  @arg                  2, USB鼠标
  20. *  @arg                  3, 不支持的USB设备
  21. *@retval       无
  22. */
  23. voidusbh_msg_show(uint8_t msgx)
  24. {
  25.     switch (msgx)
  26.     {
  27.        case 0:  /* USB无连接 */
  28.            lcd_show_string(30, 130, 200, 16, 16, "USBConnecting...", RED);
  29.            lcd_fill(0, 150, lcddev.width, lcddev.height, WHITE);
  30.            break;
  31.        case 1:  /* USB键盘 */
  32.            lcd_show_string(30, 130, 200, 16, 16, "USB Connected    ", RED);
  33.            lcd_show_string(30, 150, 200, 16, 16, "USBKeyBoard", RED);
  34.            lcd_show_string(30, 180, 210, 16, 16, "KEYVAL:", RED);
  35.            lcd_show_string(30, 200, 210, 16, 16, "INPUTSTRING:", RED);
  36.            break;
  37.        case 2:  /* USB鼠标 */
  38.            lcd_show_string(30, 130, 200, 16, 16, "USBConnected    ", RED);
  39.            lcd_show_string(30, 150, 200, 16, 16, "USBMouse", RED);
  40.            lcd_show_string(30, 180, 210, 16, 16, "BUTTON:", RED);
  41.            lcd_show_string(30, 200, 210, 16, 16, "XPOS:", RED);
  42.            lcd_show_string(30, 220, 210, 16, 16, "YPOS:", RED);
  43.            lcd_show_string(30, 240, 210, 16, 16, "ZPOS:", RED);
  44.            break;
  45.        case 3:  /* 不支持的USB设备 */
  46.            lcd_show_string(30, 130, 200, 16, 16, "USBConnected    ", RED);
  47.            lcd_show_string(30, 150, 200, 16, 16, "UnknowDevice", RED);
  48.            break;
  49.     }
  50. }
  51. /**
  52. *@brief        完成USBH不同用户状态下的数据处理
  53. *@param        phost   : USBH句柄指针
  54. *@param        id       : USBH当前的用户状态
  55. *@retval       无
  56. */
  57. voidUSBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id)
  58. {
  59.     uint8_t dev_type = 0xFF;     /* 设备类型,1,键盘;2,鼠标;其他,不支持的设备 */
  60.     switch (id)
  61.     {
  62.        caseHOST_USER_SELECT_CONFIGURATION:
  63.            break;
  64.        caseHOST_USER_DISCONNECTION:
  65.            usbh_msg_show(0);     /* 显示已经断开连接,准备重新连接 */
  66.            App_State = APPLICATION_DISCONNECT;
  67.            break;
  68.        caseHOST_USER_CLASS_ACTIVE:
  69.            App_State = APPLICATION_READY;
  70.            dev_type = phost->device.CfgDesc.Itf_Desc[phost->
  71.                                          device.current_interface].bInterfaceProtocol;
  72.            if (dev_type ==HID_KEYBRD_BOOT_CODE)         /* 键盘设备 */
  73.            {
  74.                 g_usb_first_plugin_flag = 1;              /* 标记第一次插入 */
  75.                 usbh_msg_show(1);                         /* 显示键盘界面 */
  76.            }
  77.            else if (dev_type ==HID_MOUSE_BOOT_CODE)    /* 鼠标设备 */
  78.            {
  79.                 g_usb_first_plugin_flag = 1;              /* 标记第一次插入 */
  80.                 usbh_msg_show(2);                         /* 显示鼠标界面 */
  81.            }
  82.            else
  83.            {
  84.                 usbh_msg_show(3);                         /* 显示不支持 */
  85.            }
  86.            
  87.            break;
  88.        caseHOST_USER_CONNECTION:
  89.            App_State = APPLICATION_START;
  90.            break;
  91.        default:
  92.            break;
  93.     }
  94. }
  95. /* 临时数组,用于存放鼠标坐标/键盘输入内容(4.3屏,最大可以输入2016字节) */
  96. #if !(__ARMCC_VERSION >= 6010050)   /* 不是AC6编译器,即使用AC5编译器时 */
  97. __align(4) uint8_t g_temp_buffer[2017];
  98. #else     /* 使用AC6编译器时 */
  99. __ALIGNED(4) uint8_t g_temp_buffer[2017];
  100. #endif
  101. /**
  102. *@brief        USB鼠标数据处理
  103. *@param        data  : USB鼠标数据结构体指针
  104. *@retval       无
  105. */
  106. voidmouse_data_process(HID_MOUSE_Info_TypeDef *data)
  107. {
  108.     static signed short x, y, z;
  109.     if (g_usb_first_plugin_flag)    /* 第一次插入,将数据清零 */
  110.     {
  111.        g_usb_first_plugin_flag = 0;
  112.        x = y = z = 0;
  113.     }
  114.     x += (signed char)data->x;
  115.     if (x > 9999)
  116.     {
  117.        x = 9999;
  118.     }
  119.     if (x < -9999)
  120.     {
  121.        x = -9999;
  122.     }
  123.     y += (signed char)data->y;
  124.     if (y > 9999)
  125.     {
  126.        y = 9999;
  127.     }
  128.     if (y < -9999)
  129.     {
  130.        y = -9999;
  131.     }
  132.     z += (signed char)data->z;
  133.     if (z > 9999)
  134.     {
  135.        z = 9999;
  136.     }
  137.     if (z < -9999)
  138.     {
  139.        z = -9999;
  140.     }
  141.    sprintf((char *)g_temp_buffer, "BUTTON:");
  142.     if (data->button & 0x01)
  143.     {
  144.        strcat((char *)g_temp_buffer, "LEFT ");
  145.     }
  146.     if ((data->button & 0x03) == 0x02)
  147.     {
  148.        strcat((char *)g_temp_buffer, "RIGHT");
  149.     }
  150.     else
  151.     {
  152.        if ((data->button & 0x03) == 0x03)
  153.        {
  154.            strcat((char *)g_temp_buffer,"+RIGHT");
  155.        }
  156.     }
  157.    
  158.     if ((data->button & 0x07) == 0x04)
  159.     {
  160.        strcat((char *)g_temp_buffer, "MID  ");
  161.     }
  162.     else
  163.     {
  164.        if ((data->button & 0x07) > 0x04)
  165.        {
  166.            strcat((char *)g_temp_buffer, "+MID");
  167.        }
  168.     }
  169.    
  170.    lcd_fill(30 + 56, 180, lcddev.width - 1, 180 + 16, WHITE);
  171.    lcd_show_string(30, 180, 210, 16, 16, (char *)g_temp_buffer, BLUE);
  172.    sprintf((char *)g_temp_buffer, "XPOS:%05d", x);
  173.    lcd_show_string(30, 200, 200, 16, 16, (char *)g_temp_buffer, BLUE);
  174.    sprintf((char *)g_temp_buffer, "YPOS:%05d", y);
  175.    lcd_show_string(30, 220, 200, 16, 16, (char *)g_temp_buffer, BLUE);
  176.    sprintf((char *)g_temp_buffer, "ZPOS:%05d", z);
  177.    lcd_show_string(30, 240, 200, 16, 16, (char *)g_temp_buffer, BLUE);
  178. //printf("btn,X,Y,Z:0x%x,%d,%d,%d\r\n",data->button,
  179. (signed char)data->x,(signed char)data->y,(signed char)data->z);
  180. }
  181. /**
  182. *@brief        USB键盘数据处理
  183. *@param        data  : USB键盘键值
  184. *@retval       无
  185. */
  186. void keybrd_data_process(uint8_t data)
  187. {
  188.     static uint16_t pos;
  189.     static uint16_t endx, endy;
  190.     static uint16_t maxinputchar;
  191.     uint8_t buf[4];
  192.     if (g_usb_first_plugin_flag)    /* 第一次插入,将数据清零 */
  193.     {
  194.        g_usb_first_plugin_flag = 0;
  195.        endx = ((lcddev.width - 30) / 8) * 8 + 30;       /* 得到endx值 */
  196.        endy = ((lcddev.height - 220) / 16) * 16 + 220; /* 得到endy值 */
  197.        maxinputchar = ((lcddev.width - 30) / 8);
  198.        maxinputchar *= (lcddev.height - 220) / 16;/* 当前LCD最大可以显示的字符数 */
  199.        pos = 0;
  200.     }
  201.    sprintf((char *)buf, "%02X", data);
  202.    lcd_show_string(30 + 56, 180, 200, 16, 16, (char *)buf, BLUE);  /* 显示键值 */
  203.     if (data >= ' ' && data <= '~')
  204.     {
  205.        g_temp_buffer[pos++] = data;
  206.        g_temp_buffer[pos] = 0; /* 添加结束符 */
  207.        if (pos > maxinputchar)
  208.        {
  209.            pos = maxinputchar;   /* 最大输入这么多 */
  210.        }
  211.     }
  212.     else if (data == 0x0D)       /* 退格键 */
  213.     {
  214.        if (pos)
  215.        {
  216.            pos--;
  217.        }
  218.        g_temp_buffer[pos] = 0;  /* 添加结束符 */
  219.     }
  220.     if (pos <= maxinputchar)     /* 没有超过显示区 */
  221.     {
  222.        lcd_fill(30, 220, endx, endy, WHITE);
  223.        lcd_show_string(30, 220, endx - 30, endy - 220, 16, (char *)
  224.                              g_temp_buffer, BLUE);
  225.     }
  226.     //printf("KEY Board Value:%02X\r\n", data);
  227.     //printf("KEY Board Char:%c\r\n", data);
  228. }
  229. /**
  230. *@brief        USB键盘/鼠标演示demo数据处理
  231. *@param        phost : USBH句柄指针
  232. *@retval       无
  233. */
  234. void usb_demo(USBH_HandleTypeDef *phost)
  235. {
  236.     char c;
  237.    HID_KEYBD_Info_TypeDef *k_pinfo;
  238.    HID_MOUSE_Info_TypeDef *m_pinfo;
  239.     if (App_State == APPLICATION_READY)
  240.     {
  241.        if (USBH_HID_GetDeviceType(phost) == HID_KEYBOARD)  /* 键盘设备 */
  242.        {
  243.            k_pinfo =USBH_HID_GetKeybdInfo(phost);           /* 获取键盘信息 */
  244.            if (k_pinfo != NULL)
  245.            {
  246.                 c = USBH_HID_GetASCIICode(k_pinfo);            /* 转换成ASCII码 */
  247.                 keybrd_data_process(c);    /* 在LCD上显示出键盘字符 */
  248.            }
  249.        }
  250.        else if (USBH_HID_GetDeviceType(phost) == HID_MOUSE)/* 鼠标设备 */
  251.        {
  252.            m_pinfo =USBH_HID_GetMouseInfo(phost);           /* 获取鼠标信息 */
  253.            if (m_pinfo != NULL)
  254.            {
  255.                 mouse_data_process(&mouse_info);               /* LCD上显示鼠标信息 */
  256.            }
  257.        }
  258.     }
  259. }
  260. /*****************************************************************************/
  261. /* 以下代码 usbh_check_enume_dead 和 usbh_hid_reconnect 用于HID死机处理,
  262.    提高代码健壮性 */
  263. /**
  264. *@brief        USB枚举状态死机检测,防止USB枚举失败导致的死机
  265. *@param        phost : USB HOST结构体指针
  266. *@retval       0, 没有死机
  267. *                1,死机了,外部必须重新启动USB连接.
  268. */
  269. uint8_t usbh_check_enume_dead(USBH_HandleTypeDef *phost)
  270. {
  271.     static uint16_t errcnt = 0;
  272.     /* 这个状态,如果持续存在,则说明USB死机了 */
  273.     if (phost->gState == HOST_ENUMERATION && (phost->EnumState == ENUM_IDLE ||
  274.         phost->EnumState ==ENUM_GET_FULL_DEV_DESC))
  275.     {
  276.        errcnt++;
  277.        if (errcnt > 2000)              /* 死机了 */
  278.        {
  279.            errcnt = 0;
  280.            return 1;
  281.        }
  282.     }
  283.     else
  284.     {
  285.        errcnt = 0;
  286.     }
  287.     return 0;
  288. }
  289. /**
  290. *@brief        USB HID重新连接
  291. *@param        无
  292. *@retval       无
  293. */
  294. voidusbh_hid_reconnect(void)
  295. {
  296.     /* 关闭之前的连接 */
  297.    HID_Class.DeInit(&hUSBHost);    /* 复位HID */
  298.    USBH_DeInit(&hUSBHost);          /* 复位USB HOST */
  299.    
  300.     /* 重新复位USB */
  301.     RCC->AHB2RSTR |= 1 << 7;         /* USB OTG FS 复位 */
  302.    delay_ms(5);
  303.     RCC->AHB2RSTR &= ~(1 << 7);      /* 复位结束 */
  304.    memset(&hUSBHost, 0, sizeof(hUSBHost));     /* 清零数据 */
  305.    
  306.     /* 重新连接USB HID设备 */
  307.    USBH_Init(&hUSBHost,USBH_UserProcess, 0);
  308.    USBH_RegisterClass(&hUSBHost, USBH_HID_CLASS);
  309.    USBH_Start(&hUSBHost);
  310. }
复制代码
usbh_msg_show函数,用于显示一些提示信息,在USBH_UserProcess函数里面被调用。

USBH_UserProcess函数,用于执行USB主机不同用户状态下的数据处理,在usbh_core.c等相关文件里面被调用,该函数仅针对两个状态进行处理:
1)HOST_USER_DISCONNECTION,表示连接断开了,我们在屏幕显示连接断开,并设置App_State状态为APPLICATION_DISCONNECT;
2)HOST_USER_CLASS_ACTIVE,表示USB主机类激活,即接入USB设备已经准备就绪,可以正常工作了,我们设置App_State状态为:APPLICATION_READY,并根据接入设备的不同(鼠标/键盘)显示不同的信息。

mouse_data_process函数,用于处理USB鼠标数据,在液晶屏上面显示鼠标的移动坐标值和按键状态等信息,该函数在USB_Demo函数里面被调用。

keybrd_data_process函数,用于处理键盘数据,在液晶屏上面显示键盘的输入内容,最多支持2017个字符的输入显示。该函数在USB_Demo函数里面被调用。

usb_demo函数,根据当前用户状态和USB接入设备的类型,执行不同的数据处理。该函数在main函数里面被调用。

usbh_check_enume_dead函数,获取USB枚举状态,防止USB枚举失败导致的死机。该函数在main函数里面的while循环里面被调用。

usbh_hid_reconnect函数,重新连接HID设备。当USB枚举失败后,会调用该函数,重新连接HID设备。

3. main.c代码
下面是main.c的程序,具体如下:
  1. int main(void)
  2. {
  3.    HAL_Init();                             /* 初始化HAL库 */
  4.    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
  5.    delay_init(168);                       /* 延时初始化 */
  6.    usart_init(115200);                   /* 串口初始化为115200 */
  7.    led_init();                             /* 初始化LED */
  8.    lcd_init();                             /* 初始化LCD */
  9.     key_init();                             /* 初始化按键 */
  10.     sram_init();                            /* 初始化外部SRAM */
  11.    my_mem_init(SRAMIN);                  /* 初始化内部SRAM内存池 */
  12.    my_mem_init(SRAMEX);                  /* 初始化外部SRAM内存池 */
  13.    my_mem_init(SRAMCCM);                 /* 初始化内部SRAMCCM内存池 */
  14.    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  15.    lcd_show_string(30, 70, 200, 16, 16, "USBMOUSE/KEYBOARD TEST", RED);
  16.    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  17.    lcd_show_string(30, 110, 200, 16, 16, "USB Connecting...", RED);
  18.    USBH_Init(&hUSBHost,USBH_UserProcess, 1);
  19.    USBH_RegisterClass(&hUSBHost, USBH_HID_CLASS);
  20.    USBH_Start(&hUSBHost);
  21.     while (1)
  22.     {
  23.        USBH_Process(&hUSBHost);
  24.        usb_demo(&hUSBHost);
  25.        if(usbh_check_enume_dead(&hUSBHost))
  26.         /* 检测USB HOST 枚举是否死机了?死机了,则重新初始化 */
  27.        {
  28.            printf("Error!USB HID reconnect!\r\n");
  29.            usbh_hid_reconnect();       /* 重连 */
  30.        }
  31.     }
  32. }
复制代码
main函数,初始化各个外设后,通过USBH_Init等3个函数初始化并启动USB主机通信,然后进入死循环,不停的调用USBH_Process、usb_demo和判断USB HOST枚举是否死机,执行各种USB处理。

67.4 下载验证
将程序下载到开发板后,然后在USB_HOST端子插入USB鼠标/键盘,注意:此时USB SLAVE口不要插USB线到电脑,否则会干扰!
等USB鼠标/键盘成功识别后,便可以看到LCD显示USB Connected,并显示设备类型:USB Mouse或者USB KeyBoard,同时也会显示输入的数据,如图67.4.1和图67.4.2所示:     
image005.png
图67.4.1 USB鼠标测试

image007.png
图67.4.2 USB键盘测试

其中,图67.4.1是USB鼠标测试界面,图67.4.2是USB键盘测试界面。

最后,特别提醒大家,由于例程的HID内核,只处理了第一个接口描述符,所以对于USB符合设备,只能识别第一个描述符所代表的设备。体现到实际使用中,就是:USB无线鼠标,一般是无法使用(被识别为键盘),而USB无线键盘,可以使用,因为键盘在第一个描述符,鼠标在第二个描述符。

至此,开发板的所有实验就介绍完了。其中,参考了不少网友的代码,对这些网友表示衷心的感谢,同时我也希望我们的这些代码,可以让大家有所受益,能开发出更强更好的产品。

实验例程较多,希望大家慢慢理解,各个攻破,最后祝大家身体健康、学习进步!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 07:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表