芯片:STM32F407VE
编译器:KEIL5
作者:SY
日期:2017-9-18 09:56:00
使用 STM32_USB-Host-Device_Lib_V2.2.0
usb
库,将 stm32
作为 usb
设备,实现 usb
转串口的功能。
按照例程添加相关文件后测试,主机端使用 Windows7 X64
,可以正常识别 usb
设备,Windows
安装驱动后提示:驱动不能正常工作
。
可能是需要主机端安装 USB
转串口驱动。
网上搜索后,安装 stmcdc.ini
;------------------------------------------------------------------------------
; STMicroelectronics Comunication Device Class driver (CDC) INF FILE
; (C)2010 Copyright STMicroelectronics
;------------------------------------------------------------------------------
[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%PRVDR%
CatalogFile=stmcdc.cat
DriverVer=04/25/2010,1.3.1
[SourceDisksNames]
1=%DriversDisk%,,,
[SourceDisksFiles]
[Manufacturer]
%MFGNAME%=DeviceList,NT,NTamd64
[DestinationDirs]
DefaultDestDir = 12
;------------------------------------------------------------------------------
; VID/PID Settings
;------------------------------------------------------------------------------
[DeviceList.NT]
%DESCRIPTION%=DriverInstall,USB\VID_0483&PID_5740
[DeviceList.NTamd64]
%DESCRIPTION%=DriverInstall,USB\VID_0483&PID_5740
[DriverInstall.NT]
Include=mdmcpq.inf
CopyFiles=FakeModemCopyFileSection
AddReg=DriverInstall.NT.AddReg
[DriverInstall.NT.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[DriverInstall.NT.Services]
AddService=usbser, 0x00000002, DriverServiceInst
[DriverServiceInst]
DisplayName=%SERVICE%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary= %12%\usbser.sys
LoadOrderGroup = Base
;------------------------------------------------------------------------------
; String Definitions
;------------------------------------------------------------------------------
[Strings]
PRVDR = "STMicroelectronics"
MFGNAME = "STMicroelectronics."
DESCRIPTION = "STMicroelectronics Virtual COM Port"
SERVICE = "STM Virtual COM Port"
DriversDisk = "STM Drivers Disk"
测试驱动还是不能正常工作
网上搜索发现有驱动安装包的形式:VCP_V1.4.0_Setup.exe
,遂安装,发现还是不能正常工作。
怀疑可能是从机没有移植好,采用 STM32CubeMX
软件自动生成一份下位机程序,测试下来还是和以前移植的程序现象一样
网上搜索原因:stm32的usb虚拟串口驱动win7系统64位和32位不能正常安装的解决办法!stm32 virtual comport win7(终极解决办法) ,原来是 malloc
内存分配失败,扩大堆内存后,终于驱动安装成功了!
既然 STM32CubeMX
可以成功,应该问题就是出在初始化阶段,仿真仔细排查:
uint8_t usbd_cdc_Init (void *pdev,
uint8_t cfgidx)
{
uint8_t *pbuf;
/* Open EP IN */
DCD_EP_Open(pdev,
CDC_IN_EP,
CDC_DATA_IN_PACKET_SIZE,
USB_OTG_EP_BULK);
}
隐约感觉 CDC_DATA_IN_PACKET_SIZE
可能会有问题,查看来源:
#define CDC_DATA_IN_PACKET_SIZE CDC_DATA_MAX_PACKET_SIZE
#define CDC_DATA_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */
问题应该出在这里了,我的 usb
使用的是 usb-hs
高速接口,但是物理层仍然使用内部的 phy
,这样使用起来简单,但是最大速度只能达到全速的速度12Mbps
,而全速设备的最大包大小为 64
字节。修改后,测试终于成功了。而且不需要安装任何第三方驱动!
移植过程中最终要的文件:usbd_cdc_vcp.c
/**
******************************************************************************
* @file usbd_cdc_vcp.c
* @author MCD Application Team
* @version V1.2.0
* @date 09-November-2015
* @brief Generic media access Layer.
******************************************************************************
* @attention
*
* © COPYRIGHT 2015 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#pragma data_alignment = 4
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_vcp.h"
#include "stm32f4xx.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
LINE_CODING linecoding =
{
115200, /* baud rate*/
0x00, /* stop bits-1*/
0x00, /* parity - none*/
0x08 /* nb. of bits 8*/
};
USART_InitTypeDef USART_InitStructure;
/* These are external variables imported from CDC core to be used for IN
transfer management. */
extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer.
These data will be sent over USB IN endpoint
in the CDC core functions. */
extern uint32_t APP_Rx_ptr_in; /* Increment this pointer or roll it back to
start address when writing received data
in the buffer APP_Rx_Buffer. */
/* Private function prototypes -----------------------------------------------*/
static uint16_t VCP_Init (void);
static uint16_t VCP_DeInit (void);
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
static uint16_t VCP_DataTx (void);
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len);
static uint16_t VCP_COMConfig(uint8_t Conf);
CDC_IF_Prop_TypeDef VCP_fops =
{
VCP_Init,
VCP_DeInit,
VCP_Ctrl,
VCP_DataTx,
VCP_DataRx
};
static uint8_t g_RxByte;
/* Private functions ---------------------------------------------------------*/
/**
* @brief VCP_Init
* Initializes the Media on the STM32
* @param None
* @retval Result of the operation (USBD_OK in all cases)
*/
static uint16_t VCP_Init(void)
{
return USBD_OK;
}
/**
* @brief VCP_DeInit
* DeInitializes the Media on the STM32
* @param None
* @retval Result of the operation (USBD_OK in all cases)
*/
static uint16_t VCP_DeInit(void)
{
return USBD_OK;
}
/**
* @brief VCP_Ctrl
* Manage the CDC class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the operation (USBD_OK in all cases)
*/
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
{
switch (Cmd)
{
case SEND_ENCAPSULATED_COMMAND:
/* Not needed for this driver */
break;
case GET_ENCAPSULATED_RESPONSE:
/* Not needed for this driver */
break;
case SET_COMM_FEATURE:
/* Not needed for this driver */
break;
case GET_COMM_FEATURE:
/* Not needed for this driver */
break;
case CLEAR_COMM_FEATURE:
/* Not needed for this driver */
break;
case SET_LINE_CODING:
linecoding.bitrate = (uint32_t)(Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24));
linecoding.format = Buf[4];
linecoding.paritytype = Buf[5];
linecoding.datatype = Buf[6];
/* Set the new configuration */
VCP_COMConfig(OTHER_CONFIG);
break;
case GET_LINE_CODING:
Buf[0] = (uint8_t)(linecoding.bitrate);
Buf[1] = (uint8_t)(linecoding.bitrate >> 8);
Buf[2] = (uint8_t)(linecoding.bitrate >> 16);
Buf[3] = (uint8_t)(linecoding.bitrate >> 24);
Buf[4] = linecoding.format;
Buf[5] = linecoding.paritytype;
Buf[6] = linecoding.datatype;
break;
case SET_CONTROL_LINE_STATE:
/* Not needed for this driver */
break;
case SEND_BREAK:
/* Not needed for this driver */
break;
default:
break;
}
return USBD_OK;
}
/**
* @brief VCP_DataTx
* CDC received data to be send over USB IN endpoint are managed in
* this function.
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else VCP_FAIL
*/
static uint16_t VCP_DataTx (void)
{
if (linecoding.datatype == 7)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = g_RxByte & 0x7F;
}
else if (linecoding.datatype == 8)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = g_RxByte;
}
APP_Rx_ptr_in++;
/* To avoid buffer overflow */
if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
{
APP_Rx_ptr_in = 0;
}
return USBD_OK;
}
/**
* @brief VCP_DataRx
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* until exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else VCP_FAIL
*/
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
{
for (uint32_t i=0; ireturn USBD_OK;
}
/**
* @brief VCP_COMConfig
* Configure the COM Port with default values or values received from host.
* @param Conf: can be DEFAULT_CONFIG to set the default configuration or OTHER_CONFIG
* to set a configuration received from the host.
* @retval None.
*/
static uint16_t VCP_COMConfig(uint8_t Conf)
{
return USBD_OK;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
实现的功能是做一个loopback
测试,只要收到数据立刻发出去。
实际测试下来,波特率设置为 256000bps
,按照 1ms
定时发送,发送:13227744byte
接收:13227744byte
没有丢失数据。
usb
转串口总是被大家认为是不稳定,原因就是在 usb
线拔掉后,串口也随之消失。原来操作系统为串口分配的内存等资源也没有被正确的释放,再将串口线插回去时,会出现打开串口失败!
下面提出操作 USB
转串口的正确方式:
usb
线,打开主机端串口;使用完毕后关闭串口,拔掉 usb
线usb
线,打开主机端串口;拔掉 usb
线,关闭串口;插上 usb
线,打开串口失败的方式:
usb
线,打开主机端串口;拔掉 usb
线,插上 usb
线;主机发送数据失败usb
线,打开主机端串口;拔掉 usb
线,插上 usb
线;关闭串口,打开串口;主机发送数据失败