STM32CubeMX系列教程26:USB HOST
一.USB MSC
这一节介绍usb作为主机读取U盘设备,通过USB虚拟串口通信。程序在LCD滚动显示字符工程的基础上修改,复制工程修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备,PE2设置为GPIO输出模式,USB口输出电压给从设备。
USB HOST选择大容量存储主机类,选择USB Disk开启FATFS文件系统。
配置系统时钟频率为216MHZ,USB频率均为48MHz。
在FATFS配置中选择简体中文字GBK编码支持中文,使能长文件名,缓存存储在堆(STACK)中。
USB_OTG_FS为默认配置不作修改。
中间件USB_HOST配置中,USB主机调试等级(USBH_DEBUG_LEVEL)选择2,此时用户信息和错误信息会通过标准输出设备显示,此处使用屏幕作为输出设备,故printf函数打印的信息会显示在屏幕上。
最后设置堆栈大小。
生成报告以及初始化代码,编译程序。应用层多出下面三个文件。
其中fatfs.c为文件系统的应用层文件,包含文件系统的初始化函数MX_FATFS_Init()。 usbh_conf.c为USB配置文件,包含USB管脚的初始化,寄存器参数初始化,中断回调函数等。 usb_host.c为应用层文件,包含USB HOST的初始化函数MX_USB_HOST_Init(),以及HOST后台任务函数MX_USB_HOST_Process(),由于程序中没有使用操作系统,次函数必须添加到main函数的while循环中。用户处理函数USBH_UserProcess()。
/*
* user callbak definition
*/
static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id)
{
/* USER CODE BEGIN 2 */
switch(id)
{
case HOST_USER_SELECT_CONFIGURATION:
break;
case HOST_USER_DISCONNECTION:
Appli_state = APPLICATION_DISCONNECT;
break;
case HOST_USER_CLASS_ACTIVE:
Appli_state = APPLICATION_READY;
break;
case HOST_USER_CONNECTION:
Appli_state = APPLICATION_START;
break;
default:
break;
}
/* USER CODE END 2 */
}
下载下面的应用程序添加到工程中
<a class="attach" href="portal.php?mod=attachment&id=637" target="_blank">USB_HOST_MSC.zip
应用程序包含下面三个文件,这三个文件可以在固件库里面找到原型。 STM32Cube_FW_F7_V1.3.0\Projects\STM32746G-Discovery\Applications\USB_Host\MSC_Standalone\Src
其中explorer.c文件里面包含搜索文件系统里面所有文件的函数Explore_Disk()。
file_operations.c文件里面包含一个文件操作函数MSC_File_Operations(),主要是新建文件,然后写内容再读取出来比较等操作,测试是否可以操作文件系统。
menu.c为菜单处理函数,更加不同状态进行不同操作。
/**
* @brief Manages MSC Menu Process.
* @param None
* @retval None
*/
void MSC_MenuProcess(void)
{
switch(msc_demo.state)
{
case MSC_DEMO_START:
if(Appli_state == APPLICATION_READY)
{
BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
BSP_LCD_DisplayStringAtLine(35, (uint8_t *)"Press User button to start read and write operations");
/* Wait for User Input */
while((BSP_JOY_GetState() != JOY_CTR) && (Appli_state != APPLICATION_DISCONNECT))
{
}
msc_demo.state = MSC_DEMO_FILE_OPERATIONS;
/* Prevent debounce effect for user key */
HAL_Delay(400);
BSP_LCD_ClearStringLine(19);
}
break;
case MSC_DEMO_FILE_OPERATIONS:
/* Read and Write File Here */
if(Appli_state == APPLICATION_READY)
{
MSC_File_Operations();
BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
BSP_LCD_DisplayStringAtLine(35, (uint8_t *)"Press User button to display disk content");
/* Wait for User Input */
while((BSP_JOY_GetState() != JOY_CTR) && (Appli_state != APPLICATION_DISCONNECT))
{
}
msc_demo.state = MSC_DEMO_EXPLORER;
/* Prevent debounce effect for user key */
HAL_Delay(400);
BSP_LCD_ClearStringLine(19);
}
break;
case MSC_DEMO_EXPLORER:
/* Display disk content */
if(Appli_state == APPLICATION_READY)
{
Explore_Disk("0:/", 1);
msc_demo.state = MSC_DEMO_START;
/* Prevent debounce effect for user key */
HAL_Delay(400);
}
break;
default:
break;
}
if(Appli_state == APPLICATION_DISCONNECT)
{
Appli_state = APPLICATION_IDLE;
LCD_LOG_ClearTextZone();
LCD_ErrLog("MSC device disconnected!\n");
msc_demo.state = MSC_DEMO_START;
msc_demo.select = 0;
}
}
当USB_HOST处于未连接状态(APPLICATION_DISCONNECT)时,会显示未连接错误。
当USB_HOST处于准备状态(APPLICATION_READY)时,根据MSC示例的状态进行不同操作。
第一阶段开始阶段(MSC_DEMO_START),等待按键第一次按下。
当按键按下时进入第二阶段(MSC_DEMO_FILE_OPERATIONS)进行文件读写操作测试。
再次按下按键时进入第三阶段(MSC_DEMO_EXPLORER),显示U盘目录下所有文件。程序再次回到第一阶段。
在main()函数中添加初始化函数,初始化LCD,文件系统以及MSC菜单初始化。
<syntaxhighlight lang="python">
/* USER CODE BEGIN 2 */
/* Initialize the SDRAM */
BSP_SDRAM_Init();
/* Initialize the LCD */
BSP_LCD_Init();
/* Clear the LCD Background layer */
BSP_LCD_SetLayerVisible(1,DISABLE);
BSP_LCD_SelectLayer(0);
BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
/* Initialize LCD Log module */
LCD_LOG_Init();
/* Show Header and Footer texts */
LCD_LOG_SetHeader((uint8_t *)" USB OTG FS MSC Host");
LCD_LOG_SetFooter((uint8_t *)"WaveShare Open7XXI-C board");
LCD_UsrLog("USB Host library started.\n");
/* Initialize menu and MSC process */
Menu_Init();
/* Register the file system object to the FatFs module */
if(f_mount(&USBH_fatfs, "", 0) != FR_OK)
{
LCD_ErrLog("Cannot Initialize FatFs! \n");
}
/* USER CODE END 2 */
在while循环中添加MSC的菜单处理函数MSC_MenuProcess()。
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_USB_HOST_Process();
/* USER CODE BEGIN 3 */
/* MSC Menu Process */
MSC_MenuProcess();
}
/* USER CODE END 3 */
在mian文件前面导入外部函数以及变量。
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
extern FATFS USBH_fatfs;
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
extern void Menu_Init(void);
extern void MSC_MenuProcess(void);
/* USER CODE END PFP */
</syntaxhighlight>
最后编译程序,并下载到开发板,用OTG 一端接 U 盘,另外一端接到Open746I-C核心板的USB口,按下按键按键LCD上会显U盘里面的文件。
鄙人在这里只是简单讲解一下USB的示例程序,关于USB的更多示例程序可以参考ST官方的固件库示例程序。