RT-Thread Studio学习(十七)虚拟串口

news2025/1/7 7:02:38

RT-Thread Studio学习(十七)虚拟串口

  • 一、简介
  • 二、新建RT-Thread项目并使用外部时钟
  • 三、启用USB设备功能
  • 四、测试

一、简介

本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下实现USB虚拟串口。

硬件及开发环境如下:

  • OS WIN10
  • STM32F407VET6
  • STM32CubeMX v6.10.0
  • STM32Cube MCU Package for STM32F4 Series v1.28.0
  • RT-Thread Studio v2.2.7
  • RT-Thread Source Code v5.0.2
  • STM32F4 chip support packages v0.2.3

二、新建RT-Thread项目并使用外部时钟

打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习(一)新建工程》。

三、启用USB设备功能

  1. 打开USB设备驱动框架
    RT-Thread Setting 中借助图形化配置工具打开组件中的USB设备的驱动框架,设置设备类型为Enable to use device as CDC device,如下图所示:
    在这里插入图片描述
  2. 定义USB相关的宏
    board.h文件中使能宏定义
#define BSP_USING_USBDEVICE
  1. 复制USB设备初始化函数
    双击RT-Thread Studio工程中的cubemx.ioc文件,设置USB OTG
    在这里插入图片描述
    在这里插入图片描述
    再重新生成STM32CubeMX代码,将.\cubemx\Src\usbd_conf.c中的函数HAL_PCD_MspInit复制到board.c的末尾。
void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(pcdHandle->Instance==USB_OTG_FS)
  {
  /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */

  /* USER CODE END USB_OTG_FS_MspInit 0 */

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USB_OTG_FS GPIO Configuration
    PA11     ------> USB_OTG_FS_DM
    PA12     ------> USB_OTG_FS_DP
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
    
    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
  /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */

  /* USER CODE END USB_OTG_FS_MspInit 1 */
  }
}
  1. 定义.\cubemx\Inc\stm32f4xx_hal_conf.h中的相关宏
#define HAL_PCD_MODULE_ENABLED

在.\drivers\drv_usbd.c中添加宏定义

#define EP_MPS_64                   0U

在这里插入图片描述

四、测试

修改main.c的代码,主要添加的代码如下:

/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;

//

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

static void serial_thread_entry(void *parameter)
{
    char ch;
    LOG_D("uart_rx_thread_entry runing..\n");
    while (1)
    {
        /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
        while (rt_device_read(serial, -1, &ch, 1) != 1)
        {
            /* 阻塞等待接收信号量,等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        }

        rt_kprintf("%c",ch);
        /* 读取到的数据通过串口错位输出 */
        rt_device_write(serial, 0, &ch, 1);
    }
}

static int serial_init()
{
    rt_err_t ret = RT_EOK;

    /* 查找设备 */
    serial = rt_device_find("vcom");
    if (serial  == RT_NULL)
    {
        rt_kprintf("can't find vcom device!\n");
        return RT_ERROR;
    }
    ret = rt_device_init(serial);
    if (serial  == RT_NULL)
    {
        rt_kprintf("can't initialize vcom device!\n");
        return RT_ERROR;
    }

    /* 打开设备,可读写,中断接收 */
    ret = rt_device_open(serial, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);

    //初始化信号量
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);

    // 设置接收回调函数
    rt_device_set_rx_indicate(serial, uart_input);

    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    if (thread == RT_NULL)
    {
        LOG_E("rt_thread_create failed...\n");
    }
    rt_thread_startup(thread);
    return RT_EOK;
}

在主函数main中,添加

char buf2[64];
for(int i=0; i<64; i++)
    buf2[i] = i;
rt_device_write(serial, 0, buf2, 64);
rt_thread_mdelay(1);

编译后下载,发现在串口调试助手中,能打开CDC串口并发送数据。发送数据不但能通过Bus Hound软件抓包到,而且STM32通过USART1调试口回传至PC,但调试助手的CDC串口却收不到任何数据。
在这里插入图片描述
原因在于STM32虚拟的串口为USB设备,PC端需主动“索取”才能获得rt_device_write发出的数据。
后面在PC端编写了python串口读取程序,才能接收到rt_device_write发出的数据,并且数据速率非常高,达到数百KBps。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1400498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

油管公式(全)

原文&#xff1a;The Youtube Formula 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 每个人都应该有一个 YouTube 频道。真的每个人&#xff0c;尤其是品牌。当我看到没有在 YouTube 上存在的品牌时&#xff0c;我觉得他们疯了。任何人都不利用这个机会是难以想…

python-基础篇-变量

文章目录 变量的基本使用目标01. 变量定义1) 变量演练1 —— iPython2) 变量演练 2 —— PyCharm3) 变量演练 3 —— 超市买苹果思考题 02. 变量的类型2.1 变量类型的演练 —— 个人信息2.2 变量的类型2.3 不同类型变量之间的计算1) **数字型变量** 之间可以直接计算2) **字符串…

从零开始:直播电商APP开发全流程解析

本篇文章&#xff0c;小编将从零开始&#xff0c;全面解析直播电商APP的开发流程&#xff0c;涵盖了关键的技术要点和开发阶段的关键步骤。 第一阶段&#xff1a;需求分析与规划 此阶段的关键任务包括&#xff1a; 1.用户需求调研 2.功能规划 3.技术选型 第二阶段&#xf…

安卓平板局域网内远程控制工控机方法

安卓平板局域网内远程控制工控机方法 将所需要远程控制的工控机通过网线连接到具有WiFi功能的路由器上&#xff0c;将安卓平板连接上WiFi&#xff0c;如下图所示 下载NoMachine远程软件安装包&#xff0c;官网地址&#xff1a;https://www.nomachine.com/ 点击Download now按钮…

图论:最短路(dijkstra算法、bellman算法、spfa算法、floyd算法)详细版

终于是学完了&#xff0c;这个最短路我学了好几天&#xff0c;当然也学了别的算法啦&#xff0c;也是非常的累啊。 话不多说下面看看最短路问题吧。 最短路问题是有向图&#xff0c;要求的是图中一个点到起点的距离&#xff0c;其中我们要输入点和点之间的距离&#xff0c;来求…

【Docker】安装Nginx容器并部署前后端分离项目

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Docker实战》。&#x1f3af;&#x1f3af; &…

代码随想录算法训练营第十一天|● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值

文章目录 20.有效的括号思路&#xff1a;代码&#xff1a; 1047. 删除字符串中的所有相邻重复项思路代码1:栈储存代码2&#xff1a;双指针 150. 逆波兰表达式求值思路&#xff1a;题外话代码 20.有效的括号 思路&#xff1a; 由于栈结构的特殊性&#xff0c;非常适合做对称匹配…

单体架构、微服务和无服务器架构

前言 在这篇文章中&#xff0c;我将演示在决定使用单体架构、微服务架构和无服务器架构时的权衡的简化心智模型。目标是突显每种风格的固有优势和缺陷&#xff0c;并提供关于何时选择哪种架构风格的指导。 单体架构 对于小团队或项目来说是理想的入门架构。它简单易上手&…

Python sleep函数用法:线程睡眠

如果需要让当前正在执行的线程暂停一段时间&#xff0c;并进入阻塞状态&#xff0c;则可以通过调用 time 模块的 sleep(secs) 函数来实现。该函数可指定一个 secs 参数&#xff0c;用于指定线程阻塞多少秒。 当前线程调用 sleep() 函数进入阻塞状态后&#xff0c;在其睡眠时间…

131. 分割回文串 - 力扣(LeetCode)

问题描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 输入示例 s "aab"输出示例 [["a","a","b"],["…

面试2024.1.20

简单介绍下你做的项目。 这个神领物流项目是一个前后端分离的项目&#xff0c;前段他有3个客户端&#xff08;用户端为微信小程序、司机端和快递员端为app&#xff09;一个管理端&#xff08;pc&#xff09;&#xff0c;后端用的技术栈用的是SpringAlibabaCloud、数据库用的是M…

《Aspect-Sentiment-Multiple-Opinion Triplet Extraction》论文阅读

文章目录 文章介绍文章模型encoder部分ATE任务TOWE任务ATSA任务 番外 文章地址&#xff1a; https://arxiv.org/abs/2110.07303v1 文章介绍 目前的关于ASTE三元组提取的方面级情感分析论文大多关注于简单的句式&#xff0c;比如一个方面实体仅有一个意见词加以修饰&#xff0c…

CCC数字钥匙设计【NFC基础】--LPCD相关介绍

关于NFC卡检测&#xff0c;主要可以分成两个步骤&#xff1a; 1、LPCD低功耗检测&#xff0c;唤醒NFC读卡器。 2、唤醒后&#xff0c;NFC读卡器或MCU控制器轮询Type A、Type B、Type F、Type V&#xff08;ISO15693&#xff09;等卡类型。 本文主要介绍LPCD相关功能&#xff…

AI向所有的绝症宣战?2024年将被AI颠覆的行业-医疗健康

近年来&#xff0c;人工智能技术在我国得到了迅猛发展&#xff0c;不仅在互联网、金融、交通、零售、农业等领域取得了显著成果&#xff0c;还逐渐渗透到了医疗健康行业。预测2024年&#xff0c;人工智能将在医疗领域的应用发挥更深远的影响&#xff0c;甚至有可能颠覆整个医疗…

【MySQL】where和having的区别

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;数据库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 用途: 使用位置: 操作对象: 聚合函数: 示例&#xff1a; 结语 我的其他博客 前言 数据库中的 WHERE 和 HAVING 子句在 SQL 查…

【Linux】python版本控制

文章目录 1.查看目前python的版本2.添加软件源并更新3.选择你想要下载的版本4.警示&#xff1a;没必要设置默认版本误区千万千万不要覆盖python3软链接解决办法 5.安装pip换源 6.环境管理 网上有很多教程都是教导小白去官方下载之后编译安装。但是&#xff0c;小白连cmake是什么…

【LeetCode: 295. 数据流的中位数 + 堆】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

羊驼系列大模型LLaMa、Alpaca、Vicuna

羊驼系列大模型&#xff1a;大模型的安卓系统 GPT系列&#xff1a;类比ios系统&#xff0c;不开源 LLaMa让大模型平民化 LLaMa优势 用到的数据&#xff1a;大部分英语、西班牙语&#xff0c;少中文 模型下载地址 https://huggingface.co/meta-llama Alpaca模型 Alpaca是斯…

Datawhale 强化学习笔记(三)基于策略梯度(policy-based)的算法

文章目录 参考基于价值函数的缺点策略梯度算法REINFORCE 算法策略梯度推导进阶策略函数的设计离散动作的策略函数连续动作的策略函数 参考 第九章 策略梯度 之前介绍的 DQN 算法属于基于价值(value-based)的算法&#xff0c;基于策略梯度的算法直接对策略本身进行优化。 将策…

stm32 FOC系列 直流有刷控制原理

1、直流有刷驱动板 使用三极管搭建的简易 H 桥电路&#xff0c;如图 5.3.1 所示&#xff1a; 图 5.3.1 是使用三极管搭建的简易 H 桥电路&#xff0c;其中 MOTOR 表示直流有刷电机&#xff0c; Q1、 Q2、 Q3 和 Q4 为 4 个三极管&#xff0c;其中 Q1 和 Q3 接在了电源正极&…