usb CDC

usb CDC

STM32F4 USB HOST VPC主机无法读取到从机发来的数据

问题困惑守护 回复了问题 • 2 人关注 • 1 个回复 • 338 次浏览 • 2019-08-10 10:24 • 来自相关话题

STM32F4的USB CDC问题

问题困惑admin 回复了问题 • 3 人关注 • 1 个回复 • 387 次浏览 • 2019-04-29 16:49 • 来自相关话题

(直播)分析老外的关于stm32的usb虚拟串口程序,体会配置方法和实现流程

经验分享 回复了问题 • 15 人关注 • 16 个回复 • 23971 次浏览 • 2019-04-25 14:28 • 来自相关话题

终于利用stm32cube生成了usb虚拟串口程序并初步调试通过,分享代码和配置先!!

软件教程jreeyssss 回复了问题 • 84 人关注 • 34 个回复 • 52606 次浏览 • 2019-03-05 19:09 • 来自相关话题

(转)HID+CDC复合设备在WIN10的识别问题

经验分享admin 发表了文章 • 0 个评论 • 2153 次浏览 • 2018-06-17 09:20 • 来自相关话题

1 问题现象有客户使用STM32F405并参照ST官方USB标准库下的HID+CDC的示例代码做产品,发现在WIN7上使用得好好的,可放到WIN10上,CDC第一次能够识别,再次拔插后就不能再识别,且此后无论插拔多少次都无法再识别,除非再次上电,又会重复上述现象,只有板子上电后第一次才能正确被识别,后续均不行。2 问题分析客户使用 ST官方示例代码STM32_USB-Host-Device_Lib_V2.2.0\Project\USB_Device_Examples\Composite_Examples\CDC_HID_Composite(下载页面:http://www.stmicroelectronics.com.cn/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32046.html)当我尝试使用此示例代码重现客户所遇到的问题时,发现此代码在WIN7运行OK,但与客户不同的是,我测试到的情况是在WIN10下CDC一次都无法识别,HID却一直可以识别。下面来分析下问题,既然WIN7下HID和CDC都能正常识别,放在WIN10上才不正常,那么初步可以判断,此问题可能与WIN10操作系统的USB主机驱动实现有关。通过USB分析仪分析客户代码在WIN10下USB枚举异常的数据通讯:Figure 1 第一次USB枚举过程上图是客户代码第一次正常枚举的通讯数据,从图中可以看出,WIN10 USB主机在正常获取HID报告描述符后,紧接着会获取虚拟串口状态和设置波特率,这样就正常枚举结束了。我们再来看看采集到的异常USB枚举过程:Figure 2 异常枚举过程上图是WIN10下异常枚举过程。从图中可以看出,WIN10系统上USB主机在获取到设备描述符和配置描述符后直接将设备挂起了。很明显,WIN10系统的USB主机驱动实现对设备描述符或者配置描述符的内容并不认可,才会导致无法识别HID+CDC复合设备。我们不妨检查下客户代码中的设备描述符:Figure 3 获取的设备描述符复合设备的class,subclass,protocol必须为0xef,0x02,0x01,这里VID=0x0483,PID=0x3256(Cube库下为0x5740,但这个不重要),接下来看配置描述符:Figure 4 win10不能识别的配置描述符由此可见,客户的描述符是HID interface + IAD + CDC interfaces结构。对于WIN7,这种结构可以识别,但对于WIN10,这种结构WIN10未必能够兼容,我们尝试在HID interface外部加上一层IAD结构,使其成为IAD1 + HID interface + IAD2 + CDC interfaces结构,此时客户的问题得以解决,在WIN10也可以正确识别了,修改后的描述符结构如下:Figure 5 win10能够正确识别的配置描述符结束本篇实战经验之前,让我们再次回顾IAD的概念:IAD(Interface Association Descriptor),为USB设备定义了一个标准来表述捆绑在一个逻辑功能(比如这里的CDC虚拟串口)上的多个接口的聚合的方法。USB协会分配了一个设备级别的类编码(即图3中0xEF),使用IAD的设备必须使用它(如图3的设备描述符);这样可以很容易在设备枚举时就能识别出采用了IAD的设备。IAD描述符通常放在它所要捆绑的多个接口的接口描述符之前。3 结论 在WIN10系统中,建议复合设备每个逻辑功能的接口描述符前都搭载一个IAD描述符,不论这个逻辑功能是单个接口描述符完成(比如这里的HID功能)还是要由多个接口描述符完成(比如这里的CDC功能)。本文转自:https://mp.weixin.qq.com/s/9ot9AVTN4zSMAyudVDeMzA 感谢【STM32单片机】分享的经验。 查看全部

1 问题现象

有客户使用STM32F405并参照ST官方USB标准库下的HID+CDC的示例代码做产品,发现在WIN7上使用得好好的,可放到WIN10上,CDC第一次能够识别,再次拔插后就不能再识别,且此后无论插拔多少次都无法再识别,除非再次上电,又会重复上述现象,只有板子上电后第一次才能正确被识别,后续均不行。

2 问题分析

客户使用 ST官方示例代码

STM32_USB-Host-Device_Lib_V2.2.0\Project\USB_Device_Examples\Composite_Examples\CDC_HID_Composite

(下载页面:

http://www.stmicroelectronics.com.cn/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32046.html)

当我尝试使用此示例代码重现客户所遇到的问题时,发现此代码在WIN7运行OK,但与客户不同的是,我测试到的情况是在WIN10下CDC一次都无法识别,HID却一直可以识别。


下面来分析下问题,既然WIN7下HID和CDC都能正常识别,放在WIN10上才不正常,那么初步可以判断,此问题可能与WIN10操作系统的USB主机驱动实现有关。

通过USB分析仪分析客户代码在WIN10下USB枚举异常的数据通讯:

捕获.PNG

Figure 1 第一次USB枚举过程


上图是客户代码第一次正常枚举的通讯数据,从图中可以看出,WIN10 USB主机在正常获取HID报告描述符后,紧接着会获取虚拟串口状态和设置波特率,这样就正常枚举结束了。我们再来看看采集到的异常USB枚举过程:

捕获2.PNG

Figure 2 异常枚举过程


上图是WIN10下异常枚举过程。从图中可以看出,WIN10系统上USB主机在获取到设备描述符和配置描述符后直接将设备挂起了。很明显,WIN10系统的USB主机驱动实现对设备描述符或者配置描述符的内容并不认可,才会导致无法识别HID+CDC复合设备。

我们不妨检查下客户代码中的设备描述符:

捕获3.PNG

Figure 3 获取的设备描述符


复合设备的class,subclass,protocol

必须为0xef,0x02,0x01,这里

VID=0x0483,PID=0x3256(Cube库下为0x5740,但这个不重要),接下来看配置描述符:

4.jpg

Figure 4 win10不能识别的配置描述符


由此可见,客户的描述符是HID interface + IAD + CDC interfaces结构。对于WIN7,这种结构可以识别,但对于WIN10,这种结构WIN10未必能够兼容,我们尝试在HID interface外部加上一层IAD结构,使其成为IAD1 + HID interface + IAD2 + CDC interfaces结构,此时客户的问题得以解决,在WIN10也可以正确识别了,修改后的描述符结构如下:

5.jpg

Figure 5 win10能够正确识别的配置描述符


结束本篇实战经验之前,让我们再次回顾IAD的概念:

IAD(Interface Association Descriptor),为USB设备定义了一个标准来表述捆绑在一个逻辑功能(比如这里的CDC虚拟串口)上的多个接口的聚合的方法。USB协会分配了一个设备级别的类编码(即图3中0xEF),使用IAD的设备必须使用它(如图3的设备描述符);这样可以很容易在设备枚举时就能识别出采用了IAD的设备。IAD描述符通常放在它所要捆绑的多个接口的接口描述符之前


3 结论

在WIN10系统中,建议复合设备每个逻辑功能的接口描述符前都搭载一个IAD描述符,不论这个逻辑功能是单个接口描述符完成(比如这里的HID功能)还是要由多个接口描述符完成(比如这里的CDC功能)。


本文转自:https://mp.weixin.qq.com/s/9ot9AVTN4zSMAyudVDeMzA

感谢【STM32单片机】分享的经验。

抛砖引玉:一步一步Hal库学习usb虚拟串口功能CDC或者叫VCP

软件教程星期五 回复了问题 • 46 人关注 • 22 个回复 • 32540 次浏览 • 2018-03-03 19:05 • 来自相关话题

STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+USB 虚拟串口+SD卡、串行Flash模拟U盘

经验分享开始现在-s 发表了文章 • 1 个评论 • 2784 次浏览 • 2017-12-11 13:59 • 来自相关话题

首先说明下开发条件:1、开发板:秉火霸道,STM32F103ZET2、软件:Cubemx V4.23(F1 V1.60库)3、硬件: STM32模拟USB设备:虚拟串口 CDC、HID、MSC问题描述: 官方生成的代码有的人说电脑没有反应,不会出现USB设备!解决办法:1、查看硬件原理图    注意D+要设置为高电平,全速USB,这时候需要PD3引脚为低电平,当然了你也可以在软件里设置DP为上拉,可惜最新的1.6库是无法设置DP引脚的,所以需要我们自己根据自己的硬件原理图查看下,DP引脚是否上拉为3.3V!    也有人说是Vbus引脚的问题,应该在设置里面把Vbus失效不使能,可惜1.6的库没有这个设置,好在我硬件里面已经上拉为5V,将Vbus失效了!    2、USB虚拟串口:主要就是使用CDC_Receive_FS( UserRxBuffer,(uint32_t *)(sizeof(UserRxBuffer)));和    CDC_Transmit_FS((uint8_t*)UserRxBuffer,sizeof(UserRxBuffer));这两个函数,感觉不好用,纯粹属于测试,发送和接收成功,感兴趣可以自己研究!    3、HID测试成功,正常读取 polling_interval=USBD_HID_GetPollingInterval(&hUsbDeviceFS);数值,至于具体怎么使用没有深入研究。    4、SD卡模拟U盘:    主要修改生成的usbd_storage_if.c文件里面STORAGE_Read_FS()和STORAGE_Write_FS()函数,注意blk_addr 不需要乘以512(SD卡一个块为512字节),因为不同版本库之间有的乘以512,有的不乘,但是最新的1.6库是不需要乘以512的,blk_addr 就是起始地址的意思,而blk_len表示是读多少块,而不是读多少字节数,大家一定注意!    HAL_SD_WriteBlocks(&hsd, (uint8_t *)buf, blk_addr , blk_len, 1000)    HAL_SD_ReadBlocks(&hsd,(uint8_t *)buf, blk_addr , blk_len, 1000)    5、SPIFLASH模拟U盘暂时没有成功,可能是自己板子的flash有问题,出现无法格式化的情况,还需要继续研究,也希望已经搞好的朋友分享一下!    6、联系方式:微信Startingray,本人准备将cubemx的小bug解决的过程记录下来,也是给爱好者一点启示,欢迎微信和我沟通,共同进步!个人觉得Cubemx是未来的发展方向,可以使我们避免很多小错误,但是由于现在软件版本之间的兼容性,加上不同版本库之间存在的bug,还是需要我们在使用时时刻保持警惕! 查看全部

首先说明下开发条件:

1、开发板:秉火霸道,STM32F103ZET

2、软件:Cubemx V4.23(F1 V1.60库)

3、硬件: STM32模拟USB设备:虚拟串口 CDC、HID、MSC

问题描述: 官方生成的代码有的人说电脑没有反应,不会出现USB设备!

解决办法:

1、查看硬件原理图

捕获.JPG

    注意D+要设置为高电平,全速USB,这时候需要PD3引脚为低电平,当然了你也可以在软件里设置DP为上拉,可惜最新的1.6库是无法设置DP引脚的,所以需要我们自己根据自己的硬件原理图查看下,DP引脚是否上拉为3.3V!

    也有人说是Vbus引脚的问题,应该在设置里面把Vbus失效不使能,可惜1.6的库没有这个设置,好在我硬件里面已经上拉为5V,将Vbus失效了!


    2、USB虚拟串口:

主要就是使用CDC_Receive_FS( UserRxBuffer,(uint32_t *)(sizeof(UserRxBuffer)));和

   CDC_Transmit_FS((uint8_t*)UserRxBuffer,sizeof(UserRxBuffer));这两个函数,感觉不好用,纯粹属于测试,发送和接收成功,感兴趣可以自己研究!


    3、HID测试成功,正常读取 polling_interval=USBD_HID_GetPollingInterval(&hUsbDeviceFS);数值,至于具体怎么使用没有深入研究。


    4、SD卡模拟U盘:

    主要修改生成的usbd_storage_if.c文件里面STORAGE_Read_FS()和STORAGE_Write_FS()函数,注意blk_addr 不需要乘以512(SD卡一个块为512字节),因为不同版本库之间有的乘以512,有的不乘,但是最新的1.6库是不需要乘以512的,blk_addr 就是起始地址的意思,而blk_len表示是读多少块,而不是读多少字节数,大家一定注意!

    HAL_SD_WriteBlocks(&hsd, (uint8_t *)buf, blk_addr , blk_len, 1000)

    HAL_SD_ReadBlocks(&hsd,(uint8_t *)buf, blk_addr , blk_len, 1000)


    5、SPIFLASH模拟U盘暂时没有成功,可能是自己板子的flash有问题,出现无法格式化的情况,还需要继续研究,也希望已经搞好的朋友分享一下!


    6、联系方式:微信Startingray,本人准备将cubemx的小bug解决的过程记录下来,也是给爱好者一点启示,欢迎微信和我沟通,共同进步!个人觉得Cubemx是未来的发展方向,可以使我们避免很多小错误,但是由于现在软件版本之间的兼容性,加上不同版本库之间存在的bug,还是需要我们在使用时时刻保持警惕!



stmcdc.inf文件(虚拟串口驱动文件)

回复

其他分享admin 回复了问题 • 3 人关注 • 1 个回复 • 5257 次浏览 • 2016-09-27 20:42 • 来自相关话题

记录一个移植F4usb虚串VCP到F103的CDC时候的一个问题

经验分享idfulin 回复了问题 • 4 人关注 • 4 个回复 • 2642 次浏览 • 2016-04-12 18:55 • 来自相关话题

分享国外文章 : 建立一个基于USB_CDC的工程为STM32F4Discovery(建立usb虚拟串口),非常详细,值得借鉴!

其他分享admin 发表了文章 • 3 个评论 • 3551 次浏览 • 2015-02-13 15:15 • 来自相关话题

文章名:Making a basic USB CDC project for STM32F4Discovery
摘录:
This tutorial shows how to create a basic USB communication device using the STM32F4Discovery board. The USB protocol stack implementation is contained in the STM32CubeF4 firmware package, however to get a complete project you need to either use the Stm32Cube MX tool to generate it, or assemble it from different components in the firmware package. In this tutorial we will use the second way.
这篇教程是是基于他们官方的软件来写的,名字是VisualGDB 4.2,这个就是一个viral studio的外挂插件,安装后类似于keil的编译器,很强大,我试了一下,就是用着不习惯,呵呵

关于他的插件的用法咱们不去追究,只看CDC怎么从stm32cubemx的软件包提供的模板,去完成一个实用的usb_CDC功能.

不过,对这个软件插件有兴趣的可以安装使用一下, 大小只有5M
但是安装后会提示安装一些stm32的驱动,大概也有10M,
和谐版安装包已经发布在本站网盘,名字是: VisualGDB-4.2r4.rar

这篇文章的PDF版本同时也放在了VisualGDB-4.2r4.rar文件中!

插件安装完成后,将文件夹内的Crack里面的文件,复制到安装目录就行了.
具体自己百度......

文章地址: usb cdc工程完整演示

如果以上地址打不开,可以到本论坛网盘里下载PDF文档,
文档名称:Making a basic USB CDC project for STM32F4Discovery _ VisualGDB Tutorials.pdf
下面是我摘抄的部分代码, 人家国外写代码真心漂亮!

1.Now that the basic project is working, we will add the USB protocol implementation from ST. The USB implementation consists of 3 parts:
USB core protocol implementation
USB CDC device class (virtual COM port)
USB configuration (descriptors and hardware mappings)




[]Select the STM32_USB_Device_Library\Core directory from the STM32CubeF4 package. Select 'copy folder to project with subpath' and enter 'USB' as the subpath:[/]
3.Press OK. The core files will be copied and imported to Solution Explorer. Import the Class\CDC directory from the STM32CubeF4 package in a similar way:


4.Finally we need to copy USB configuration files. A sample CDC project can be found under Projects\STM324x9I_EVAL\Applications\USB_Device\CDC_Standalone in the STM32CubeF4 package. Copy usb_conf and usb_desc sources from the src directory and their counterparts from the inc directory. Add them to the project and delete the usbd_conf_template.h and usbd_conf_template.c files from the USB\core folder as they are now replaced by actual configuration files. When you're done, the Solution Explorer should look the following way:

5.Finally we need to add the directories with the copied include files to the include directory list and ensure the usb_conf.c file uses the USB peripheral in FS mode (HS is not supported on STM32F407). Open VisualGDB Project Properties, add the 'USE_USB_FS' macro to Preprocessor Macros and the '.', 'USB/Core/Inc' and 'USB/CDED/Inc' directories to Include Directories (don't use the backward slash ('\')):


6.Now it's the time to start using the imported USB code from main(). Replace the main() function with the following code (do not remove SysTick_Handler):


extern "C"
{
#include <usbd_core.h>
#include <usbd_cdc.h>
#include <usbd_cdc_if_template.h>
#include <usbd_desc.h>

USBD_HandleTypeDef USBD_Device;
}

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

int main(void)
{
HAL_Init();
SystemClock_Config();
USBD_Init(&USBD_Device, &VCP_Desc, 0);

USBD_RegisterClass(&USBD_Device, &USBD_CDC);
USBD_CDC_RegisterInterface(&USBD_Device,
&USBD_CDC_Template_fops);
USBD_Start(&USBD_Device);

for (;;) ;
}

++++++++++++++++++++++++++++++++
Note that the PLL values above are valid for the 8 MHz crystal on the STM32F4Discovery board. If you are using a different crystal, you will need to modify the values.

7.Two last things to do before we can test our device is to implement the _sbrk() function that tells the C library the location of the heap and provide the USB OTG interrupt handler that will call the corresponding handler of the ST USB library:


extern "C"
{
caddr_t _sbrk(int increment)
{
extern char end asm("end");
register char *pStack asm("sp");

static char *s_pHeapEnd;

if (!s_pHeapEnd)
s_pHeapEnd = &end;

if (s_pHeapEnd + increment > pStack)
return (caddr_t)-1;

char *pOldHeapEnd = s_pHeapEnd;
s_pHeapEnd += increment;
return (caddr_t)pOldHeapEnd;
}

extern PCD_HandleTypeDef hpcd;

void OTG_FS_IRQHandler(void)
{
HAL_PCD_IRQHandler(&hpcd);
}
}

8.Build the project again. Note how the FLASH footprint increased from 2.6KB to 23KB as the USB code is now included in the binary:


9.Connect your board using both USB sockets. Note that the mini-USB socket is needed for JTAG debugging and the micro-USB socket is connected to the STM32F407 microcontroller itself:



10.Press Ctrl-F5 to program the device without debugging it. The Device Manager should now show 2 instances of the port. Each instance corresponds to one of 2 interfaces reported by the ST library (see the definition of USBD_CDC_CfgFSDesc):



11.Although the ST USB library implements the standard USB CDC class and Windows has drivers for it, it will not recognize the device without an inf file specifying which driver to use. Download and install the STM32 VCP drivers to get Windows to recognize your device. Take a note of the COM port number assigned to the device:
这个VCP驱动本站已经上传到网盘, 分为X86系统盒X64系统,自己看着下载啊,别下错!


12.Now we will add some basic functionality to our project. We will make a variation of a simple 'echo' application. First of all modify the TEMPLATE_Init() function in usbd_cdc_if_template.c to set a receive buffer:


extern USBD_HandleTypeDef USBD_Device;

static struct
{
uint8_t Buffer[CDC_DATA_HS_OUT_PACKET_SIZE];
int Position, Size;
char ReadDone;
} s_RxBuffer;

char g_VCPInitialized;

static int8_t TEMPLATE_Init(void)
{
USBD_CDC_SetRxBuffer(&USBD_Device, s_RxBuffer.Buffer);
g_VCPInitialized = 1;
return (0);
}


13.Then modify TEMPLATE_Receive() that is called from an interrupt handler to store received data in our buffer:


static int8_t TEMPLATE_Receive (uint8_t[i] Buf, uint32_t [/i]Len)
{
s_RxBuffer.Position = 0;
s_RxBuffer.Size = *Len;
s_RxBuffer.ReadDone = 1;
return (0);
}


14.Then add basic read and write functions:


int VCP_read(void *pBuffer, int size)
{
if (!s_RxBuffer.ReadDone)
return 0;

int remaining = s_RxBuffer.Size - s_RxBuffer.Position;
int todo = MIN(remaining, size);
if (todo <= 0)
return 0;

memcpy(pBuffer, s_RxBuffer.Buffer + s_RxBuffer.Position, todo);
s_RxBuffer.Position += todo;
if (s_RxBuffer.Position >= s_RxBuffer.Size)
{
s_RxBuffer.ReadDone = 0;
USBD_CDC_ReceivePacket(&USBD_Device);
}

return todo;
}

int VCP_write(const void *pBuffer, int size)
{
if (size > CDC_DATA_HS_OUT_PACKET_SIZE)
{
int offset;
for (offset = 0; offset < size; offset++)
{
int todo = MIN(CDC_DATA_HS_OUT_PACKET_SIZE,
size - offset);
int done = VCP_write(((char *)pBuffer) + offset, todo);
if (done != todo)
return offset + done;
}

return size;
}

USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)USBD_Device.pClassData;
while(pCDC->TxState) { } //Wait for previous transfer

USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)pBuffer, size);
if (USBD_CDC_TransmitPacket(&USBD_Device) != USBD_OK)
return 0;

while(pCDC->TxState) { } //Wait until transfer is done
return size;
}


15.Add the prototypes of the new functions and the initialization flag to usb_cdc_if_template.h:


int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);
extern char g_VCPInitialized;

+++++++++++++++++++++++++++++++++
Note that the current code will use the receive buffer for one packet only and wait for the entire transmission to complete before returning. This is slow and inefficient compared to a pair of ring buffers and is only shown here do to extreme simplicity.

16.The ST's USBD_CDC_TransmitPacket() function contains a bug: it sets the 'transmission in progress' flag AFTER starting the actual transmission, so if the 'transmission done' interrupt happens too early, the flag will be set AFTER the interrupt and hence will never be cleared. To fix this, move "hcdc->TxState = 1" line before the call to USBD_LL_Transmit():


if(hcdc->TxState == 0)
{
hcdc->TxState = 1;

USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer,
hcdc->TxLength);
return USBD_OK;
}


17.Finally replace the empty loop in main() with the following code:


char byte;
for (;;)
{
if (VCP_read(&byte, 1) != 1)
continue;
VCP_write("\r\nYou typed ", 12);
VCP_write(&byte, 1);
VCP_write("\r\n", 2);
}

后面还有一点,不过,不用他的插件的话,就用不上! 查看全部
文章名:Making a basic USB CDC project for STM32F4Discovery
摘录:
This tutorial shows how to create a basic USB communication device using the STM32F4Discovery board. The USB protocol stack implementation is contained in the STM32CubeF4 firmware package, however to get a complete project you need to either use the Stm32Cube MX tool to generate it, or assemble it from different components in the firmware package. In this tutorial we will use the second way.
这篇教程是是基于他们官方的软件来写的,名字是VisualGDB 4.2,这个就是一个viral studio的外挂插件,安装后类似于keil的编译器,很强大,我试了一下,就是用着不习惯,呵呵

关于他的插件的用法咱们不去追究,只看CDC怎么从stm32cubemx的软件包提供的模板,去完成一个实用的usb_CDC功能.

不过,对这个软件插件有兴趣的可以安装使用一下, 大小只有5M
但是安装后会提示安装一些stm32的驱动,大概也有10M,
和谐版安装包已经发布在本站网盘,名字是: VisualGDB-4.2r4.rar

这篇文章的PDF版本同时也放在了VisualGDB-4.2r4.rar文件中!

插件安装完成后,将文件夹内的Crack里面的文件,复制到安装目录就行了.
具体自己百度......

文章地址: usb cdc工程完整演示

如果以上地址打不开,可以到本论坛网盘里下载PDF文档,
文档名称:Making a basic USB CDC project for STM32F4Discovery _ VisualGDB Tutorials.pdf
下面是我摘抄的部分代码, 人家国外写代码真心漂亮!

1.Now that the basic project is working, we will add the USB protocol implementation from ST. The USB implementation consists of 3 parts:
USB core protocol implementation
USB CDC device class (virtual COM port)
USB configuration (descriptors and hardware mappings)




    []Select the STM32_USB_Device_Library\Core directory from the STM32CubeF4 package. Select 'copy folder to project with subpath' and enter 'USB' as the subpath:[/]

3.Press OK. The core files will be copied and imported to Solution Explorer. Import the Class\CDC directory from the STM32CubeF4 package in a similar way:


4.Finally we need to copy USB configuration files. A sample CDC project can be found under Projects\STM324x9I_EVAL\Applications\USB_Device\CDC_Standalone in the STM32CubeF4 package. Copy usb_conf and usb_desc sources from the src directory and their counterparts from the inc directory. Add them to the project and delete the usbd_conf_template.h and usbd_conf_template.c files from the USB\core folder as they are now replaced by actual configuration files. When you're done, the Solution Explorer should look the following way:

5.Finally we need to add the directories with the copied include files to the include directory list and ensure the usb_conf.c file uses the USB peripheral in FS mode (HS is not supported on STM32F407). Open VisualGDB Project Properties, add the 'USE_USB_FS' macro to Preprocessor Macros and the '.', 'USB/Core/Inc' and 'USB/CDED/Inc' directories to Include Directories (don't use the backward slash ('\')):


6.Now it's the time to start using the imported USB code from main(). Replace the main() function with the following code (do not remove SysTick_Handler):


extern "C"
{
#include <usbd_core.h>
#include <usbd_cdc.h>
#include <usbd_cdc_if_template.h>
#include <usbd_desc.h>

USBD_HandleTypeDef USBD_Device;
}

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

int main(void)
{
HAL_Init();
SystemClock_Config();
USBD_Init(&USBD_Device, &VCP_Desc, 0);

USBD_RegisterClass(&USBD_Device, &USBD_CDC);
USBD_CDC_RegisterInterface(&USBD_Device,
&USBD_CDC_Template_fops);
USBD_Start(&USBD_Device);

for (;;) ;
}

++++++++++++++++++++++++++++++++
Note that the PLL values above are valid for the 8 MHz crystal on the STM32F4Discovery board. If you are using a different crystal, you will need to modify the values.

7.Two last things to do before we can test our device is to implement the _sbrk() function that tells the C library the location of the heap and provide the USB OTG interrupt handler that will call the corresponding handler of the ST USB library:


extern "C"
{
caddr_t _sbrk(int increment)
{
extern char end asm("end");
register char *pStack asm("sp");

static char *s_pHeapEnd;

if (!s_pHeapEnd)
s_pHeapEnd = &end;

if (s_pHeapEnd + increment > pStack)
return (caddr_t)-1;

char *pOldHeapEnd = s_pHeapEnd;
s_pHeapEnd += increment;
return (caddr_t)pOldHeapEnd;
}

extern PCD_HandleTypeDef hpcd;

void OTG_FS_IRQHandler(void)
{
HAL_PCD_IRQHandler(&hpcd);
}
}

8.Build the project again. Note how the FLASH footprint increased from 2.6KB to 23KB as the USB code is now included in the binary:


9.Connect your board using both USB sockets. Note that the mini-USB socket is needed for JTAG debugging and the micro-USB socket is connected to the STM32F407 microcontroller itself:



10.Press Ctrl-F5 to program the device without debugging it. The Device Manager should now show 2 instances of the port. Each instance corresponds to one of 2 interfaces reported by the ST library (see the definition of USBD_CDC_CfgFSDesc):



11.Although the ST USB library implements the standard USB CDC class and Windows has drivers for it, it will not recognize the device without an inf file specifying which driver to use. Download and install the STM32 VCP drivers to get Windows to recognize your device. Take a note of the COM port number assigned to the device:
这个VCP驱动本站已经上传到网盘, 分为X86系统盒X64系统,自己看着下载啊,别下错!


12.Now we will add some basic functionality to our project. We will make a variation of a simple 'echo' application. First of all modify the TEMPLATE_Init() function in usbd_cdc_if_template.c to set a receive buffer:


extern USBD_HandleTypeDef USBD_Device;

static struct
{
uint8_t Buffer[CDC_DATA_HS_OUT_PACKET_SIZE];
int Position, Size;
char ReadDone;
} s_RxBuffer;

char g_VCPInitialized;

static int8_t TEMPLATE_Init(void)
{
USBD_CDC_SetRxBuffer(&USBD_Device, s_RxBuffer.Buffer);
g_VCPInitialized = 1;
return (0);
}


13.Then modify TEMPLATE_Receive() that is called from an interrupt handler to store received data in our buffer:


static int8_t TEMPLATE_Receive (uint8_t[i] Buf, uint32_t [/i]Len)
{
s_RxBuffer.Position = 0;
s_RxBuffer.Size = *Len;
s_RxBuffer.ReadDone = 1;
return (0);
}


14.Then add basic read and write functions:


int VCP_read(void *pBuffer, int size)
{
if (!s_RxBuffer.ReadDone)
return 0;

int remaining = s_RxBuffer.Size - s_RxBuffer.Position;
int todo = MIN(remaining, size);
if (todo <= 0)
return 0;

memcpy(pBuffer, s_RxBuffer.Buffer + s_RxBuffer.Position, todo);
s_RxBuffer.Position += todo;
if (s_RxBuffer.Position >= s_RxBuffer.Size)
{
s_RxBuffer.ReadDone = 0;
USBD_CDC_ReceivePacket(&USBD_Device);
}

return todo;
}

int VCP_write(const void *pBuffer, int size)
{
if (size > CDC_DATA_HS_OUT_PACKET_SIZE)
{
int offset;
for (offset = 0; offset < size; offset++)
{
int todo = MIN(CDC_DATA_HS_OUT_PACKET_SIZE,
size - offset);
int done = VCP_write(((char *)pBuffer) + offset, todo);
if (done != todo)
return offset + done;
}

return size;
}

USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)USBD_Device.pClassData;
while(pCDC->TxState) { } //Wait for previous transfer

USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)pBuffer, size);
if (USBD_CDC_TransmitPacket(&USBD_Device) != USBD_OK)
return 0;

while(pCDC->TxState) { } //Wait until transfer is done
return size;
}


15.Add the prototypes of the new functions and the initialization flag to usb_cdc_if_template.h:


int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);
extern char g_VCPInitialized;

+++++++++++++++++++++++++++++++++
Note that the current code will use the receive buffer for one packet only and wait for the entire transmission to complete before returning. This is slow and inefficient compared to a pair of ring buffers and is only shown here do to extreme simplicity.

16.The ST's USBD_CDC_TransmitPacket() function contains a bug: it sets the 'transmission in progress' flag AFTER starting the actual transmission, so if the 'transmission done' interrupt happens too early, the flag will be set AFTER the interrupt and hence will never be cleared. To fix this, move "hcdc->TxState = 1" line before the call to USBD_LL_Transmit():


if(hcdc->TxState == 0)
{
hcdc->TxState = 1;

USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer,
hcdc->TxLength);
return USBD_OK;
}


17.Finally replace the empty loop in main() with the following code:


char byte;
for (;;)
{
if (VCP_read(&byte, 1) != 1)
continue;
VCP_write("\r\nYou typed ", 12);
VCP_write(&byte, 1);
VCP_write("\r\n", 2);
}

后面还有一点,不过,不用他的插件的话,就用不上!

STM32USB用STM32Cube来生成USB转串口通讯的程序?有知道的吗?

问题困惑ZJZTO 回复了问题 • 8 人关注 • 11 个回复 • 3627 次浏览 • 2015-01-31 11:14 • 来自相关话题

分享:当串口com的端口号太大怎么办?下面教你解除串口端口占用

经验分享admin 发表了文章 • 0 个评论 • 2202 次浏览 • 2014-12-16 22:50 • 来自相关话题

大多数时候电脑的com口没用到但是com口的端口号却不会从小到大来.....
下面教你解除那些占着茅坑不拉屎的端口的方法
虽然现在串口使用的不多了,但是有的时候还是会用上,但是在我门偶尔要使用串口(COM口)的时候却发现,它总是提示被占用(在使用中),而程序又限定了端口号,这个是有我们只有想办法解决串口/COM端口被占用(在使用中)的问题了

第一,检查这个端口是不是有设备在使用,如果有,可以先断开这个设备,让开位置来

第二,也是常见的问题,被某些软件占用了,解决方法如下

点击左下角“开始”菜单——“运行”——输入“regedit”——点击“确定”,打开注册表编辑器。

依照这个路径打开“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter”

删除右侧的“ComDb”值
双击comdb字样,弹出输入框,全选删除,ok
插入串口线,设备管理器里面删除掉此时的端口,或者修改为其他端口,若是删除的,则再次插入后自动变更. 查看全部
大多数时候电脑的com口没用到但是com口的端口号却不会从小到大来.....
下面教你解除那些占着茅坑不拉屎的端口的方法
虽然现在串口使用的不多了,但是有的时候还是会用上,但是在我门偶尔要使用串口(COM口)的时候却发现,它总是提示被占用(在使用中),而程序又限定了端口号,这个是有我们只有想办法解决串口/COM端口被占用(在使用中)的问题了

第一,检查这个端口是不是有设备在使用,如果有,可以先断开这个设备,让开位置来

第二,也是常见的问题,被某些软件占用了,解决方法如下

点击左下角“开始”菜单——“运行”——输入“regedit”——点击“确定”,打开注册表编辑器。

依照这个路径打开“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter”

删除右侧的“ComDb”值
双击comdb字样,弹出输入框,全选删除,ok
插入串口线,设备管理器里面删除掉此时的端口,或者修改为其他端口,若是删除的,则再次插入后自动变更.

stm32的usb虚拟串口驱动win7系统64位和32位不能正常安装的解决办法!stm32 virtual comport win7(终极解决办法)

经验分享admin 发表了文章 • 10 个评论 • 16248 次浏览 • 2014-12-16 13:48 • 来自相关话题

这两天用stm32f4discovery板搞usb虚拟串口,程序用stm32cubemx自动生成
生成的程序中用到了malloc这样的内存分配函数...
导致程序不能正常跑起来,也无法识别,
[相关驱动和文件本站网盘里有]
32位电脑请下载:usb虚拟串口缺失文件和驱动(32位系统x86专用).zip

64位电脑下载:usb虚拟串口缺失文件和驱动(X64位系统用).zip
下载地址:http://pan.baidu.com/s/1gdhcja7

下面都是屁话了.........

经on the way提醒修改了下,PC上面能识别出 [ stm virual comport ]这个设备
但是显示的是叹号,于是拔掉串口连接线,安装ST公司提供的虚拟串口驱动
请去下载 STM32 USB转串口驱动 Virtual COM Port Driver(V1.3.1)版本
这个安装一次完成(切记此时不要连接usb线)
完成后,连接usb虚拟串口的连接线,自动安装驱动
之后由于我的是win7 32位 Ghost系统,而且我安装过电脑管家一类的软件
曾经用清理工具把系统内不用的驱动清理过,所以关键的usbser.sys什么的都没有,
但是下载后添加到系统内还是不行。
**丢失的文件有: mdmcpq.inf 和 usbser.sys
下载这两个文件后,将mdmcpq.inf复制到c:/windows/inf/里面去
将usbser.sys复制到C:/windows/system32/drivers/里面去**
然后重新插入usb线,并在设备管理器界面右键选更新驱动,
仍然提示 已经是最新驱动,安装失败的提示
此时修改c:/windows/inf/里面的mdmcpq.inf文件内容
将里面的
**[FakeModemCopyFileSection]
usbser.sys,,,0x20
修改为
[FakeModemCopyFileSection]
;usbser.sys,,,0x20**
即,在usber.sys之前添加一个分号,然后保存,回到设备管理,更新驱动,OK





大家还有疑问的可以留言,我这次试验了N中办法,就上面的是有效的.
等我回家后试试我电脑win7 64位的如何
实验表明XP和win7 32位可用.............
TNND,win7 64电脑还是不行,百度了下,有人说是64位和32位的usbser.sys不一样,我倒....
我再去找找,坑爹啊,回到家不能用......
再去找找.....发现是usbser.sys问题,已解决 查看全部
这两天用stm32f4discovery板搞usb虚拟串口,程序用stm32cubemx自动生成
生成的程序中用到了malloc这样的内存分配函数...
导致程序不能正常跑起来,也无法识别,
[相关驱动和文件本站网盘里有]
32位电脑请下载:usb虚拟串口缺失文件和驱动(32位系统x86专用).zip

64位电脑下载:usb虚拟串口缺失文件和驱动(X64位系统用).zip
下载地址:http://pan.baidu.com/s/1gdhcja7

下面都是屁话了.........

经on the way提醒修改了下,PC上面能识别出 [ stm virual comport ]这个设备
但是显示的是叹号,于是拔掉串口连接线,安装ST公司提供的虚拟串口驱动
请去下载 STM32 USB转串口驱动 Virtual COM Port Driver(V1.3.1)版本
这个安装一次完成(切记此时不要连接usb线)
完成后,连接usb虚拟串口的连接线,自动安装驱动
之后由于我的是win7 32位 Ghost系统,而且我安装过电脑管家一类的软件
曾经用清理工具把系统内不用的驱动清理过,所以关键的usbser.sys什么的都没有,
但是下载后添加到系统内还是不行。
**丢失的文件有: mdmcpq.inf 和 usbser.sys
下载这两个文件后,将mdmcpq.inf复制到c:/windows/inf/里面去
将usbser.sys复制到C:/windows/system32/drivers/里面去**
然后重新插入usb线,并在设备管理器界面右键选更新驱动,
仍然提示 已经是最新驱动,安装失败的提示
此时修改c:/windows/inf/里面的mdmcpq.inf文件内容
将里面的
**[FakeModemCopyFileSection]
usbser.sys,,,0x20
修改为
[FakeModemCopyFileSection]
;usbser.sys,,,0x20**
即,在usber.sys之前添加一个分号,然后保存,回到设备管理,更新驱动,OK

无标题.png

大家还有疑问的可以留言,我这次试验了N中办法,就上面的是有效的.
等我回家后试试我电脑win7 64位的如何
实验表明XP和win7 32位可用.............
TNND,win7 64电脑还是不行,百度了下,有人说是64位和32位的usbser.sys不一样,我倒....
我再去找找,坑爹啊,回到家不能用......
再去找找.....发现是usbser.sys问题,已解决
条新动态, 点击查看
老外那个全部的定义如下:

#define USBD_CFG_MAX_NUM 1
#define USBD_ITF_MAX_NUM 1
#define USB_MAX_STR_DESC_SIZ ... 显示全部 »
老外那个全部的定义如下:

#define USBD_CFG_MAX_NUM 1
#define USBD_ITF_MAX_NUM 1
#define USB_MAX_STR_DESC_SIZ 50
#define CDC_IN_EP 0x81 / EP1 for data IN /
#define CDC_OUT_EP 0x01 / EP1 for data OUT /
#define CDC_CMD_EP 0x82 / EP2 for CDC commands /
#define CDC_DATA_MAX_PACKET_SIZE 64 / Endpoint IN & OUT Packet size /
#define CDC_CMD_PACKET_SZE 8 / Control Endpoint Packet size /

#define CDC_IN_FRAME_INTERVAL 5 / Number of frames between IN transfers /
#define APP_RX_DATA_SIZE 2048 /* Total size of IN buffer:

#define RX_FIFO_FS_SIZE 128
#define TX0_FIFO_FS_SIZE 64
#define TX1_FIFO_FS_SIZE 128
#define TX2_FIFO_FS_SIZE 0
#define TX3_FIFO_FS_SIZE 0
#define TXH_NP_FS_FIFOSIZ 96
#define TXH_P_FS_FIFOSIZ 96



#define USBD_VID 0x0483

#define USBD_PID 0x5740

/** @defgroup USB_String_Descriptors
* @{
*/
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "STMicroelectronics"

#define USBD_PRODUCT_HS_STRING "STM32 Virtual ComPort in HS mode"
#define USBD_SERIALNUMBER_HS_STRING "00000000050B"

#define USBD_PRODUCT_FS_STRING "STM32 Virtual ComPort in FS Mode"
#define USBD_SERIALNUMBER_FS_STRING "00000000050C"

#define USBD_CONFIGURATION_HS_STRING "VCP Config"
#define USBD_INTERFACE_HS_STRING "VCP Interface"

#define USBD_CONFIGURATION_FS_STRING "VCP Config"
#define USBD_INTERFACE_FS_STRING "VCP Interface"

#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
#define USB_STRING_DESCRIPTOR_TYPE 0x03
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
#define USB_SIZ_DEVICE_DESC 18
#define USB_SIZ_STRING_LANGID 4

STM32F4 USB HOST VPC主机无法读取到从机发来的数据

回复

问题困惑守护 回复了问题 • 2 人关注 • 1 个回复 • 338 次浏览 • 2019-08-10 10:24 • 来自相关话题

STM32F4的USB CDC问题

回复

问题困惑admin 回复了问题 • 3 人关注 • 1 个回复 • 387 次浏览 • 2019-04-29 16:49 • 来自相关话题

(直播)分析老外的关于stm32的usb虚拟串口程序,体会配置方法和实现流程

回复

经验分享 回复了问题 • 15 人关注 • 16 个回复 • 23971 次浏览 • 2019-04-25 14:28 • 来自相关话题

终于利用stm32cube生成了usb虚拟串口程序并初步调试通过,分享代码和配置先!!

回复

软件教程jreeyssss 回复了问题 • 84 人关注 • 34 个回复 • 52606 次浏览 • 2019-03-05 19:09 • 来自相关话题

抛砖引玉:一步一步Hal库学习usb虚拟串口功能CDC或者叫VCP

回复

软件教程星期五 回复了问题 • 46 人关注 • 22 个回复 • 32540 次浏览 • 2018-03-03 19:05 • 来自相关话题

stmcdc.inf文件(虚拟串口驱动文件)

回复

其他分享admin 回复了问题 • 3 人关注 • 1 个回复 • 5257 次浏览 • 2016-09-27 20:42 • 来自相关话题

记录一个移植F4usb虚串VCP到F103的CDC时候的一个问题

回复

经验分享idfulin 回复了问题 • 4 人关注 • 4 个回复 • 2642 次浏览 • 2016-04-12 18:55 • 来自相关话题

STM32USB用STM32Cube来生成USB转串口通讯的程序?有知道的吗?

回复

问题困惑ZJZTO 回复了问题 • 8 人关注 • 11 个回复 • 3627 次浏览 • 2015-01-31 11:14 • 来自相关话题

(转)HID+CDC复合设备在WIN10的识别问题

经验分享admin 发表了文章 • 0 个评论 • 2153 次浏览 • 2018-06-17 09:20 • 来自相关话题

1 问题现象有客户使用STM32F405并参照ST官方USB标准库下的HID+CDC的示例代码做产品,发现在WIN7上使用得好好的,可放到WIN10上,CDC第一次能够识别,再次拔插后就不能再识别,且此后无论插拔多少次都无法再识别,除非再次上电,又会重复上述现象,只有板子上电后第一次才能正确被识别,后续均不行。2 问题分析客户使用 ST官方示例代码STM32_USB-Host-Device_Lib_V2.2.0\Project\USB_Device_Examples\Composite_Examples\CDC_HID_Composite(下载页面:http://www.stmicroelectronics.com.cn/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32046.html)当我尝试使用此示例代码重现客户所遇到的问题时,发现此代码在WIN7运行OK,但与客户不同的是,我测试到的情况是在WIN10下CDC一次都无法识别,HID却一直可以识别。下面来分析下问题,既然WIN7下HID和CDC都能正常识别,放在WIN10上才不正常,那么初步可以判断,此问题可能与WIN10操作系统的USB主机驱动实现有关。通过USB分析仪分析客户代码在WIN10下USB枚举异常的数据通讯:Figure 1 第一次USB枚举过程上图是客户代码第一次正常枚举的通讯数据,从图中可以看出,WIN10 USB主机在正常获取HID报告描述符后,紧接着会获取虚拟串口状态和设置波特率,这样就正常枚举结束了。我们再来看看采集到的异常USB枚举过程:Figure 2 异常枚举过程上图是WIN10下异常枚举过程。从图中可以看出,WIN10系统上USB主机在获取到设备描述符和配置描述符后直接将设备挂起了。很明显,WIN10系统的USB主机驱动实现对设备描述符或者配置描述符的内容并不认可,才会导致无法识别HID+CDC复合设备。我们不妨检查下客户代码中的设备描述符:Figure 3 获取的设备描述符复合设备的class,subclass,protocol必须为0xef,0x02,0x01,这里VID=0x0483,PID=0x3256(Cube库下为0x5740,但这个不重要),接下来看配置描述符:Figure 4 win10不能识别的配置描述符由此可见,客户的描述符是HID interface + IAD + CDC interfaces结构。对于WIN7,这种结构可以识别,但对于WIN10,这种结构WIN10未必能够兼容,我们尝试在HID interface外部加上一层IAD结构,使其成为IAD1 + HID interface + IAD2 + CDC interfaces结构,此时客户的问题得以解决,在WIN10也可以正确识别了,修改后的描述符结构如下:Figure 5 win10能够正确识别的配置描述符结束本篇实战经验之前,让我们再次回顾IAD的概念:IAD(Interface Association Descriptor),为USB设备定义了一个标准来表述捆绑在一个逻辑功能(比如这里的CDC虚拟串口)上的多个接口的聚合的方法。USB协会分配了一个设备级别的类编码(即图3中0xEF),使用IAD的设备必须使用它(如图3的设备描述符);这样可以很容易在设备枚举时就能识别出采用了IAD的设备。IAD描述符通常放在它所要捆绑的多个接口的接口描述符之前。3 结论 在WIN10系统中,建议复合设备每个逻辑功能的接口描述符前都搭载一个IAD描述符,不论这个逻辑功能是单个接口描述符完成(比如这里的HID功能)还是要由多个接口描述符完成(比如这里的CDC功能)。本文转自:https://mp.weixin.qq.com/s/9ot9AVTN4zSMAyudVDeMzA 感谢【STM32单片机】分享的经验。 查看全部

1 问题现象

有客户使用STM32F405并参照ST官方USB标准库下的HID+CDC的示例代码做产品,发现在WIN7上使用得好好的,可放到WIN10上,CDC第一次能够识别,再次拔插后就不能再识别,且此后无论插拔多少次都无法再识别,除非再次上电,又会重复上述现象,只有板子上电后第一次才能正确被识别,后续均不行。

2 问题分析

客户使用 ST官方示例代码

STM32_USB-Host-Device_Lib_V2.2.0\Project\USB_Device_Examples\Composite_Examples\CDC_HID_Composite

(下载页面:

http://www.stmicroelectronics.com.cn/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32046.html)

当我尝试使用此示例代码重现客户所遇到的问题时,发现此代码在WIN7运行OK,但与客户不同的是,我测试到的情况是在WIN10下CDC一次都无法识别,HID却一直可以识别。


下面来分析下问题,既然WIN7下HID和CDC都能正常识别,放在WIN10上才不正常,那么初步可以判断,此问题可能与WIN10操作系统的USB主机驱动实现有关。

通过USB分析仪分析客户代码在WIN10下USB枚举异常的数据通讯:

捕获.PNG

Figure 1 第一次USB枚举过程


上图是客户代码第一次正常枚举的通讯数据,从图中可以看出,WIN10 USB主机在正常获取HID报告描述符后,紧接着会获取虚拟串口状态和设置波特率,这样就正常枚举结束了。我们再来看看采集到的异常USB枚举过程:

捕获2.PNG

Figure 2 异常枚举过程


上图是WIN10下异常枚举过程。从图中可以看出,WIN10系统上USB主机在获取到设备描述符和配置描述符后直接将设备挂起了。很明显,WIN10系统的USB主机驱动实现对设备描述符或者配置描述符的内容并不认可,才会导致无法识别HID+CDC复合设备。

我们不妨检查下客户代码中的设备描述符:

捕获3.PNG

Figure 3 获取的设备描述符


复合设备的class,subclass,protocol

必须为0xef,0x02,0x01,这里

VID=0x0483,PID=0x3256(Cube库下为0x5740,但这个不重要),接下来看配置描述符:

4.jpg

Figure 4 win10不能识别的配置描述符


由此可见,客户的描述符是HID interface + IAD + CDC interfaces结构。对于WIN7,这种结构可以识别,但对于WIN10,这种结构WIN10未必能够兼容,我们尝试在HID interface外部加上一层IAD结构,使其成为IAD1 + HID interface + IAD2 + CDC interfaces结构,此时客户的问题得以解决,在WIN10也可以正确识别了,修改后的描述符结构如下:

5.jpg

Figure 5 win10能够正确识别的配置描述符


结束本篇实战经验之前,让我们再次回顾IAD的概念:

IAD(Interface Association Descriptor),为USB设备定义了一个标准来表述捆绑在一个逻辑功能(比如这里的CDC虚拟串口)上的多个接口的聚合的方法。USB协会分配了一个设备级别的类编码(即图3中0xEF),使用IAD的设备必须使用它(如图3的设备描述符);这样可以很容易在设备枚举时就能识别出采用了IAD的设备。IAD描述符通常放在它所要捆绑的多个接口的接口描述符之前


3 结论

在WIN10系统中,建议复合设备每个逻辑功能的接口描述符前都搭载一个IAD描述符,不论这个逻辑功能是单个接口描述符完成(比如这里的HID功能)还是要由多个接口描述符完成(比如这里的CDC功能)。


本文转自:https://mp.weixin.qq.com/s/9ot9AVTN4zSMAyudVDeMzA

感谢【STM32单片机】分享的经验。

STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+USB 虚拟串口+SD卡、串行Flash模拟U盘

经验分享开始现在-s 发表了文章 • 1 个评论 • 2784 次浏览 • 2017-12-11 13:59 • 来自相关话题

首先说明下开发条件:1、开发板:秉火霸道,STM32F103ZET2、软件:Cubemx V4.23(F1 V1.60库)3、硬件: STM32模拟USB设备:虚拟串口 CDC、HID、MSC问题描述: 官方生成的代码有的人说电脑没有反应,不会出现USB设备!解决办法:1、查看硬件原理图    注意D+要设置为高电平,全速USB,这时候需要PD3引脚为低电平,当然了你也可以在软件里设置DP为上拉,可惜最新的1.6库是无法设置DP引脚的,所以需要我们自己根据自己的硬件原理图查看下,DP引脚是否上拉为3.3V!    也有人说是Vbus引脚的问题,应该在设置里面把Vbus失效不使能,可惜1.6的库没有这个设置,好在我硬件里面已经上拉为5V,将Vbus失效了!    2、USB虚拟串口:主要就是使用CDC_Receive_FS( UserRxBuffer,(uint32_t *)(sizeof(UserRxBuffer)));和    CDC_Transmit_FS((uint8_t*)UserRxBuffer,sizeof(UserRxBuffer));这两个函数,感觉不好用,纯粹属于测试,发送和接收成功,感兴趣可以自己研究!    3、HID测试成功,正常读取 polling_interval=USBD_HID_GetPollingInterval(&hUsbDeviceFS);数值,至于具体怎么使用没有深入研究。    4、SD卡模拟U盘:    主要修改生成的usbd_storage_if.c文件里面STORAGE_Read_FS()和STORAGE_Write_FS()函数,注意blk_addr 不需要乘以512(SD卡一个块为512字节),因为不同版本库之间有的乘以512,有的不乘,但是最新的1.6库是不需要乘以512的,blk_addr 就是起始地址的意思,而blk_len表示是读多少块,而不是读多少字节数,大家一定注意!    HAL_SD_WriteBlocks(&hsd, (uint8_t *)buf, blk_addr , blk_len, 1000)    HAL_SD_ReadBlocks(&hsd,(uint8_t *)buf, blk_addr , blk_len, 1000)    5、SPIFLASH模拟U盘暂时没有成功,可能是自己板子的flash有问题,出现无法格式化的情况,还需要继续研究,也希望已经搞好的朋友分享一下!    6、联系方式:微信Startingray,本人准备将cubemx的小bug解决的过程记录下来,也是给爱好者一点启示,欢迎微信和我沟通,共同进步!个人觉得Cubemx是未来的发展方向,可以使我们避免很多小错误,但是由于现在软件版本之间的兼容性,加上不同版本库之间存在的bug,还是需要我们在使用时时刻保持警惕! 查看全部

首先说明下开发条件:

1、开发板:秉火霸道,STM32F103ZET

2、软件:Cubemx V4.23(F1 V1.60库)

3、硬件: STM32模拟USB设备:虚拟串口 CDC、HID、MSC

问题描述: 官方生成的代码有的人说电脑没有反应,不会出现USB设备!

解决办法:

1、查看硬件原理图

捕获.JPG

    注意D+要设置为高电平,全速USB,这时候需要PD3引脚为低电平,当然了你也可以在软件里设置DP为上拉,可惜最新的1.6库是无法设置DP引脚的,所以需要我们自己根据自己的硬件原理图查看下,DP引脚是否上拉为3.3V!

    也有人说是Vbus引脚的问题,应该在设置里面把Vbus失效不使能,可惜1.6的库没有这个设置,好在我硬件里面已经上拉为5V,将Vbus失效了!


    2、USB虚拟串口:

主要就是使用CDC_Receive_FS( UserRxBuffer,(uint32_t *)(sizeof(UserRxBuffer)));和

   CDC_Transmit_FS((uint8_t*)UserRxBuffer,sizeof(UserRxBuffer));这两个函数,感觉不好用,纯粹属于测试,发送和接收成功,感兴趣可以自己研究!


    3、HID测试成功,正常读取 polling_interval=USBD_HID_GetPollingInterval(&hUsbDeviceFS);数值,至于具体怎么使用没有深入研究。


    4、SD卡模拟U盘:

    主要修改生成的usbd_storage_if.c文件里面STORAGE_Read_FS()和STORAGE_Write_FS()函数,注意blk_addr 不需要乘以512(SD卡一个块为512字节),因为不同版本库之间有的乘以512,有的不乘,但是最新的1.6库是不需要乘以512的,blk_addr 就是起始地址的意思,而blk_len表示是读多少块,而不是读多少字节数,大家一定注意!

    HAL_SD_WriteBlocks(&hsd, (uint8_t *)buf, blk_addr , blk_len, 1000)

    HAL_SD_ReadBlocks(&hsd,(uint8_t *)buf, blk_addr , blk_len, 1000)


    5、SPIFLASH模拟U盘暂时没有成功,可能是自己板子的flash有问题,出现无法格式化的情况,还需要继续研究,也希望已经搞好的朋友分享一下!


    6、联系方式:微信Startingray,本人准备将cubemx的小bug解决的过程记录下来,也是给爱好者一点启示,欢迎微信和我沟通,共同进步!个人觉得Cubemx是未来的发展方向,可以使我们避免很多小错误,但是由于现在软件版本之间的兼容性,加上不同版本库之间存在的bug,还是需要我们在使用时时刻保持警惕!



分享国外文章 : 建立一个基于USB_CDC的工程为STM32F4Discovery(建立usb虚拟串口),非常详细,值得借鉴!

其他分享admin 发表了文章 • 3 个评论 • 3551 次浏览 • 2015-02-13 15:15 • 来自相关话题

文章名:Making a basic USB CDC project for STM32F4Discovery
摘录:
This tutorial shows how to create a basic USB communication device using the STM32F4Discovery board. The USB protocol stack implementation is contained in the STM32CubeF4 firmware package, however to get a complete project you need to either use the Stm32Cube MX tool to generate it, or assemble it from different components in the firmware package. In this tutorial we will use the second way.
这篇教程是是基于他们官方的软件来写的,名字是VisualGDB 4.2,这个就是一个viral studio的外挂插件,安装后类似于keil的编译器,很强大,我试了一下,就是用着不习惯,呵呵

关于他的插件的用法咱们不去追究,只看CDC怎么从stm32cubemx的软件包提供的模板,去完成一个实用的usb_CDC功能.

不过,对这个软件插件有兴趣的可以安装使用一下, 大小只有5M
但是安装后会提示安装一些stm32的驱动,大概也有10M,
和谐版安装包已经发布在本站网盘,名字是: VisualGDB-4.2r4.rar

这篇文章的PDF版本同时也放在了VisualGDB-4.2r4.rar文件中!

插件安装完成后,将文件夹内的Crack里面的文件,复制到安装目录就行了.
具体自己百度......

文章地址: usb cdc工程完整演示

如果以上地址打不开,可以到本论坛网盘里下载PDF文档,
文档名称:Making a basic USB CDC project for STM32F4Discovery _ VisualGDB Tutorials.pdf
下面是我摘抄的部分代码, 人家国外写代码真心漂亮!

1.Now that the basic project is working, we will add the USB protocol implementation from ST. The USB implementation consists of 3 parts:
USB core protocol implementation
USB CDC device class (virtual COM port)
USB configuration (descriptors and hardware mappings)




[]Select the STM32_USB_Device_Library\Core directory from the STM32CubeF4 package. Select 'copy folder to project with subpath' and enter 'USB' as the subpath:[/]
3.Press OK. The core files will be copied and imported to Solution Explorer. Import the Class\CDC directory from the STM32CubeF4 package in a similar way:


4.Finally we need to copy USB configuration files. A sample CDC project can be found under Projects\STM324x9I_EVAL\Applications\USB_Device\CDC_Standalone in the STM32CubeF4 package. Copy usb_conf and usb_desc sources from the src directory and their counterparts from the inc directory. Add them to the project and delete the usbd_conf_template.h and usbd_conf_template.c files from the USB\core folder as they are now replaced by actual configuration files. When you're done, the Solution Explorer should look the following way:

5.Finally we need to add the directories with the copied include files to the include directory list and ensure the usb_conf.c file uses the USB peripheral in FS mode (HS is not supported on STM32F407). Open VisualGDB Project Properties, add the 'USE_USB_FS' macro to Preprocessor Macros and the '.', 'USB/Core/Inc' and 'USB/CDED/Inc' directories to Include Directories (don't use the backward slash ('\')):


6.Now it's the time to start using the imported USB code from main(). Replace the main() function with the following code (do not remove SysTick_Handler):


extern "C"
{
#include <usbd_core.h>
#include <usbd_cdc.h>
#include <usbd_cdc_if_template.h>
#include <usbd_desc.h>

USBD_HandleTypeDef USBD_Device;
}

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

int main(void)
{
HAL_Init();
SystemClock_Config();
USBD_Init(&USBD_Device, &VCP_Desc, 0);

USBD_RegisterClass(&USBD_Device, &USBD_CDC);
USBD_CDC_RegisterInterface(&USBD_Device,
&USBD_CDC_Template_fops);
USBD_Start(&USBD_Device);

for (;;) ;
}

++++++++++++++++++++++++++++++++
Note that the PLL values above are valid for the 8 MHz crystal on the STM32F4Discovery board. If you are using a different crystal, you will need to modify the values.

7.Two last things to do before we can test our device is to implement the _sbrk() function that tells the C library the location of the heap and provide the USB OTG interrupt handler that will call the corresponding handler of the ST USB library:


extern "C"
{
caddr_t _sbrk(int increment)
{
extern char end asm("end");
register char *pStack asm("sp");

static char *s_pHeapEnd;

if (!s_pHeapEnd)
s_pHeapEnd = &end;

if (s_pHeapEnd + increment > pStack)
return (caddr_t)-1;

char *pOldHeapEnd = s_pHeapEnd;
s_pHeapEnd += increment;
return (caddr_t)pOldHeapEnd;
}

extern PCD_HandleTypeDef hpcd;

void OTG_FS_IRQHandler(void)
{
HAL_PCD_IRQHandler(&hpcd);
}
}

8.Build the project again. Note how the FLASH footprint increased from 2.6KB to 23KB as the USB code is now included in the binary:


9.Connect your board using both USB sockets. Note that the mini-USB socket is needed for JTAG debugging and the micro-USB socket is connected to the STM32F407 microcontroller itself:



10.Press Ctrl-F5 to program the device without debugging it. The Device Manager should now show 2 instances of the port. Each instance corresponds to one of 2 interfaces reported by the ST library (see the definition of USBD_CDC_CfgFSDesc):



11.Although the ST USB library implements the standard USB CDC class and Windows has drivers for it, it will not recognize the device without an inf file specifying which driver to use. Download and install the STM32 VCP drivers to get Windows to recognize your device. Take a note of the COM port number assigned to the device:
这个VCP驱动本站已经上传到网盘, 分为X86系统盒X64系统,自己看着下载啊,别下错!


12.Now we will add some basic functionality to our project. We will make a variation of a simple 'echo' application. First of all modify the TEMPLATE_Init() function in usbd_cdc_if_template.c to set a receive buffer:


extern USBD_HandleTypeDef USBD_Device;

static struct
{
uint8_t Buffer[CDC_DATA_HS_OUT_PACKET_SIZE];
int Position, Size;
char ReadDone;
} s_RxBuffer;

char g_VCPInitialized;

static int8_t TEMPLATE_Init(void)
{
USBD_CDC_SetRxBuffer(&USBD_Device, s_RxBuffer.Buffer);
g_VCPInitialized = 1;
return (0);
}


13.Then modify TEMPLATE_Receive() that is called from an interrupt handler to store received data in our buffer:


static int8_t TEMPLATE_Receive (uint8_t[i] Buf, uint32_t [/i]Len)
{
s_RxBuffer.Position = 0;
s_RxBuffer.Size = *Len;
s_RxBuffer.ReadDone = 1;
return (0);
}


14.Then add basic read and write functions:


int VCP_read(void *pBuffer, int size)
{
if (!s_RxBuffer.ReadDone)
return 0;

int remaining = s_RxBuffer.Size - s_RxBuffer.Position;
int todo = MIN(remaining, size);
if (todo <= 0)
return 0;

memcpy(pBuffer, s_RxBuffer.Buffer + s_RxBuffer.Position, todo);
s_RxBuffer.Position += todo;
if (s_RxBuffer.Position >= s_RxBuffer.Size)
{
s_RxBuffer.ReadDone = 0;
USBD_CDC_ReceivePacket(&USBD_Device);
}

return todo;
}

int VCP_write(const void *pBuffer, int size)
{
if (size > CDC_DATA_HS_OUT_PACKET_SIZE)
{
int offset;
for (offset = 0; offset < size; offset++)
{
int todo = MIN(CDC_DATA_HS_OUT_PACKET_SIZE,
size - offset);
int done = VCP_write(((char *)pBuffer) + offset, todo);
if (done != todo)
return offset + done;
}

return size;
}

USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)USBD_Device.pClassData;
while(pCDC->TxState) { } //Wait for previous transfer

USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)pBuffer, size);
if (USBD_CDC_TransmitPacket(&USBD_Device) != USBD_OK)
return 0;

while(pCDC->TxState) { } //Wait until transfer is done
return size;
}


15.Add the prototypes of the new functions and the initialization flag to usb_cdc_if_template.h:


int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);
extern char g_VCPInitialized;

+++++++++++++++++++++++++++++++++
Note that the current code will use the receive buffer for one packet only and wait for the entire transmission to complete before returning. This is slow and inefficient compared to a pair of ring buffers and is only shown here do to extreme simplicity.

16.The ST's USBD_CDC_TransmitPacket() function contains a bug: it sets the 'transmission in progress' flag AFTER starting the actual transmission, so if the 'transmission done' interrupt happens too early, the flag will be set AFTER the interrupt and hence will never be cleared. To fix this, move "hcdc->TxState = 1" line before the call to USBD_LL_Transmit():


if(hcdc->TxState == 0)
{
hcdc->TxState = 1;

USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer,
hcdc->TxLength);
return USBD_OK;
}


17.Finally replace the empty loop in main() with the following code:


char byte;
for (;;)
{
if (VCP_read(&byte, 1) != 1)
continue;
VCP_write("\r\nYou typed ", 12);
VCP_write(&byte, 1);
VCP_write("\r\n", 2);
}

后面还有一点,不过,不用他的插件的话,就用不上! 查看全部
文章名:Making a basic USB CDC project for STM32F4Discovery
摘录:
This tutorial shows how to create a basic USB communication device using the STM32F4Discovery board. The USB protocol stack implementation is contained in the STM32CubeF4 firmware package, however to get a complete project you need to either use the Stm32Cube MX tool to generate it, or assemble it from different components in the firmware package. In this tutorial we will use the second way.
这篇教程是是基于他们官方的软件来写的,名字是VisualGDB 4.2,这个就是一个viral studio的外挂插件,安装后类似于keil的编译器,很强大,我试了一下,就是用着不习惯,呵呵

关于他的插件的用法咱们不去追究,只看CDC怎么从stm32cubemx的软件包提供的模板,去完成一个实用的usb_CDC功能.

不过,对这个软件插件有兴趣的可以安装使用一下, 大小只有5M
但是安装后会提示安装一些stm32的驱动,大概也有10M,
和谐版安装包已经发布在本站网盘,名字是: VisualGDB-4.2r4.rar

这篇文章的PDF版本同时也放在了VisualGDB-4.2r4.rar文件中!

插件安装完成后,将文件夹内的Crack里面的文件,复制到安装目录就行了.
具体自己百度......

文章地址: usb cdc工程完整演示

如果以上地址打不开,可以到本论坛网盘里下载PDF文档,
文档名称:Making a basic USB CDC project for STM32F4Discovery _ VisualGDB Tutorials.pdf
下面是我摘抄的部分代码, 人家国外写代码真心漂亮!

1.Now that the basic project is working, we will add the USB protocol implementation from ST. The USB implementation consists of 3 parts:
USB core protocol implementation
USB CDC device class (virtual COM port)
USB configuration (descriptors and hardware mappings)




    []Select the STM32_USB_Device_Library\Core directory from the STM32CubeF4 package. Select 'copy folder to project with subpath' and enter 'USB' as the subpath:[/]

3.Press OK. The core files will be copied and imported to Solution Explorer. Import the Class\CDC directory from the STM32CubeF4 package in a similar way:


4.Finally we need to copy USB configuration files. A sample CDC project can be found under Projects\STM324x9I_EVAL\Applications\USB_Device\CDC_Standalone in the STM32CubeF4 package. Copy usb_conf and usb_desc sources from the src directory and their counterparts from the inc directory. Add them to the project and delete the usbd_conf_template.h and usbd_conf_template.c files from the USB\core folder as they are now replaced by actual configuration files. When you're done, the Solution Explorer should look the following way:

5.Finally we need to add the directories with the copied include files to the include directory list and ensure the usb_conf.c file uses the USB peripheral in FS mode (HS is not supported on STM32F407). Open VisualGDB Project Properties, add the 'USE_USB_FS' macro to Preprocessor Macros and the '.', 'USB/Core/Inc' and 'USB/CDED/Inc' directories to Include Directories (don't use the backward slash ('\')):


6.Now it's the time to start using the imported USB code from main(). Replace the main() function with the following code (do not remove SysTick_Handler):


extern "C"
{
#include <usbd_core.h>
#include <usbd_cdc.h>
#include <usbd_cdc_if_template.h>
#include <usbd_desc.h>

USBD_HandleTypeDef USBD_Device;
}

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

int main(void)
{
HAL_Init();
SystemClock_Config();
USBD_Init(&USBD_Device, &VCP_Desc, 0);

USBD_RegisterClass(&USBD_Device, &USBD_CDC);
USBD_CDC_RegisterInterface(&USBD_Device,
&USBD_CDC_Template_fops);
USBD_Start(&USBD_Device);

for (;;) ;
}

++++++++++++++++++++++++++++++++
Note that the PLL values above are valid for the 8 MHz crystal on the STM32F4Discovery board. If you are using a different crystal, you will need to modify the values.

7.Two last things to do before we can test our device is to implement the _sbrk() function that tells the C library the location of the heap and provide the USB OTG interrupt handler that will call the corresponding handler of the ST USB library:


extern "C"
{
caddr_t _sbrk(int increment)
{
extern char end asm("end");
register char *pStack asm("sp");

static char *s_pHeapEnd;

if (!s_pHeapEnd)
s_pHeapEnd = &end;

if (s_pHeapEnd + increment > pStack)
return (caddr_t)-1;

char *pOldHeapEnd = s_pHeapEnd;
s_pHeapEnd += increment;
return (caddr_t)pOldHeapEnd;
}

extern PCD_HandleTypeDef hpcd;

void OTG_FS_IRQHandler(void)
{
HAL_PCD_IRQHandler(&hpcd);
}
}

8.Build the project again. Note how the FLASH footprint increased from 2.6KB to 23KB as the USB code is now included in the binary:


9.Connect your board using both USB sockets. Note that the mini-USB socket is needed for JTAG debugging and the micro-USB socket is connected to the STM32F407 microcontroller itself:



10.Press Ctrl-F5 to program the device without debugging it. The Device Manager should now show 2 instances of the port. Each instance corresponds to one of 2 interfaces reported by the ST library (see the definition of USBD_CDC_CfgFSDesc):



11.Although the ST USB library implements the standard USB CDC class and Windows has drivers for it, it will not recognize the device without an inf file specifying which driver to use. Download and install the STM32 VCP drivers to get Windows to recognize your device. Take a note of the COM port number assigned to the device:
这个VCP驱动本站已经上传到网盘, 分为X86系统盒X64系统,自己看着下载啊,别下错!


12.Now we will add some basic functionality to our project. We will make a variation of a simple 'echo' application. First of all modify the TEMPLATE_Init() function in usbd_cdc_if_template.c to set a receive buffer:


extern USBD_HandleTypeDef USBD_Device;

static struct
{
uint8_t Buffer[CDC_DATA_HS_OUT_PACKET_SIZE];
int Position, Size;
char ReadDone;
} s_RxBuffer;

char g_VCPInitialized;

static int8_t TEMPLATE_Init(void)
{
USBD_CDC_SetRxBuffer(&USBD_Device, s_RxBuffer.Buffer);
g_VCPInitialized = 1;
return (0);
}


13.Then modify TEMPLATE_Receive() that is called from an interrupt handler to store received data in our buffer:


static int8_t TEMPLATE_Receive (uint8_t[i] Buf, uint32_t [/i]Len)
{
s_RxBuffer.Position = 0;
s_RxBuffer.Size = *Len;
s_RxBuffer.ReadDone = 1;
return (0);
}


14.Then add basic read and write functions:


int VCP_read(void *pBuffer, int size)
{
if (!s_RxBuffer.ReadDone)
return 0;

int remaining = s_RxBuffer.Size - s_RxBuffer.Position;
int todo = MIN(remaining, size);
if (todo <= 0)
return 0;

memcpy(pBuffer, s_RxBuffer.Buffer + s_RxBuffer.Position, todo);
s_RxBuffer.Position += todo;
if (s_RxBuffer.Position >= s_RxBuffer.Size)
{
s_RxBuffer.ReadDone = 0;
USBD_CDC_ReceivePacket(&USBD_Device);
}

return todo;
}

int VCP_write(const void *pBuffer, int size)
{
if (size > CDC_DATA_HS_OUT_PACKET_SIZE)
{
int offset;
for (offset = 0; offset < size; offset++)
{
int todo = MIN(CDC_DATA_HS_OUT_PACKET_SIZE,
size - offset);
int done = VCP_write(((char *)pBuffer) + offset, todo);
if (done != todo)
return offset + done;
}

return size;
}

USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)USBD_Device.pClassData;
while(pCDC->TxState) { } //Wait for previous transfer

USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)pBuffer, size);
if (USBD_CDC_TransmitPacket(&USBD_Device) != USBD_OK)
return 0;

while(pCDC->TxState) { } //Wait until transfer is done
return size;
}


15.Add the prototypes of the new functions and the initialization flag to usb_cdc_if_template.h:


int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);
extern char g_VCPInitialized;

+++++++++++++++++++++++++++++++++
Note that the current code will use the receive buffer for one packet only and wait for the entire transmission to complete before returning. This is slow and inefficient compared to a pair of ring buffers and is only shown here do to extreme simplicity.

16.The ST's USBD_CDC_TransmitPacket() function contains a bug: it sets the 'transmission in progress' flag AFTER starting the actual transmission, so if the 'transmission done' interrupt happens too early, the flag will be set AFTER the interrupt and hence will never be cleared. To fix this, move "hcdc->TxState = 1" line before the call to USBD_LL_Transmit():


if(hcdc->TxState == 0)
{
hcdc->TxState = 1;

USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer,
hcdc->TxLength);
return USBD_OK;
}


17.Finally replace the empty loop in main() with the following code:


char byte;
for (;;)
{
if (VCP_read(&byte, 1) != 1)
continue;
VCP_write("\r\nYou typed ", 12);
VCP_write(&byte, 1);
VCP_write("\r\n", 2);
}

后面还有一点,不过,不用他的插件的话,就用不上!

分享:当串口com的端口号太大怎么办?下面教你解除串口端口占用

经验分享admin 发表了文章 • 0 个评论 • 2202 次浏览 • 2014-12-16 22:50 • 来自相关话题

大多数时候电脑的com口没用到但是com口的端口号却不会从小到大来.....
下面教你解除那些占着茅坑不拉屎的端口的方法
虽然现在串口使用的不多了,但是有的时候还是会用上,但是在我门偶尔要使用串口(COM口)的时候却发现,它总是提示被占用(在使用中),而程序又限定了端口号,这个是有我们只有想办法解决串口/COM端口被占用(在使用中)的问题了

第一,检查这个端口是不是有设备在使用,如果有,可以先断开这个设备,让开位置来

第二,也是常见的问题,被某些软件占用了,解决方法如下

点击左下角“开始”菜单——“运行”——输入“regedit”——点击“确定”,打开注册表编辑器。

依照这个路径打开“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter”

删除右侧的“ComDb”值
双击comdb字样,弹出输入框,全选删除,ok
插入串口线,设备管理器里面删除掉此时的端口,或者修改为其他端口,若是删除的,则再次插入后自动变更. 查看全部
大多数时候电脑的com口没用到但是com口的端口号却不会从小到大来.....
下面教你解除那些占着茅坑不拉屎的端口的方法
虽然现在串口使用的不多了,但是有的时候还是会用上,但是在我门偶尔要使用串口(COM口)的时候却发现,它总是提示被占用(在使用中),而程序又限定了端口号,这个是有我们只有想办法解决串口/COM端口被占用(在使用中)的问题了

第一,检查这个端口是不是有设备在使用,如果有,可以先断开这个设备,让开位置来

第二,也是常见的问题,被某些软件占用了,解决方法如下

点击左下角“开始”菜单——“运行”——输入“regedit”——点击“确定”,打开注册表编辑器。

依照这个路径打开“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\COM Name Arbiter”

删除右侧的“ComDb”值
双击comdb字样,弹出输入框,全选删除,ok
插入串口线,设备管理器里面删除掉此时的端口,或者修改为其他端口,若是删除的,则再次插入后自动变更.

stm32的usb虚拟串口驱动win7系统64位和32位不能正常安装的解决办法!stm32 virtual comport win7(终极解决办法)

经验分享admin 发表了文章 • 10 个评论 • 16248 次浏览 • 2014-12-16 13:48 • 来自相关话题

这两天用stm32f4discovery板搞usb虚拟串口,程序用stm32cubemx自动生成
生成的程序中用到了malloc这样的内存分配函数...
导致程序不能正常跑起来,也无法识别,
[相关驱动和文件本站网盘里有]
32位电脑请下载:usb虚拟串口缺失文件和驱动(32位系统x86专用).zip

64位电脑下载:usb虚拟串口缺失文件和驱动(X64位系统用).zip
下载地址:http://pan.baidu.com/s/1gdhcja7

下面都是屁话了.........

经on the way提醒修改了下,PC上面能识别出 [ stm virual comport ]这个设备
但是显示的是叹号,于是拔掉串口连接线,安装ST公司提供的虚拟串口驱动
请去下载 STM32 USB转串口驱动 Virtual COM Port Driver(V1.3.1)版本
这个安装一次完成(切记此时不要连接usb线)
完成后,连接usb虚拟串口的连接线,自动安装驱动
之后由于我的是win7 32位 Ghost系统,而且我安装过电脑管家一类的软件
曾经用清理工具把系统内不用的驱动清理过,所以关键的usbser.sys什么的都没有,
但是下载后添加到系统内还是不行。
**丢失的文件有: mdmcpq.inf 和 usbser.sys
下载这两个文件后,将mdmcpq.inf复制到c:/windows/inf/里面去
将usbser.sys复制到C:/windows/system32/drivers/里面去**
然后重新插入usb线,并在设备管理器界面右键选更新驱动,
仍然提示 已经是最新驱动,安装失败的提示
此时修改c:/windows/inf/里面的mdmcpq.inf文件内容
将里面的
**[FakeModemCopyFileSection]
usbser.sys,,,0x20
修改为
[FakeModemCopyFileSection]
;usbser.sys,,,0x20**
即,在usber.sys之前添加一个分号,然后保存,回到设备管理,更新驱动,OK





大家还有疑问的可以留言,我这次试验了N中办法,就上面的是有效的.
等我回家后试试我电脑win7 64位的如何
实验表明XP和win7 32位可用.............
TNND,win7 64电脑还是不行,百度了下,有人说是64位和32位的usbser.sys不一样,我倒....
我再去找找,坑爹啊,回到家不能用......
再去找找.....发现是usbser.sys问题,已解决 查看全部
这两天用stm32f4discovery板搞usb虚拟串口,程序用stm32cubemx自动生成
生成的程序中用到了malloc这样的内存分配函数...
导致程序不能正常跑起来,也无法识别,
[相关驱动和文件本站网盘里有]
32位电脑请下载:usb虚拟串口缺失文件和驱动(32位系统x86专用).zip

64位电脑下载:usb虚拟串口缺失文件和驱动(X64位系统用).zip
下载地址:http://pan.baidu.com/s/1gdhcja7

下面都是屁话了.........

经on the way提醒修改了下,PC上面能识别出 [ stm virual comport ]这个设备
但是显示的是叹号,于是拔掉串口连接线,安装ST公司提供的虚拟串口驱动
请去下载 STM32 USB转串口驱动 Virtual COM Port Driver(V1.3.1)版本
这个安装一次完成(切记此时不要连接usb线)
完成后,连接usb虚拟串口的连接线,自动安装驱动
之后由于我的是win7 32位 Ghost系统,而且我安装过电脑管家一类的软件
曾经用清理工具把系统内不用的驱动清理过,所以关键的usbser.sys什么的都没有,
但是下载后添加到系统内还是不行。
**丢失的文件有: mdmcpq.inf 和 usbser.sys
下载这两个文件后,将mdmcpq.inf复制到c:/windows/inf/里面去
将usbser.sys复制到C:/windows/system32/drivers/里面去**
然后重新插入usb线,并在设备管理器界面右键选更新驱动,
仍然提示 已经是最新驱动,安装失败的提示
此时修改c:/windows/inf/里面的mdmcpq.inf文件内容
将里面的
**[FakeModemCopyFileSection]
usbser.sys,,,0x20
修改为
[FakeModemCopyFileSection]
;usbser.sys,,,0x20**
即,在usber.sys之前添加一个分号,然后保存,回到设备管理,更新驱动,OK

无标题.png

大家还有疑问的可以留言,我这次试验了N中办法,就上面的是有效的.
等我回家后试试我电脑win7 64位的如何
实验表明XP和win7 32位可用.............
TNND,win7 64电脑还是不行,百度了下,有人说是64位和32位的usbser.sys不一样,我倒....
我再去找找,坑爹啊,回到家不能用......
再去找找.....发现是usbser.sys问题,已解决