由于国际环境日趋复杂严峻和不确定性,MCU的国产替代已经刻不容缓。实际工作中,我们通常用GD MCU替换STM32 MCU。在移植过程中,遇到STM32CubeMx生成的USBCDC接口不能被上位机识别的问题,下面介绍一种移植GD USB库到HAL库的方法。MCU型号选STM32F407VGT6和GD32F407VGT6,用GD32407V-START开发板测试。
先用ST的CubeMX按下面步骤生成USB工程文件。
- 打开CubeMX,新建工程,选择芯片型号STM32F407VGT6
2. 双击进入下一步,选择外部晶振HSE
3. 调试模式选择SWD
4. 选择USB_OTG_FS,Device_Only,NVIC中断设置打“√”
5. 开发板上晶振是25M,选HSE 25M,修改参数M\N\P\Q,配置USB时钟48MHz,系统时钟SYSLK为168MHz
6. 项目管理里面修改堆栈大小
7. 点击生成代码,并打开工程,这里要注意工程文件名路径不要有中文,不然无法正常打开工程文件。
现在在CDCtest工程目录中新建USB_DEVICE文件夹,GD32F4xx_Firmware_Library_V3.04\Firmware\GD32F4xx_usb_library目录下的所有文件拷贝至USB_DEVICE文件夹下,并添加至CDCtest工程中,GD的GD32F4xx_Firmware_Library库文件可以到GD官网下载,也可以找GD代理商提供。添加好后的文件目录结构如下图所示:
添加完的USB库文件需要做简单的修改,把睡眠模式相关函数pmu_to_deepsleepmode和微秒延时函数usb_udelay注释掉,毫秒延时函数usb_mdelay用HAL_Delay替代。
接下来把GD32F4xx_Firmware_Library_V3.04\Examples\USB\USB_Device\cdc_acm\inc目录下的usb_conf.h和usbd_conf.h拷贝至CDCtest工程的CDCtest\Core\inc目录下,并在该目录下新建gd32f4xx_compat.h文件备用。
添加头文件包含路径。
添加宏定义USE_USE_FS。
修改usb_conf.h头文件
修改stm32f4xx_it.c中的USB中断处理函数HAL_PCD_IRQHandler。
在gd32f4xx_compat.h文件中添加如下内容。
#ifndef GD32F4XX_COMPAT_H
#define GD32F4XX_COMPAT_H
/* bit operations */
#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr))
#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr))
#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr))
#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x)))
#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end))))
#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start))
#endif
把GD32F4xx_Firmware_Library_V3.04\Examples\USB\USB_Device\cdc_acm\src\app.c文件中的内容拷贝到main.c中。
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cdc_acm_core.h"
usb_core_driver cdc_acm;
/* 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 */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* 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_USB_OTG_FS_PCD_Init();
/* USER CODE BEGIN 2 */
usbd_init (&cdc_acm,
#ifdef USE_USB_FS
USB_CORE_ENUM_FS,
#elif defined(USE_USB_HS)
USB_CORE_ENUM_HS,
#endif /* USE_USB_FS */
&cdc_desc,
&cdc_class);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if (USBD_CONFIGURED == cdc_acm.dev.cur_status) {
if (0U == cdc_acm_check_ready(&cdc_acm)) {
cdc_acm_data_receive(&cdc_acm);
} else {
cdc_acm_data_send(&cdc_acm);
}
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
编译程序没有报错,下载程序到MCU,注意下载芯片型号要选择GD32F407VG
打开设备管理器,虚拟串口显示正常。