话不多说,先上程序。
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "usbh_usr.h"
#include "string.h"
//ALIENTEK 探索者STM32F407开发板 实验54
//USB鼠标键盘 实验 -库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司
//作者:正点原子 @ALIENTEK
USBH_HOST USB_Host;
USB_OTG_CORE_HANDLE USB_OTG_Core_dev;
extern HID_Machine_TypeDef HID_Machine;
//USB信息显示
//msgx:0,USB无连接
// 1,USB键盘
// 2,USB鼠标
// 3,不支持的USB设备
void USBH_Msg_Show(u8 msgx)
{
POINT_COLOR=RED;
switch(msgx)
{
case 0: //USB无连接
LCD_ShowString(30,130,200,16,16,"USB Connecting...");
LCD_Fill(0,150,lcddev.width,lcddev.height,WHITE);
break;
case 1: //USB键盘
LCD_ShowString(30,130,200,16,16,"USB Connected ");
LCD_ShowString(30,150,200,16,16,"USB KeyBoard");
LCD_ShowString(30,180,210,16,16,"KEYVAL:");
LCD_ShowString(30,200,210,16,16,"INPUT STRING:");
break;
case 2: //USB鼠标
LCD_ShowString(30,130,200,16,16,"USB Connected ");
LCD_ShowString(30,150,200,16,16,"USB Mouse");
LCD_ShowString(30,180,210,16,16,"BUTTON:");
LCD_ShowString(30,200,210,16,16,"X POS:");
LCD_ShowString(30,220,210,16,16,"Y POS:");
LCD_ShowString(30,240,210,16,16,"Z POS:");
break;
case 3: //不支持的USB设备
LCD_ShowString(30,130,200,16,16,"USB Connected ");
LCD_ShowString(30,150,200,16,16,"Unknow Device");
break;
}
}
//HID重新连接
void USBH_HID_Reconnect(void)
{
//关闭之前的连接
USBH_DeInit(&USB_OTG_Core_dev,&USB_Host); //复位USB HOST
USB_OTG_StopHost(&USB_OTG_Core_dev); //停止USBhost
if(USB_Host.usr_cb->DeviceDisconnected) //存在,才禁止
{
USB_Host.usr_cb->DeviceDisconnected(); //关闭USB连接
USBH_DeInit(&USB_OTG_Core_dev, &USB_Host);
USB_Host.usr_cb->DeInit();
USB_Host.class_cb->DeInit(&USB_OTG_Core_dev,&USB_Host.device_prop);
}
USB_OTG_DisableGlobalInt(&USB_OTG_Core_dev);//关闭所有中断
//重新复位USB
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS,ENABLE);//USB OTG FS 复位
delay_ms(5);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS,DISABLE); //复位结束
memset(&USB_OTG_Core_dev,0,sizeof(USB_OTG_CORE_HANDLE));
memset(&USB_Host,0,sizeof(USB_Host));
//重新连接USB HID设备
USBH_Init(&USB_OTG_Core_dev,USB_OTG_FS_CORE_ID,&USB_Host,&HID_cb,&USR_Callbacks);
}
int main(void)
{
u32 t;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
LED_Init(); //初始化LED
LCD_Init();
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"USB MOUSE/KEYBOARD TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2014/7/23");
LCD_ShowString(30,130,200,16,16,"USB Connecting...");
//初始化USB主机
USBH_Init(&USB_OTG_Core_dev,USB_OTG_FS_CORE_ID,&USB_Host,&HID_cb,&USR_Callbacks);
while(1)
{
USBH_Process(&USB_OTG_Core_dev, &USB_Host);
if(bDeviceState==1)//连接建立了
{
if(USBH_Check_HIDCommDead(&USB_OTG_Core_dev,&HID_Machine))//检测USB HID通信,是否还正常?
{
USBH_HID_Reconnect();//重连
}
}else //连接未建立的时候,检测
{
if(USBH_Check_EnumeDead(&USB_Host)) //检测USB HOST 枚举是否死机了?死机了,则重新初始化
{
USBH_HID_Reconnect();//重连
}
}
t++;
if(t==200000)
{
LED0=!LED0;
t=0;
}
}
}
开头定义了USBH_HOST和USB_OTG_CORE_HANDLE结构体变量。
先打开USBH_HOST结构体看一下。
typedef struct _Host_TypeDef
{
HOST_State gState; /* Host State Machine Value */
HOST_State gStateBkp; /* backup of previous State machine value */
ENUM_State EnumState; /* Enumeration state Machine */
CMD_State RequestState;
USBH_Ctrl_TypeDef Control;
USBH_Device_TypeDef device_prop;
USBH_Class_cb_TypeDef *class_cb;
USBH_Usr_cb_TypeDef *usr_cb;
} USBH_HOST, *pUSBH_HOST;
里面有两个HOST_State的变量,gState主机状态值 gStateBkp主机上一状态值,一个ENUM_State的变量EnumState枚举状态机,一个CMD_State变量RequestState,一个USBH_Ctrl_TypeDef的变量Control,一个USBH_Device_TypeDef的变量device_prop,一个USBH_Class_cb_TypeDef的变量 *class_cb,一个 USBH_Usr_cb_TypeDef的变量 *usr_cb。
不清楚这几个变量先往下看。
打开USB_OTG_CORE_HANDLE结构体
typedef struct USB_OTG_handle
{
USB_OTG_CORE_CFGS cfg;
USB_OTG_CORE_REGS regs;
#ifdef USE_DEVICE_MODE
DCD_DEV dev;
#endif
#ifdef USE_HOST_MODE
HCD_DEV host;
#endif
#ifdef USE_OTG_MODE
OTG_DEV otg;
#endif
}
USB_OTG_CORE_HANDLE , *PUSB_OTG_CORE_HANDLE;
这个结构体里面有 USB_OTG_CORE_CFGS结构体变量cfg,USB_OTG_CORE_REGS结构体变量regs,下面是定义了哪个模式就用哪个结构体的变量,我们使用的是host模式,所以就定义了HCD_DEV结构体变量host。这些结构都是写在usb_core.h里面,所以我们可以断定这些都是USB核心数据。然后往下看。
HID_Machine_TypeDef结构体
/* Structure for HID process */
typedef struct _HID_Process
{
uint8_t buff[64];
uint8_t hc_num_in;
uint8_t hc_num_out;
HID_State state;
uint8_t HIDIntOutEp;
uint8_t HIDIntInEp;
HID_CtlState ctl_state;
uint16_t length;
uint8_t ep_addr;
uint16_t poll;
__IO uint16_t timer;
HID_cb_TypeDef *cb;
}
HID_Machine_TypeDef;
这次终于又注释了,HID进程的结构体变量。里面有HID_State结构体的变量state,还有HID_CtlState的结构体变量ctl_state,还有HID_cb_TypeDef的结构体变量*cb。
然后我们接着往下看,跳过这两个个函数,直接进入主函数。
前面的函数我们先略过,别的章节再讲,我们直攻USB初始化函数
USBH_Init(&USB_OTG_Core_dev,USB_OTG_FS_CORE_ID,&USB_Host,&HID_cb,&USR_Callbacks);
打开这个函数
/**
* @brief USBH_Init//注:汉 USB初始化
* Host hardware and stack initializations //注:汉 主机硬件和堆栈初始化
* @param class_cb: Class callback structure address//注: 汉 类回调的结构体地址
* @param usr_cb: User callback structure address//注: 汉 使用者回调的机构体地址
* @retval None
*/
void USBH_Init(USB_OTG_CORE_HANDLE *pdev,
USB_OTG_CORE_ID_TypeDef coreID,
USBH_HOST *phost,
USBH_Class_cb_TypeDef *class_cb,
USBH_Usr_cb_TypeDef *usr_cb)
{
/* Hardware Init */
USB_OTG_BSP_Init(pdev);
/* configure GPIO pin used for switching VBUS power */
USB_OTG_BSP_ConfigVBUS(0);
/* Host de-initializations */
USBH_DeInit(pdev, phost);
/*Register class and user callbacks */
phost->class_cb = class_cb;
phost->usr_cb = usr_cb;
/* Start the USB OTG core */
HCD_Init(pdev , coreID);
/* Upon Init call usr call back */
phost->usr_cb->Init();
/* Enable Interrupts */
USB_OTG_BSP_EnableInterrupt(pdev);
}
我们先看一下回调的结构体参数,第一个就是再最开始定义的USB_OTG_CORE_HANDLE结构体变量的位置,第二个打开看看
/** @defgroup USB_DEFINES_Exported_Types
* @{
*/
typedef enum
{
USB_OTG_HS_CORE_ID = 0,
USB_OTG_FS_CORE_ID = 1
}USB_OTG_CORE_ID_TypeDef;
两种内核模式FS和HS的内核。
第三个参数为开始定义的USBH_HOST结构体变量的位置,第四个结构体和USBH_HOST里面其中倒数第二个参数的结构体一样,第五结构体和USBH_HOST里面其中倒数第一个参数的结构体一样。
然后我们打开这个这个函数。
/**
* @brief USBH_Init
* Host hardware and stack initializations //主机硬件和堆栈初始化
* @param class_cb: Class callback structure address//类回调结构体地址
* @param usr_cb: User callback structure address//用户回调结构体地址
* @retval None
*/
void USBH_Init(USB_OTG_CORE_HANDLE *pdev,
USB_OTG_CORE_ID_TypeDef coreID,
USBH_HOST *phost,
USBH_Class_cb_TypeDef *class_cb,
USBH_Usr_cb_TypeDef *usr_cb)
{
/* Hardware Init *///硬件初始化
USB_OTG_BSP_Init(pdev);
/* configure GPIO pin used for switching VBUS power *///配置GPIO引脚用于开关VBUS引脚
USB_OTG_BSP_ConfigVBUS(0);
/* Host de-initializations *///主机取消初始化
USBH_DeInit(pdev, phost);
/*Register class and user callbacks *///寄存器类和用户回调
phost->class_cb = class_cb;
phost->usr_cb = usr_cb;
/* Start the USB OTG core */ //启动USB OTG核心
HCD_Init(pdev , coreID);
/* Upon Init call usr call back *///初始化调用时启动USR回调
phost->usr_cb->Init();
/* Enable Interrupts *///使能中断
USB_OTG_BSP_EnableInterrupt(pdev);
}
未完待续。