STM32F103 USB实现虚拟串口
最近买了一个STM32F103C8T6最小核心板,使用CubeIDE无法识别该芯片,发现该芯片的flash是128Kbytes,ST的标准库是64Kbytes,奇怪啊!也许是国产替代的,国产化太先进了,导致原厂落后了,不认识先进的东西了。
只好又在某宝买了5.5元的STM32F103C6T6最小核心板,CubeID环境下正常工作和调试。感谢万能的某宝!最便宜的东西才能工作正常,好无语啊!
实验环境
STM32F103C6T6A最小系统板, CubeIDE 1.10.1, ST-LINK;
实验目的
实现USB的串口数据传输;
操作步骤
- cubeIDE建立工程并生成代码。
- 设置晶振RCC
- 设置SYS, 调试方式
- 设置USB,激活USB
- 设置Middleware, USB vitrual port,
- 保存并generate code,进行编译一遍,通常是不能编译通过的。
- 修改usb_cdc_if.h 文件
/* USER CODE BEGIN INCLUDE */
#define USB_REC_LEN 256 //定义USB串口接收字节数
extern uint8_t USB_RX_BUF[USB_REC_LEN];//接收缓冲
extern uint16_t USB_RX_STA;//接收标记
/* USER CODE END INCLUDE */`
- 设修改usb_cdc_if.c文件
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t USB_RX_BUF[USB_REC_LEN];//接收缓冲,�?大USB_REC_LEN个字�?.
uint16_t USB_RX_STA=0;//接收状�?�标记(接收到的有效字节数量�?
/* USER CODE END PV */
修改接收函数代码
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
if(*Len<USB_REC_LEN)//判断收到数据量是否小于寄存器上限
{
uint16_t i;
USB_RX_STA = *Len;//将数据量值放入标志位
for(i=0;i<*Len;i++)//循环
USB_RX_BUF[i] = Buf[i];//将数据内容放入数据寄存器
}
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); //将接收数组buff清空
USBD_CDC_ReceivePacket(&hUsbDeviceFS); //再次虚拟串口接收
return (USBD_OK);
/* USER CODE END 6 */
}
修改发送函数代码
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
uint32_t TimeStart = HAL_GetTick();
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
//if (hcdc->TxState != 0) return USBD_BUSY;
while(hcdc->TxState)
{
if(HAL_GetTick()-TimeStart > 10)
return USBD_BUSY;
else
break;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
TimeStart = HAL_GetTick();
while(hcdc->TxState)
{
if(HAL_GetTick()-TimeStart > 10)
return USBD_BUSY;
}
/* USER CODE END 7 */
return result;
}
添加输出函数
#include <stdarg.h>
void USB_printf(const char *format, ...)//USB模拟串口的打印函�?
{
va_list args;
uint32_t length;
va_start(args, format);
length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);
va_end(args);
CDC_Transmit_FS(UserTxBufferFS, length);
}
- 修改main.c
添加include文件
/* USER CODE BEGIN Includes */
#include "../../USB_DEVICE/App/usbd_cdc_if.h"
/* USER CODE END Includes */
修改main函数的while循环
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//USB模拟串口的查寻接收处理
if(USB_RX_STA!=0)//判断是否有
{
//USB_printf("USB_RX:");//向USB模拟串口发字符串
CDC_Transmit_FS(USB_RX_BUF,USB_RX_STA);//USB串口:将接收的数据发回给电脑端
//USB_printf("\r\n");//向USB模拟串口发(回车)
USB_RX_STA=0;//数据标志位清0
memset(USB_RX_BUF,0,sizeof(USB_RX_BUF));//USB串口数据寄存器清0
}
}
/* USER CODE END 3 */
- 修改堆栈和堆;
11.修改编译优化
设置编译优化: Properties for F10****/ C/C++ Build / Settings / MCU GCC Compiler / Optimization \ Optimization level = “Optimize for size(-Os)”
否则会出现错误如下:
\tools\arm-none-eabi\bin\ld.exe: F103C6T6Atest.elf section
.text' will not fit in region
FLASH’ \tools\arm-none-eabi\bin\ld.exe: region
`FLASH’ overflowed by 1656 bytes collect2.exe: error: ld returned 1
exit status make: *** [makefile:68: F103C6T6Atest.elf] Error 1 “make
-j8 all” terminated with exit code 2. Build might be incomplete.
运行测试
1.设备管理器可以看到串口;
2.使用串口工具,发送接收数据正常。
CubeIDE1.10.1 环境下的源代码:https://download.csdn.net/download/qq_23313467/87824117
注意事项:STM32F103C6T6的存储容量比较小,实现USB的虚拟串口基本上用完了内存和flash,如果再添加别的复杂功能,估计存储就不够了。参看了一下生成的hex文件,已经达到38k了!