STM32F103-CubeMX-USB学习--虚拟串口/com口

STM32-CubeMX USB学习

1. 虚拟com学习

1.1 开发环境

  1. 软件环境:
    STM32CubeMX
    版本:SetupSTM32CubeMX-6.0.1.exe
    Firmware:STM32Cube FM_F1 V1.8.0

keil 5 V5.29—支持并行编译,可以加速编译效率(最新的版本就可以)
keil的固件包版本:
Keil.STM32F1xx_DFP.2.0.0.pack
keil相关资料的下载
https://www.cnblogs.com/armfly/p/12564643.html

java版本–有遇到过java版本太新导致出问题的
jre-8u201-windows-x64.exe
以下版本亲测有问题,请勿使用
jdk-14.0.2_windows-x64_bin.exe

版本的差异会导致各种报错,切记核对相关版本.

路径中不能出现中文空格,出现会报错.

版本问题导致的报错之一
Error: L6218E: Undefined symbol USB_FlushRxFifo (referred from stm32f1xx_hal_pcd.o).

  1. 硬件环境
    Stm32F103c8t6–淘宝上最便宜的开发板
    在这里插入图片描述

1.2 使用STM32CubeMX配置代码

  1. 选择芯片型号,我这边是C8t6
    在这里插入图片描述

  2. debug选择 SW模式
    在这里插入图片描述

  3. 配置外部时钟输入
    在这里插入图片描述

  4. 配置USB device的功能
    在这里插入图片描述

  5. 将USB的模式配置成COM口的功能在这里插入图片描述

  6. 时钟树配置,如果前面没有配置外部晶振输入,这边无法配置成功。正常的话自动会配置成功
    在这里插入图片描述

  7. 工程配置,配置成对应keil的版本

在这里插入图片描述
框出来的位置有时候因为尺寸太小会出错,有人说默认的也可以,反正我改了,如下图
在这里插入图片描述

  1. 第一栏里面选择第一个和第二个都一样的,有问题的话可以换了试一下
    第二栏里勾选将文件分为.c和.h

在这里插入图片描述

  1. 生成工程文件
    在这里插入图片描述

1.3 串口自发自收

  1. 实现串口输出ABCD,需要更改的部分
//1.添加头文件
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "gpio.h"
#include "usbd_cdc_if.h"

更改main函数

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void USB_Disconnected(void) {
    __HAL_RCC_USB_FORCE_RESET();
    HAL_Delay(200);
    __HAL_RCC_USB_RELEASE_RESET();
 
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOA_CLK_ENABLE();
 
    GPIO_Initure.Pin = GPIO_PIN_11 | GPIO_PIN_12;
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Initure.Pull = GPIO_PULLDOWN;
    GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_Initure);
 
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
    HAL_Delay(300);
}

/* USER CODE END 0 */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  //USB 卸载操作,取消按复位键后无法识别的问题
  USB_Disconnected();

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
	//2.添加数组
	unsigned char buff[10] = {"abcd\n\r"};
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		//3. 在while循环中添加如下代码
		HAL_Delay(1000);
		CDC_Transmit_FS(buff,sizeof(buff)); //USB 串口发送数据
  }
  /* USER CODE END 3 */
}

串口助手
在这里插入图片描述

  1. 读取输入的值和上一次是否相同,从而输出不同的值
    首先需要将main函数恢复成初始的状态
    更改下面的函数
    CDC_Receive_FS();这个函数在usbd_cdc_if.c的文件下面的位置
    初始代码
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

将代码改成如下的样子

uint8_t a=0,a1=1;
unsigned char buff1[4] = {"abcd"};
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{	
	
	a = *Buf;		

	if(a == a1)
				CDC_Transmit_FS(Buf,*Len);//自收自发
	else 
	{
			CDC_Transmit_FS(buff1,sizeof(buff1));
			a1 = a;
	}
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);

  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
	//CDC_Transmit_FS(Buf,*Len);//自收自发


  return (USBD_OK);
  /* USER CODE END 6 */	

}

会对比此次的和上一次的差异,如果一样则输出 接收到的值,如果不一样则输出abcd

PS:有一个BUG,数字大了后识别会出错,只能识别发送的第一个数据的差异
在这里插入图片描述

1.4 串口定向printf

参考文档:
文件的配置教程
https://www.jianshu.com/p/579783d28044

1.驱动下载链接
https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-utilities/stsw-stm32102.html
2. 代码操作
https://blog.csdn.net/u010779035/article/details/104369515

假装的Print—使用sprintf 这个函数将数据处理到串口发送的数组中,串口通过设置中断或者定时发送,进行数据的发送,但需要占用比较大的数据资源。实时性不确定。

1.5 串口接收的数据存到数组中

如下代码需要在main函数中进行更改

定义初始化函数

/* USER CODE BEGIN PTD */
uint8_t uart_number[64]="nihao\n\r";
/* USER CODE END PTD */

如下使用串口发送函数,将数组 uart_number 发送出去

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		CDC_Transmit_FS(uart_number,sizeof(uart_number)); //USB 串口发送数据
		HAL_Delay(1000);	
		
  }
  /* USER CODE END 3 */

CDC_Receive_FS();这个函数在usbd_cdc_if.c的文件下面的位置


extern uint8_t uart_number[64];
uint8_t* aa;
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
	uint32_t i;
	
  /* USER CODE BEGIN 6 */
	
	
	//会对比此次的和上一次的差异,如果一样则输出 接收到的值,如果不一样则输出abcd
	//最多11个汉字 64个16进制数 

	memset(uart_number, 0, sizeof uart_number); //清除数组uart_number
	
	
	//循环函数,将接收到的数字,存到数组中
	aa = Buf;	
		for(i = 0;i < *Len;i++)
	{
		uart_number[i] = *aa;
		aa++;
	}
			

	
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

另外PS一个bug:
可能由于数组的问题,在接收数据太大后会出现溢出?//最多11个汉字 64个16进制数
能够满足基本的使用,但是不推荐太长的数据,或者控制单次发送的数据长度,分多次发送。

解决BUG:关于在按下reset之后,串口可以识别,但是无法打开的问题

在USB初始化前强制USB时钟复位

void USB_Disconnected(void) {
    __HAL_RCC_USB_FORCE_RESET();
    HAL_Delay(200);
    __HAL_RCC_USB_RELEASE_RESET();
 
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOA_CLK_ENABLE();
 
    GPIO_Initure.Pin = GPIO_PIN_11 | GPIO_PIN_12;
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Initure.Pull = GPIO_PULLDOWN;
    GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_Initure);
 
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
    HAL_Delay(300);
}

再USB初始化之前,执行一下这些就行了,相当于告诉电脑断开链。这样按下复位键后会自动断开连接,软件上重新选择com口和重新打开旧可以正常识别。

PS:这样的方式就使得USB虚拟的串口,会有一段空白的阶段,使得其无法输出初始化状态下的串口信息。有着一丝的鸡肋?

上面的程序放在如下的main.c 文件中

  /* USER CODE BEGIN SysInit */
	//注销USB
   USB_Disconnected();

  /* USER CODE END SysInit */

总结:
待完善STM32的其他功能,HID,Audio等功能

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值