RT Thread Studio创建USB虚拟串口工程

MCU型号:STM32F103RET6

1.生成一个带串口输出的工程文件,新建RT-Thread项目工程文件。
在这里插入图片描述
2.查看电路图中的串口输出管脚,根据STMCubeMx软件可知此串口为USART1,选择芯片型号为STM32F103RET6,控制台串口选择UART1,发送脚:PB6,接收脚:PB7
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.设置下载bin文件的下载地址为:0x08000000。
在这里插入图片描述
4.代码编译后下载到电路板,连上串口调试助手可看到调试信息。
在这里插入图片描述
5.打开RT-Thread Settings设置设备驱动中的USB,USB设置如图所示,设置完成之后,记得保存,否则设置无效。
在这里插入图片描述
在这里插入图片描述
6.查看原理图中的外部晶振大小,由图可知为8MHz。
在这里插入图片描述
7.打开CubeMx_Settings配置USB虚拟串口。
在这里插入图片描述
8.配置外部晶振,配置USB,重新配置外部时钟,配置完之后生成工程文件
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
9.删除usb_device.h,usbd_cdc_if.h,usbd_conf.h,usbd_desc.h文件,去掉main.c文件中的#include “usb_device.h”

在这里插入图片描述
在这里插入图片描述

10.在stm32f1xx_hal_conf.h打开宏定义HAL_UART_MODULE_ENABLED.
在这里插入图片描述
11.1.将usbd_conf.c文件中的void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)和HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)拷贝到stm32f1xx_hal_msp.c文件中。

void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
  if(pcdHandle->Instance==USB)
  {
  /* USER CODE BEGIN USB_MspInit 0 */

  /* USER CODE END USB_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USB_CLK_ENABLE();

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN USB_MspInit 1 */

  /* USER CODE END USB_MspInit 1 */
  }
}

void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
{
  if(pcdHandle->Instance==USB)
  {
  /* USER CODE BEGIN USB_MspDeInit 0 */

  /* USER CODE END USB_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USB_CLK_DISABLE();

    /* Peripheral interrupt Deinit*/
    HAL_NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);

    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);

  /* USER CODE BEGIN USB_MspDeInit 1 */

  /* USER CODE END USB_MspDeInit 1 */
  }
}

12.在board.h文件中开启BSP_USING_USBDEVICE,#define BSP_USING_USBDEVICE。
在这里插入图片描述
13.编译程序,烧录到电路板中,插上USB,在电脑中可显示端口号。
在这里插入图片描述
14.新建usbd_vcom.h和usbd_vcom.c文件,实现USB虚拟串口数据的发送和接收。
usbd_vcom.h
在这里插入图片描述

#ifndef __USBD_VCOM_H__
#define __USBD_VCOM_H__

#include <rtthread.h>

typedef struct
{
#define USBD_VCOM_THREAD_STACK_SIZE   1024
#define USBD_VCOM_THREAD_PRIO         15
#define USBD_VCOM_THREAD_TICK         10
    struct rt_semaphore sem_rx;
    rt_thread_t thread_rx;
    uint8_t is_running_rx;
}usbd_vcom_rtos_t;

typedef struct
{
    rt_device_t dev;
    usbd_vcom_rtos_t rtos;
}usbd_vcom_t;

extern usbd_vcom_t usbd_vcom;

#define usbd_vcom_get_dev() usbd_vcom.dev

rt_err_t usbd_vcom_drive_init(void);
rt_err_t usbd_vcom_rx_call(rt_device_t dev, rt_size_t size);
rt_err_t usbd_vcom_init(void);
void usbd_vcom_thread_rx(void *para);
#endif

usbd_vcom.c文件

#include "usbd_vcom.h"

usbd_vcom_t usbd_vcom;

rt_err_t usbd_vcom_drive_init(void)
{
    rt_device_t *ps_dev=&usbd_vcom.dev;
    rt_err_t result = RT_EOK;

    *ps_dev = rt_device_find("vcom");
    if (!(*ps_dev))
    {
        return RT_ERROR;
    }

    result = rt_device_open(*ps_dev, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
    if (result != RT_EOK)
    {
        return RT_ERROR;
    }

    rt_device_set_rx_indicate(*ps_dev, usbd_vcom_rx_call);

    return RT_EOK;
}

rt_err_t usbd_vcom_rx_call(rt_device_t dev, rt_size_t size)
{
    usbd_vcom_rtos_t *ps_rtos=&usbd_vcom.rtos;

    if (0 == ps_rtos->is_running_rx)
    {
        return RT_ERROR;
    }

    rt_sem_release(&ps_rtos->sem_rx);

    return RT_EOK;
}

rt_err_t usbd_vcom_init(void)
{
    usbd_vcom_t *ps_handle=&usbd_vcom;
    usbd_vcom_rtos_t *ps_rtos=&ps_handle->rtos;
    rt_err_t result = RT_EOK;

    memset(ps_handle,0,sizeof(usbd_vcom_t));
    result = usbd_vcom_drive_init();
    if(result!=RT_EOK)
    {
        return RT_ERROR;
    }

    result = rt_sem_init(&ps_rtos->sem_rx, "usbd_vcom_sem_rx", 0, RT_IPC_FLAG_FIFO);
    if(result!=RT_EOK)
    {
        return RT_ERROR;
    }

    ps_rtos->thread_rx = rt_thread_create("usbd_vcom_thread_rx", usbd_vcom_thread_rx, ps_handle, USBD_VCOM_THREAD_STACK_SIZE, USBD_VCOM_THREAD_PRIO, USBD_VCOM_THREAD_TICK);
    if (ps_rtos->thread_rx == RT_NULL)
    {
        return RT_ERROR;
    }

    rt_thread_startup(ps_rtos->thread_rx);
}

void usbd_vcom_thread_rx(void *para)
{
    usbd_vcom_t *ps_handle=(usbd_vcom_t*)para;
    usbd_vcom_rtos_t *ps_rtos=&ps_handle->rtos;
    uint8_t b_data=0;

    ps_rtos->is_running_rx=1;

    while (ps_rtos->is_running_rx)
    {
        while (rt_device_read(ps_handle->dev, -1, &b_data, 1) != 1)
        {
            rt_sem_take(&ps_rtos->sem_rx, RT_WAITING_FOREVER);
        }
        rt_device_write(ps_handle->dev, 0, &b_data, 1);
    }
}

15.在main.c文件中增加usbd_vcom.h头文件以及添加usbd_vcom_init()的初始化代码。
在这里插入图片描述
16.编译程序,烧录到电路板中,利用串口调试助手连接上USB对应的的端口,发送数据会回显数据。

<think>好的,我现在需要帮助用户解决RT-Thread Studio中串口终端无法输入的问题。根据用户提供的引用资料,我需要先分析可能的原因,然后逐步给出解决方案。首先,用户提到在引用[1]和[2]中,串口终端无法连接或没有输出,甚至可能导致程序挂掉。这可能涉及到配置错误、硬件问题或者软件冲突。 首先,我应该检查串口配置是否正确。引用[3]提到需要修改宏定义和GPIO设置,这可能意味着用户的UART驱动程序没有正确配置。例如,是否在board.h中启用了UART2,并设置了正确的引脚?另外,用户是否在RT-Thread Settings中打开了对应的串口设备,并配置了正确的参数,比如波特率? 其次,CubeMX的使用可能影响工程。根据引用[4],如果在使用CubeMX生成代码后没有正确关闭,可能会导致RT-Thread Studio无法正常操作。用户需要确认是否在生成代码后关闭了CubeMX,再重新打开工程进行编译。 另外,硬件连接问题也是常见的。用户需要检查串口线是否接触良好,或者是否使用了正确的USB转串口模块。同时,是否有其他软件占用了串口,比如串口调试助手未关闭,导致端口被占用? 还有可能中断冲突或优先级问题。如果用户启用了中断接收,但中断配置不正确,可能导致程序卡死。需要检查中断服务函数是否正确注册,中断优先级是否合理,以及是否在接收数据时处理得当,避免死锁或资源竞争。 最后,用户可能需要查看终端配置,比如是否选择了正确的串口端口,是否在RT-Thread Studio的终端设置中启用了流控制等。有时,关闭流控制(如RTS/CTS)可以解决无法输入的问题。 综合这些可能性,我应该分步骤引导用户逐一排查,从软件配置到硬件连接,确保每个环节都正确无误。同时,参考提供的引用资料中的解决方案,如修改宏定义、检查CubeMX的使用流程、验证串口调试助手的使用情况等,帮助用户找到问题根源并解决。</think>以下为RT-Thread Studio串口终端无法输入问题的逐步解决方案: ### 一、检查硬件配置 1. **确认硬件连接** - 检查USB转串口模块与MCU的UART引脚连接是否正确(TX接RX,RX接TX) - 使用万用表测量串口电压是否正常(通常3.3V电平) 2. **排查硬件冲突** - 尝试更换USB接口或串口模块,排除硬件故障 - 使用其他串口调试工具(如PuTTY)验证串口功能是否正常[^2] --- ### 二、验证软件配置 1. **CubeMX与工程配置冲突** - 若使用CubeMX生成代码,必须关闭CubeMX后再操作RT-Thread Studio[^4] - 在`board.h`中添加UART宏定义(示例): ```c #define BSP_USING_UART2 #define UART2_TX_PIN PA2 #define UART2_RX_PIN PA3 ``` 2. **驱动配置检查** - 在RT-Thread Settings中启用UART设备驱动 - 确认`drv_usart.c`中已注册对应串口的中断服务函数[^3] --- ### 三、排查软件冲突 1. **端口占用问题** - 关闭其他串口调试工具(如SecureCRT、Xshell) - 通过设备管理器检查串口是否被异常占用 2. **终端参数设置** ```python # RT-Thread终端默认参数应匹配代码配置 波特率 = 115200 数据位 = 8 停止位 = 1 校验位 = None ``` - 在Studio终端设置中关闭流控制(RTS/CTS选项) --- ### 四、调试代码逻辑 1. **中断配置验证** - 检查中断优先级设置是否冲突(建议UART中断优先级设为中等级别) - 添加调试语句验证中断触发情况: ```c void UART2_IRQHandler(void) { rt_kprintf("UART2 Interrupt Triggered\n"); // 调试输出 /* 中断处理逻辑 */ } ``` 2. **内存溢出检测** - 使用`list_thread`命令查看线程栈使用情况 - 检查串口接收缓冲区是否溢出(可通过减小接收缓冲区大小测试) --- ### 五、特殊场景处理 若出现**打开终端后程序挂起**的现象: 1. 检查`rt_hw_console_getchar()`函数实现 2. 确认未在中断服务例程(ISR)中调用阻塞式API 3. 使用`hard_fault`调试工具定位异常位置 --- ### 典型解决方案流程图 ```mermaid graph TD A[无法输入] --> B{硬件检测} B -->|正常| C[CubeMX配置验证] B -->|异常| D[更换硬件] C --> E[驱动层检查] E --> F[终端参数匹配] F --> G[中断配置调试] G --> H[功能验证] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值