主機環境:Windows 7 SP1
開發環境:MDK5.14
目標板:STM32F103C8T6
開發庫:STM32F1Cube庫和STM32_USB_Device_Library
STM32Cube庫中提供了一些有關USB的例程,在其工程目錄下的Applications目錄中,這裏打開STM3210E_EVAL目錄,可以看到如下例程:
這裏選取一個簡單的例子CDC_Standalone,爲一個USB通信例程,具體實現是一個USB轉串口的功能,相當於USB串口線。把示例裏面的inc和src目錄下的文件拷貝到新建工程中,這裏是把跟usb通信相關的文件放到了vcp目錄下。文件目錄結構如下:
其中BSP目錄很簡單,由於所購買的單板只用到了USB,UART模塊以及一個LED燈,原理圖如下:
其中PA15引腳連接了一個LED燈,如下:
因此在stm32f103_demo文件中只添加了led的操作,源文件如下:
<pre name="code" class="cpp">/**
******************************************************************************
* @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
*
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* 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
*
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* 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在可以在主機上識別成一個串口,並可以使用串口操作,硬件連接完畢後我們可以通過設備管理器來查看到有兩個串口,如下:
COM5是單板實際的串口,而COM6看名字就曉得了,是USB虛擬出來的一個串口,打開兩個串口終端,可以實現串口通信了,如下:
從COM5發送的信息可以在COM6中收到,同時從COM6中發送的信息可以在COM5中收到。同時該DEMO是支持串口波特率的修改的,我們將COM6和COM5的波特率改爲57600,繼續進行通信,依然是可以的,如下:
當然除去波特率以外,數據位、停止位、校驗位都是可以正常修改的,有了這些直觀性的功能描述會方便我們理解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
*
* <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* 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口控制,如圖:
把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;
}
}
至此基本代碼修改完畢,剩下的就是分析代碼了。