CUBEMX  STM32F105RB  U盘读写详细教程

abin 42817001

  1. 打开cubemx软件,

 CUBEMX STM32F105RB U盘读写详细教程

 

2.选择单片机型号,本文选stm32f105rb

3.设置RCC,

CUBEMX STM32F105RB U盘读写详细教程

4.设置时钟

CUBEMX STM32F105RB U盘读写详细教程

1 根据开发板选外部晶振,一般是8Mhz。

 2 选通外部晶振通道,由于ubs要使用48Mhz频率,内部频率无法提供

 3工具单片机选择主频,

1  2  3步骤无先后顺序,

5.选择调试端口,这里使用UART2,可以根据需要选择其他的uart

CUBEMX STM32F105RB U盘读写详细教程

6.配置USB顺序

CUBEMX STM32F105RB U盘读写详细教程

CUBEMX STM32F105RB U盘读写详细教程

检查usb时钟是否是48Mhz,一般软件会自动设置好。

CUBEMX STM32F105RB U盘读写详细教程

 

CUBEMX STM32F105RB U盘读写详细教程

Host 设置 见usbh_conf.h  65-90行

CUBEMX STM32F105RB U盘读写详细教程

 

CUBEMX STM32F105RB U盘读写详细教程

 

 

7.设置PC9脚输出

由于本开发板的usb通过PC9低电平导通三极管给usb供电,所以要另外设置PC9脚, 如与本板不同可忽略本步骤。

8.管脚布局查看

CUBEMX STM32F105RB U盘读写详细教程

 

CUBEMX STM32F105RB U盘读写详细教程

9.PROJECT配置

CUBEMX STM32F105RB U盘读写详细教程

CUBEMX STM32F105RB U盘读写详细教程10.点击软件界面的右上角的CUBEMX STM32F105RB U盘读写详细教程 产生代码,可能会出现一个警告窗口,不必理会,点YES 

 

 

 

CUBEMX STM32F105RB U盘读写详细教程

 

 

 

软件会自动生成KEIL需要的相关工程文件,点打开工程,然后就自动打开KEIL,

CUBEMX STM32F105RB U盘读写详细教程

 

11.Keil 操作

CUBEMX STM32F105RB U盘读写详细教程

 

12.Cubemx生成的main.c还不能直接使用,要定义变量 回调函数 USB操作函数等

代码要保存在cubemx设定好的用户代码区域,如果硬件变动生成新代码,用户自定义的代码就会保留。

 

13.下面是main.c修改后的文件,红色部分是增加的内容,其他文件不需修改

/* USER CODE BEGIN Header */

/**

  ******************************************************************************

  * @file           : main.c

  * @brief          : Main program body

  ******************************************************************************

  * @attention

  *

  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.

  * All rights reserved.</center></h2>

  *

  * This software component is licensed by ST under Ultimate Liberty license

  * SLA0044, the "License"; You may not use this file except in compliance with

  * the License. You may obtain a copy of the License at:

  *                             www.st.com/SLA0044

  *

  ******************************************************************************

  */

/* USER CODE END Header */

 

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "fatfs.h"

#include "usart.h"

#include "usb_host.h"

#include "gpio.h"

 

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

 

/* USER CODE END Includes */

 

/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */

 

/* USER CODE END PTD */

 

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */

 

/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */

//定义PC9脚,如不需要可取消

#define USB_POWER_Pin GPIO_PIN_9

#define USB_POWER_GPIO_Port GPIOC

 

/* USER CODE END PM */

 

/* Private variables ---------------------------------------------------------*/

 

/* USER CODE BEGIN PV */

 

/* USER CODE END PV */

 

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

void MX_USB_HOST_Process(void);

 

/* USER CODE BEGIN PFP */

 

FATFS USBDISKFatFs;           /* File system object for USB disk logical drive */

FIL MyFile;                   /* File object */

extern ApplicationTypeDef Appli_state;

 

/* USER CODE END PFP */

 

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

//下面2个函数 使能、禁止HCD_Port的回调函数,勿修改,必须

/**

* @brief  Port Port Enabled callback.

  * @param  hhcd: HCD handle

  * @retval None

  */

void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)

{

  USBH_LL_PortEnabled(hhcd->pData);

}

 

/**

  * @brief  Port Port Disabled callback.

  * @param  hhcd: HCD handle

  * @retval None

  */

void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)

{

  USBH_LL_PortDisabled(hhcd->pData);

}

/**

  * @brief  Main routine for Mass Storage Class

  * @param  None

  * @retval None

  */

//下面函数操作USB 文件读写,可根据需要修改,函数名可自定义

void MSC_Application(void)

{

  /* FatFs function common result code description: */

    /*  FR_OK = 0,                (0) Succeeded */

    /*  FR_DISK_ERR,              (1) A hard error occurred in the low level disk I/O layer */

    /*  FR_INT_ERR,               (2) Assertion failed */

    /*  FR_NOT_READY,             (3) The physical drive cannot work */

    /*  FR_NO_FILE,               (4) Could not find the file */

    /*  FR_NO_PATH,               (5) Could not find the path */

    /*  FR_INVALID_NAME,          (6) The path name format is invalid */

    /*  FR_DENIED,                (7) Access denied due to prohibited access or directory full */

    /*  FR_EXIST,                 (8) Access denied due to prohibited access */

    /*  FR_INVALID_OBJECT,        (9) The file/directory object is invalid */

    /*  FR_WRITE_PROTECTED,       (10) The physical drive is write protected */

    /*  FR_INVALID_DRIVE,         (11) The logical drive number is invalid */

    /*  FR_NOT_ENABLED,           (12) The volume has no work area */

    /*  FR_NO_FILESYSTEM,         (13) There is no valid FAT volume */

    /*  FR_MKFS_ABORTED,          (14) The f_mkfs() aborted due to any parameter error */

    /*  FR_TIMEOUT,               (15) Could not get a grant to access the volume within defined period */

    /*  FR_LOCKED,                (16) The operation is rejected according to thex file sharing policy */

    /*  FR_NOT_ENOUGH_CORE,       (17) LFN working buffer could not be allocated */

    /*  FR_TOO_MANY_OPEN_FILES,   (18) Number of open files > _FS_SHARE */

    /*  FR_INVALID_PARAMETER      (19) Given parameter is invalid */

 

  FRESULT res;                                          /* FatFs function common result code */

  uint32_t byteswritten, bytesread;                     /* File write/read counts */

  uint8_t wtext[] = "Hello Test USB!";                     /* File write buffer */

  uint8_t rtext[100];                                   /* File read buffer */

 

  /* Register the file system object to the FatFs module */

  res = f_mount(&USBDISKFatFs, (TCHAR const*)USBHPath, 0);

  if(res != FR_OK) 

  {

    /* FatFs Initialization Error */

    USBH_UsrLog("f_mount error: %d", res);

    Error_Handler();

  }

 

  USBH_UsrLog("create the file in: %s", USBHPath);

  /* Create and Open a new text file object with write access */

  res = f_open(&MyFile, "USBHost.txt", FA_CREATE_ALWAYS | FA_WRITE);

  if(res != FR_OK)

  {

    /* 'hello.txt' file Open for write Error */

    USBH_UsrLog("f_open with write access error: %d", res);

    Error_Handler();

  }

  /* Write data to the text file */

  res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);

  if((byteswritten == 0) || (res != FR_OK))

  {

    /* 'hello.txt' file Write or EOF Error */

    USBH_UsrLog("file write or EOF error: %d", res);

    Error_Handler();

  }

 

  /* Close the open text file */

  f_close(&MyFile);

 

  /* Open the text file object with read access */

  res = f_open(&MyFile, "USBHost.txt", FA_READ);

  if(res != FR_OK)

  {

    /* 'hello.txt' file Open for read Error */

    USBH_UsrLog("f_open with read access error: %d", res);

    Error_Handler();

  }

 

  /* Read data from the text file */

  res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);

  if((bytesread == 0) || (res != FR_OK))

  {

    /* 'hello.txt' file Read or EOF Error */

    USBH_UsrLog("f_read error: %d", res);

    Error_Handler();

  }

 

  /* Close the open text file */

  f_close(&MyFile);

 

  /* Compare read data with the expected data */

  if((bytesread != byteswritten))

  {               

    /* Read data is different from the expected data */

    USBH_UsrLog("file doesn't match");

    Error_Handler();

  }

 

  /* Success of the demo: no error occurrence */

  USBH_UsrLog("USBHost.txt was created into the disk");

 

  /* Unlink the USB disk I/O driver */

  FATFS_UnLinkDriver(USBHPath);

}

 

/* USER CODE END 0 */

 

/**

  * @brief  The application entry point.

  * @retval int

  */

int main(void)

{

  /* USER CODE BEGIN 1 */

 

  /* USER CODE END 1 */

 

 

  /* MCU Configuration--------------------------------------------------------*/

 

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

 

  /* USER CODE BEGIN Init */

 

  /* USER CODE END Init */

 

  /* Configure the system clock */

  SystemClock_Config();

 

  /* USER CODE BEGIN SysInit */

 

  /* USER CODE END SysInit */

 

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_USART2_UART_Init();

  MX_FATFS_Init();

  MX_USB_HOST_Init();

  /* USER CODE BEGIN 2 */

//拉低PC9,如无该设置可取消

HAL_GPIO_WritePin(USB_POWER_GPIO_Port, USB_POWER_Pin, GPIO_PIN_RESET);

 

  /* USER CODE END 2 */

 

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

printf("STM32 start ok!\n");

  while (1)

  {

    /* USER CODE END WHILE */

    MX_USB_HOST_Process();

 

    /* USER CODE BEGIN 3 */

//判断USB是否进入准备状态APPLICATION_READY

switch(Appli_state)

    {

      /**

        * The generated code from STM32CubeMX has two "confusing" application states

        * APPLICATION_START on HOST_USER_CONNECTION and APPLICATION_READY on HOST_USER_CLASS_ACTIVE.

        * Any FatFs commands should be executed after APPLICATION_STATE_READY is reached."

        */

      case APPLICATION_READY:

        printf("ready ok\n");

      MSC_Application();

        Appli_state = APPLICATION_IDLE;

        break;

 

      case APPLICATION_IDLE:

      default:

        break;     

    }

     

  }

  /* USER CODE END 3 */

}

 

/**

  * @brief System Clock Configuration

  * @retval None

  */

void SystemClock_Config(void)

{

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

 

  /** Initializes the CPU, AHB and APB busses clocks

  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

  RCC_OscInitStruct.HSEState = RCC_HSE_ON;

  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;

  RCC_OscInitStruct.HSIState = RCC_HSI_ON;

  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_HSE;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL_NONE;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

  {

    Error_Handler();

  }

  /** Initializes the CPU, AHB and APB busses clocks

  */

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

 

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

  {

    Error_Handler();

  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;

  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV3;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

  {

    Error_Handler();

  }

  /** Configure the Systick interrupt time

  */

  __HAL_RCC_PLLI2S_ENABLE();

}

 

/* USER CODE BEGIN 4 */

 

//##############

//USB调试信息输出要用到printf,必须设置

//如果printf不能使用,需#include <stdio.h>,如使用UART1,则下面的huart2要改成huart1

/* fputc */

int fputc(int ch, FILE *f)

 {

 

HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1 , 0xffff);

while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission 每个发送都值得优化

 

return ch;

}

 

 

/* USER CODE END 4 */

 

/**

  * @brief  This function is executed in case of error occurrence.

  * @retval None

  */

void Error_Handler(void)

{

  /* USER CODE BEGIN Error_Handler_Debug */

  /* User can add his own implementation to report the HAL error return state */

 

  /* USER CODE END Error_Handler_Debug */

}

 

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t *file, uint32_t line)

{

  /* USER CODE BEGIN 6 */

  /* User can add his own implementation to report the file name and line number,

     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */

 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 

14.程序运行结果如下(启动后插上U盘,然后拔出U盘)。

由于FATFS系统版本不同,可能有些U盘无法识别。比如3.0 U

  1. 是MX_USB_HOST_Process(); 函数产生的信息
  2. 是 void MSC_Application(void)  输出的内容

CUBEMX STM32F105RB U盘读写详细教程

 

15.网友介绍F407可以直接使用CUBEMX生成的文件,无需修改。使用F407的朋友可自行验证。

16.本文内容在STM32F105RB + cubemx5.4 + keilMDK5.2 + J-LINK V8.0调试通过。

17.本文由abin  42817001整理,

18.感谢 @厦门-电梯-窝瓜(892219846) @大拇指[em]IT(2571393392)   指点、解惑。

19.完成时间 2011.09

 

 

 

相关文章: