- 方法2的方法是visual studio直接导进来keil工程,这样做的一个缺点就是:
- 1、生成是vs工程目录太乱;
- 2、keil在编译后.c文件下都会包括用到的.h文件,可以查看到.h文件的内容,但是vs编译后.c文件下并不会包括.h文件,这样在vs里是看不到导进来的.h文件。而且在.h路径方面,vs跟keil设置的路径是一样的,导致vs工程不能单独移动,得带着整个CubeMX工程一起移动,岂不是麻烦。如果想可以单独移动vs,得重新添加.h路径以及.c文件。
-
从CubeMX生成的工程目录下拷贝出我们需要的文件,最好放在另一个路径下,不要跟CubeMX工程在同一路径下,我第一次是放在了同一路径下,当我单独移动VS project后,vs projcet里的那些.c/.h都打不开,提示找不到该文件,所以还是建议拷贝出来的文件放在不同路径下再接着下面的操作.
-
1、用VS新建一个USB CDC通信Project模板,备用,参照方法一。
-
2、从CubeMX生成配置好的USB虚拟串口通信配置工程目录中拷贝出需要的文件夹。CubeMX配置参照方法二。
-
-
-
3、将vs模板中不用的文件移除,加入我们拷贝出来的文件
-
4、按下图方式添加文件:(vcp.h,vcp.c是自己创建的)
-
6、到此完成。编译下没有错误,下载,发现PC可以识别USBcom口。
-
7、自带的收发函数能用但不好用,搞一下它。
-
在usbd_cdc_if.c中添加代码:
static struct
{
uint8_t Buffer[CDC_DATA_HS_OUT_PACKET_SIZE];
int Position, Size;
char ReadDone;
} s_RxBuffer;
char g_VCPInitialized;
-
修改自带的CDC_Receive_FS()函数如下:
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
// USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
//USBD_CDC_ReceivePacket(&hUsbDeviceFS);
// return (USBD_OK);
s_RxBuffer.Position = 0;
s_RxBuffer.Size = *Len;
s_RxBuffer.ReadDone = 1;
return (USBD_OK);
}
-
添加新函数:VCP_read()和VCP_write()用于数据收发:
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(&hUsbDeviceFS);
}
return todo;
}
int VCP_write(const void *pBuffer, int size)
{
if (size > CDC_DATA_FS_OUT_PACKET_SIZE)
{
int offset;
int done = 0;
for (offset = 0; offset < size; offset += done)
{
int todo = MIN(CDC_DATA_FS_OUT_PACKET_SIZE, size - offset);
done = VCP_write(((char *)pBuffer) + offset, todo);
if (done != todo)
return offset + done;
}
return size;
}
/*
USBD_CDC_HandleTypeDef *pCDC =
(USBD_CDC_HandleTypeDef *)hUsbDeviceFS.pClassData;
while (pCDC->TxState) {} //Wait for previous transfer
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, (uint8_t *)pBuffer, size);
if (USBD_CDC_TransmitPacket(&hUsbDeviceFS) != USBD_OK)
return 0;
while (pCDC->TxState) {} //Wait until transfer is done
return size;
*/
uint8_t result = USBD_OK;
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0) {
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, (uint8_t *)pBuffer, size);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
return result;
}
int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);
extern char g_VCPInitialized;
-
做了一个vcp.c和vcp.h,创建一个print函数,用来向PC打印调试信息,vcp.c文件如下:
#include "vcp.h"
#include "usbd_cdc_if.h"
void print(const char *buffer)
{
int length = strlen(buffer);
//CDC_Transmit_FS((uint8_t*)buffer, length);
VCP_write((uint8_t*)buffer, length);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
char byte[3];
while (1)
{
//VCP_read(byte,3);
//VCP_write(byte, sizeof(byte));
print("Yours VCP is success!\n");
HAL_Delay(500);
}
}
-
main函数中测试下收发函数,串口助手发给MCU后,MCU再发回给串口助手:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
char byte[3]; //只定义了收发字节数最大是3字节
while (1)
{
VCP_read(byte,3);
VCP_write(byte, sizeof(byte));
//print("Yours VCP is success!\n");
HAL_Delay(1000);
}
}