STM32 USB学习笔记2

主机环境:Windows 7 SP1

开发环境:MDK5.14

目标板:STM32F103C8T6

开发库:STM32F1Cube库和STM32_USB_Device_Library


STM32Cube库中提供了一些有关USB的例程,在其工程目录下的Applications目录中,这里打开STM3210E_EVAL目录,可以看到如下例程:

STM32 USB学习笔记2_第1张图片

这里选取一个简单的例子CDC_Standalone,为一个USB通信例程,具体实现是一个USB转串口的功能,相当于USB串口线。把示例里面的inc和src目录下的文件拷贝到新建工程中,这里是把跟usb通信相关的文件放到了vcp目录下。文件目录结构如下:

STM32 USB学习笔记2_第2张图片

其中BSP目录很简单,由于所购买的单板只用到了USB,UART模块以及一个LED灯,原理图如下:

STM32 USB学习笔记2_第3张图片

其中PA15引脚连接了一个LED灯,如下:

STM32 USB学习笔记2_第4张图片

因此在stm32f103_demo文件中只添加了led的操作,源文件如下:

/**
  ******************************************************************************
  * @file    stm32f103_demo.c
  * @author  MCD Application Team
  * @version V6.0.0
  * @date    13-October-2015
  * @brief   This file provides a set of firmware functions to manage Leds, 
  *          for STM32F103_DEMO
  ******************************************************************************
  * @attention
  *
  * 

© COPYRIGHT(c) 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "STM32f103_demo.h" /** @addtogroup BSP * @{ */ /** @defgroup STM32F103_DEMO STM32F103-DEMO * @{ */ /** @defgroup STM32F103_DEMO_Common STM32F103-DEMO Common * @{ */ /** @defgroup STM32F103_DEMO_Private_TypesDefinitions Private Types Definitions * @{ */ /** * @} */ /** @defgroup STM32F103_DEMO_Private_Defines Private Defines * @{ */ /** * @brief STM32103 EVAL BSP Driver version number V6.0.0 */ #define __STM32F103_DEMO_BSP_VERSION_MAIN (0x06) /*!< [31:24] main version */ #define __STM32F103_DEMO_BSP_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ #define __STM32F103_DEMO_BSP_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ #define __STM32F103_DEMO_BSP_VERSION_RC (0x00) /*!< [7:0] release candidate */ #define __STM32F103_DEMO_BSP_VERSION ((__STM32F103_DEMO_BSP_VERSION_MAIN << 24)\ |(__STM32F103_DEMO_BSP_VERSION_SUB1 << 16)\ |(__STM32F103_DEMO_BSP_VERSION_SUB2 << 8 )\ |(__STM32F103_DEMO_BSP_VERSION_RC)) /** * @} */ /** @defgroup STM32F103_DEMO_Private_Variables Private Variables * @{ */ /** * @brief LED variables */ GPIO_TypeDef* LED_PORT[LEDn] = {LED_GPIO_PORT}; const uint16_t LED_PINS[LEDn] = {LED_PIN}; /** * @brief This method returns the STM32103 EVAL BSP Driver revision * @retval version : 0xXYZR (8bits for each decimal, R for RC) */ uint32_t BSP_GetVersion(void) { return __STM32F103_DEMO_BSP_VERSION; } /** * @brief Configures LED GPIO. * @param Led: Specifies the Led to be configured. * This parameter can be one of following parameters: * @arg LED * @retval None */ void BSP_LED_Init(Led_TypeDef Led) { GPIO_InitTypeDef gpioinitstruct = {0}; /* Enable the GPIO_LED clock */ LED_GPIO_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); __HAL_AFIO_REMAP_SWJ_DISABLE(); /* Configure the GPIO_LED pin */ gpioinitstruct.Pin = LED_PINS[Led]; gpioinitstruct.Mode = GPIO_MODE_OUTPUT_PP; gpioinitstruct.Pull = GPIO_NOPULL; gpioinitstruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(LED_PORT[Led], &gpioinitstruct); HAL_GPIO_WritePin(LED_PORT[Led], LED_PINS[Led], GPIO_PIN_RESET); } /** * @brief Turns selected LED On. * @param Led: Specifies the Led to be set on. * This parameter can be one of following parameters: * @arg LED * @retval None */ void BSP_LED_On(Led_TypeDef Led) { HAL_GPIO_WritePin(LED_PORT[Led], LED_PINS[Led], GPIO_PIN_RESET); } /** * @brief Turns selected LED Off. * @param Led: Specifies the Led to be set off. * This parameter can be one of following parameters: * @arg LED * @retval None */ void BSP_LED_Off(Led_TypeDef Led) { HAL_GPIO_WritePin(LED_PORT[Led], LED_PINS[Led], GPIO_PIN_SET); } /** * @brief Toggles the selected LED. * @param Led: Specifies the Led to be toggled. * This parameter can be one of following parameters: * @arg LED * @retval None */ void BSP_LED_Toggle(Led_TypeDef Led) { HAL_GPIO_TogglePin(LED_PORT[Led], LED_PINS[Led]); } /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 
  头文件如下: 
  

/**
  ******************************************************************************
  * @file    stm32f103_demo.h
  * @author  MCD Application Team
  * @version V6.0.0
  * @date    13-October-2015
  * @brief   This file contains definitions for STM32F103_DEMO's LEDs, 
  *          hardware resources.
  ******************************************************************************
  * @attention
  *
  * 

© COPYRIGHT(c) 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F103_DEMO_H #define __STM32F103_DEMO_H #ifdef __cplusplus extern "C" { #endif /** @addtogroup BSP * @{ */ /** @addtogroup STM32F103_DEMO * @{ */ /* Includes ------------------------------------------------------------------*/ #include "stm32f1xx_hal.h" /** @addtogroup STM32F103_DEMO_Common STM3210E-EVAL Common * @{ */ /** @defgroup STM32F103_DEMO_Exported_Types Exported Types * @{ */ /** * @brief LED Types Definition */ typedef enum { LED = 0, LED_GREEN = LED, } Led_TypeDef; /** * @} */ /** @defgroup STM32F103_DEMO_Exported_Constants Exported Constants * @{ */ /** * @brief Define for STM32F103_DEMO board */ #if !defined (USE_STM32F103_DEMO) #define USE_STM32F103_DEMO #endif /** @addtogroup STM32F103_DEMO_LED * @{ */ #define LEDn 1 #define LED_PIN GPIO_PIN_15 /* PA.15*/ #define LED_GPIO_PORT GPIOA #define LED_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define LED_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() /** @addtogroup STM32F103_DEMO_Exported_Functions * @{ */ uint32_t BSP_GetVersion(void); void BSP_LED_Init(Led_TypeDef Led); void BSP_LED_On(Led_TypeDef Led); void BSP_LED_Off(Led_TypeDef Led); void BSP_LED_Toggle(Led_TypeDef Led); /** * @} */ /** * @} */ #ifdef __cplusplus } #endif #endif /* __STM32F103_DEMO_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

其他文件几乎不做改动,只需把引用stm32f10e_eval.h头文件的内容改为stm32f13_demo.h即可。需要注意的是PA15口在STM32正常运行时是用作调试接口的,因此需要禁止调试功能,这在BSP_LED_Init()函数中有体现,编译代码并下载到目标板。

在运行代码之前我们需要安装一个usb串口驱动:VCP_1.40_Setup,这个可以在ST官网上找到,有了它我们的USB在可以在主机上识别成一个串口,并可以使用串口操作,硬件连接完毕后我们可以通过设备管理器来查看到有两个串口,如下:

STM32 USB学习笔记2_第5张图片

COM5是单板实际的串口,而COM6看名字就晓得了,是USB虚拟出来的一个串口,打开两个串口终端,可以实现串口通信了,如下:

STM32 USB学习笔记2_第6张图片

STM32 USB学习笔记2_第7张图片

从COM5发送的信息可以在COM6中收到,同时从COM6中发送的信息可以在COM5中收到。同时该DEMO是支持串口波特率的修改的,我们将COM6和COM5的波特率改为57600,继续进行通信,依然是可以的,如下:

STM32 USB学习笔记2_第8张图片

STM32 USB学习笔记2_第9张图片

当然除去波特率以外,数据位、停止位、校验位都是可以正常修改的,有了这些直观性的功能描述会方便我们理解USB CDC类的使用,接下来就一步步分析一下VCP的代码实现吧。

首先分析物理硬件的处理吧,即stm32f1xx_hal_msp,c文件,该文件很简单只是初始化UART的IO资源,

/**
  ******************************************************************************
  * @file    USB_Device/CDC_Standalone/Src/stm32f1xx_hal_msp.c
  * @author  MCD Application Team
  * @version V1.2.0
  * @date    31-July-2015
  * @brief   HAL MSP module.
  ******************************************************************************
  * @attention
  *
  * 

© COPYRIGHT(c) 2015 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /** @addtogroup USBD_USER * @{ */ /** @defgroup USBD_USR_MAIN * @brief This file is the CDC application main file * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** * @brief UART MSP Initialization * This function configures the hardware resources used in this example: * - Peripheral's clock enable * - Peripheral's GPIO Configuration * - DMA configuration for transmission request by peripheral * - NVIC configuration for DMA interrupt request enable * @param huart: UART handle pointer * @retval None */ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { static DMA_HandleTypeDef hdma_tx; GPIO_InitTypeDef GPIO_InitStruct; /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable GPIO clock */ USARTx_TX_GPIO_CLK_ENABLE(); USARTx_RX_GPIO_CLK_ENABLE(); /* Enable USARTx clock */ USARTx_CLK_ENABLE(); /* Enable DMA clock */ DMAx_CLK_ENABLE(); /*##-2- Configure peripheral GPIO ##########################################*/ /* UART TX GPIO pin configuration */ GPIO_InitStruct.Pin = USARTx_TX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct); /* UART RX GPIO pin configuration */ GPIO_InitStruct.Pin = USARTx_RX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct); /*##-3- Configure the NVIC for UART ########################################*/ HAL_NVIC_SetPriority(USARTx_IRQn, 4, 0); HAL_NVIC_EnableIRQ(USARTx_IRQn); /*##-4- Configure the DMA channels ##########################################*/ /* Configure the DMA handler for Transmission process */ hdma_tx.Instance = USARTx_TX_DMA_STREAM; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_LOW; HAL_DMA_Init(&hdma_tx); /* Associate the initialized DMA handle to the UART handle */ __HAL_LINKDMA(huart, hdmatx, hdma_tx); /*##-5- Configure the NVIC for DMA #########################################*/ /* NVIC configuration for DMA transfer complete interrupt (USARTx_TX) */ HAL_NVIC_SetPriority(USARTx_DMA_TX_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USARTx_DMA_TX_IRQn); /*##-6- Enable TIM peripherals Clock #######################################*/ TIMx_CLK_ENABLE(); /*##-7- Configure the NVIC for TIMx ########################################*/ /* Set Interrupt Group Priority */ HAL_NVIC_SetPriority(TIMx_IRQn, 5, 0); /* Enable the TIMx global Interrupt */ HAL_NVIC_EnableIRQ(TIMx_IRQn); } /** * @brief UART MSP De-Initialization * This function frees the hardware resources used in this example: * - Disable the Peripheral's clock * - Revert GPIO, DMA and NVIC configuration to their default state * @param huart: UART handle pointer * @retval None */ void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) { /*##-1- Reset peripherals ##################################################*/ USARTx_FORCE_RESET(); USARTx_RELEASE_RESET(); /*##-2- Disable peripherals and GPIO Clocks #################################*/ /* Configure UART Tx as alternate function */ HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN); /* Configure UART Rx as alternate function */ HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN); /*##-3- Disable the NVIC for UART ##########################################*/ HAL_NVIC_DisableIRQ(USARTx_IRQn); /*##-4- Disable the NVIC for DMA ###########################################*/ HAL_NVIC_DisableIRQ(USARTx_DMA_TX_IRQn); /*##-5- Reset TIM peripheral ###############################################*/ TIMx_FORCE_RESET(); TIMx_RELEASE_RESET(); } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

这里使能了3个中断:UART1中断、DMA1通道4(UART_TX)中断、TIM3定时器中断。这些IO资源的初始化相对简单,清晰易懂,这里之所以初始化UARTIO资源是因为本DEMO实现的是USB转串口的功能,即把从UART口收到的数据从USB口发送出去,把从USB口收到的数据从UART口发送出去。有关USB口的IO资源的初始化是在另一个文件中。其中定时器的作用在另外的文件中有体现,虽然不清楚为啥把定时器的使能放在这里而不是跟它的初始化放在一起。。。

在通常情况下USB设备在D+、D-加上上拉电阻来检测设备的连接和断开事件,在例程中是使用一个IO来动态地拉高拉低,而我这里所购买的单板是没有接IO口的直接使用的1.5K上拉电阻,因此不再需要单独的IO口控制,如图:

STM32 USB学习笔记2_第10张图片

把usbd_conf.c文件中有关上拉电阻控制的代码去掉即可,涉及到HAL_PCD_MspInit()函数和HAL_PCDEx_SetConnectionState()两个函数,修改如下:

/**
  * @brief  Initializes the PCD MSP.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{
  GPIO_InitTypeDef  GPIO_InitStruct;
   
  /* Enable the GPIOA clock */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  /* Configure USB DM/DP pins */
  GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  /* Enable USB Clock */
  __HAL_RCC_USB_CLK_ENABLE();
    
  /* Set USB Interrupt priority */
  HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 7, 0);

  /* Enable USB Interrupt */
  HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
}

/**
  * @brief  Software Device Connection
  * @param  hpcd: PCD handle
  * @param  state: connection state (0 : disconnected / 1: connected)
  * @retval None
  */
void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
{
	
}

最后稍微修改下main函数中的Toggle_Leds()函数把累加计数器改为增加到1000后清零,即每隔1S翻转一次,如下:

/**
  * @brief  Toggle LEDs to shows user input state.
  * @param  None
  * @retval None
  */
void Toggle_Leds(void)
{
	static uint32_t ticks;

	if (ticks++ == 1000)
	{
		BSP_LED_Toggle(LED);
		ticks = 0;
	}
}

至此基本代码修改完毕,剩下的就是分析代码了。




你可能感兴趣的:(STM32,单片机)