零基础国产GD32单片机编程入门(二十五)USB口介绍及CDC类虚拟串口通讯详解及源码

文章目录

    • 一.概要
    • 二.USB2.0基本介绍及虚拟串口介绍
    • 三.GD32单片机USB模块框图
    • 四.GD32单片机USB设备模式
    • 五.GD32F103C8T6 USB设备CDC类
    • 六.配置一个USB虚拟串口收发例程
    • 七.工程源代码下载
    • 八.小结

一.概要

GD32F103C8T6 USB虚拟串口是一种采用GD32F103C8T6单片机,通过USB接口连接电脑,将电脑的USB接口转换成串口接口,实现与电脑的通信的一种转换器。它可以实现与电脑的通信,还可以实现与外部设备的通信,广泛应用于工业控制、智能家居、智能硬件等领域。

本文介绍了GD32单片机USB口的基本概念,内部结构,以及用USB虚拟串口进行数据通讯的例程。

二.USB2.0基本介绍及虚拟串口介绍

USB2.0使用一对差分信号传输数据,并可以为USB设备提供电源。差分信号名称一般标示为“D+”和“D-”。
USB2.0可以支持三种传输速率:低速USB设备传输速率为1.5Mbps,全速USB设备传输速率为12Mbps,高速USB设备传输速率为480Mbps。GD32F103C8T6就属于全速USB设备传输,最快12Mbps。
在硬件电路方面,全速USB设备内部的“D+”信号应该通过1.5K的电阻上拉到3~3.6V。

USB虚拟串口,简称VCP,是Virtual COM Port的简写,它是利用 USB的 CDC类来实现的一种通信接口。我们可以利用GD32自带的USB功能,来实现一个USB虚拟串口,从而通过USB,实现电脑与GD32单片机的数据互传。

三.GD32单片机USB模块框图

GD32单片机通用串行总线全速设备接口(USBD)模块提供了一个实现符合USB 2.0全速协议外设的方案。它内部包含了一个USB物理层而不需要额外的外部物理层芯片。USBD支持USB 2.0协议所定义的四种传输类型(控制、批量、中断和同步传输)

在这里插入图片描述

SIE
• 硬件识别同步信号、进行比特填充、产生以及校验CRC、产生以及验证PID、握手 。
• 根据外设事件来产生SOF、复位信号等。

Packet Buffer interface
• 通过一组收、发buffer来管理512字节的local memory。
• 硬件根据来自SIE的请求来选择合适的buffer。

寄存器
• EndPoint相关的寄存器:该EP的传输类型、地址、当前状态 。
• 控制寄存器:控制USB模块事件(比如唤醒和休眠)和反应USB模块当前状态 。
• 中断寄存器:中断掩码,记录事件。

根据USB标准定义,USB全速模块采用了固定的48MHz时钟。要使用USBD,需要打开两个时钟,一个是USB控制器时钟,它的频率必须配到48MHz,另一个是APB1到USB接口时钟,它也是APB1的总线时钟,其频率可以高于也可以低于48MHz。

四.GD32单片机USB设备模式

USB一般有两种模式,主机模式,设备模式。

USB主机模式:‌在主机模式下,‌单片机能够枚举外部USB设备,‌如键盘、‌鼠标、‌闪存盘等,‌并对其进行配置和管理。‌这种模式适用于需要同时连接多个外部设备并进行数据交换的复杂应用场景。

USB设备模式:‌在设备模式下,‌单片机作为USB设备的角色,‌可以与主机进行通信。‌这包括配置USB设备描述符、‌初始化USB控制器、‌编写类处理函数等,‌以实现特定的通信需求。‌GD32支持多种USB类,‌如CDC(‌通信设备类)‌、‌HID(‌人机接口设备类)‌、‌MSC(‌大容量存储类)‌等,‌以满足不同的应用场景。

GD32F103C8T6只支持设备模式,在设备模式下,GD32可以模拟各种USB类设备,如键盘、鼠标、存储设备等,开发者需要配置USB接口并实现特定的USB类。

在这里插入图片描述

五.GD32F103C8T6 USB设备CDC类

CDC(Communication Device Class)类是 USB2.0 标准下的一个子类,定义了通信相关设备的抽象集合,我们虚拟串口通信就是CDC类。USB2.0标准下定义了很多子类,有音频类,CDC类,HID,打印,大容量存储类HUB,智能卡等等,这些在urb.org 官网上有具体的定义,这里我们主要讲的是通信类CDC。

USB CDC类的通信部分主要包含三部分:枚举过程、虚拟串口操作和数据通信。其中虚拟串口操作部分并不一定强制需要,因为若跳过这些虚拟串口的操作,实际上USB依然是可以通信的,之所以会有虚拟串口操作,主要是我们通常使用PC作为Host端,在PC端使用一个串口工具来与其进行通信,PC端的对应驱动将其虚拟成一个普通串口,这样一来,可以方便PC端软件通过操作串口的方式来与其进行通信,但实际上,Host端与Device端物理上是通过USB总线来进行通信的,与串口没有关系,这一虚拟化过程,起决定性作用的是对应驱动,包含如何将每一条具体的虚拟串口操作对应到实际上的USB操作。这里需要注意地是,Host端与Device端的USB通信速率并不受所谓的串口波特率影响,它就是标准的USB2.0全速(12Mbps)速度,实际速率取决于总线的实际使用率、驱动访问USB外设有效速率(两边)以及外部环境对通信本身造成的干扰率等等因素组成。

USB CDC类实现了规范的下列方面:
• 设备描述符管理
• 配置描述符管理
• 枚举为具有2个数据端点(IN和OUT)的CDC设备和一个指令端点(IN)
• 请求管理(如规范6.2节所述)
• 抽象控制模型兼容
• 联合体功能收集(使用1个IN端点控制)
• 数据接口类

CDC软件框架简介
当USBD设备初始化且枚举完成后,USB设备首先通过cdc_acm_check_ready()函数check是否准备数据发送,如果不需要发送就调用cdc_acm_data_receive()函数接收上位机发送的数据,如果需要发送就调用cdc_acm_data_send()将接收到的数据发送给主机。

设备描述符如下所示,其中bDevcieClass为0x02,表明当前设备为CDC设备类。

/* note:it should use the C99 standard when compiling the below codes */
/* USB standard device descriptor */
const usb_descriptor_device_struct device_descriptor =
{.Header = {.bLength = USB_DEVICE_DESC_SIZE, .bDescriptorType = USB_DESCTYPE_DEVICE},.bcdUSB = 0x0200,.bDeviceClass = 0x02,.bDeviceSubClass = 0x00,.bDeviceProtocol = 0x00,.bMaxPacketSize0 = USBD_EP0_MAX_SIZE,.idVendor = USBD_VID,.idProduct = USBD_PID,.bcdDevice = 0x0100,.iManufacturer = USBD_MFC_STR_IDX,.iProduct = USBD_PRODUCT_STR_IDX,.iSerialNumber = USBD_SERIAL_STR_IDX,.bNumberConfigurations = USBD_CFG_MAX_NUM
};

由配置描述符可知,该USB虚拟串口设备包含两个接口:CMD命令接口和data数据接口。CMD命令接口包含一个IN端点,用于传输命令,该端点采用中断传输方式,轮询间隔为10ms,最大包长为8字节。data数据接口包含一个OUT端点和一个IN端点,这两个端点均采用批量传输方式,最大包长为64字节。另外,该配置描述符中包含了一些类特殊接口描述符,具体请读者参阅CDC类标准协议。

/* USB device configuration descriptor */
usb_descriptor_configuration_set_struct configuration_descriptor = 
{.cdc_loopback_cmd_endpoint = {.Header = {.bLength = sizeof(usb_descriptor_endpoint_struct), .bDescriptorType = USB_DESCTYPE_ENDPOINT},.bEndpointAddress = CDC_ACM_CMD_EP,.bmAttributes = 0x03,.wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE,.bInterval = 0x0A},.cdc_loopback_data_interface = {.Header = {.bLength = sizeof(usb_descriptor_interface_struct), .bDescriptorType = USB_DESCTYPE_INTERFACE},.bInterfaceNumber = 0x01,.bAlternateSetting = 0x00,.bNumEndpoints = 0x02,.bInterfaceClass = 0x0A,.bInterfaceSubClass = 0x00,.bInterfaceProtocol = 0x00,.iInterface = 0x00},.cdc_loopback_out_endpoint = {.Header = {.bLength = sizeof(usb_descriptor_endpoint_struct), .bDescriptorType = USB_DESCTYPE_ENDPOINT },.bEndpointAddress = CDC_ACM_DATA_OUT_EP,.bmAttributes = 0x02,.wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE,.bInterval = 0x00},.cdc_loopback_in_endpoint = {.Header = {.bLength = sizeof(usb_descriptor_endpoint_struct), .bDescriptorType = USB_DESCTYPE_ENDPOINT },.bEndpointAddress = CDC_ACM_DATA_IN_EP,.bmAttributes = 0x02,.wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE,.bInterval = 0x00}
};

为了实现CDC设备类,设备需要支持一些设备类专用请求,这些类专用请求的处理在cdc_acm_req_handler()函数中,该函数的定义如下所示,其中SET_LINE_CODING命令用于响应主机向设备发送设备配置,包括波特率、停止位、字符位数等,收到的数据保存在noti_bu内。GET_LINE_CODING命令用于主机请求设备当前的波特率、停止位、奇偶校验位和字符位数,但在本例程中,主机并未请求该命令,所以设备所设置的串口数据并没有作用,主机可以选择任意波特率与设备进行通信。

/*!\brief      handle the CDC ACM class-specific requests\param[in]  pudev: pointer to USB device instance\param[in]  req: device class-specific request\param[out] none\retval     USB device operation status
*/
usbd_status_enum cdc_acm_req_handler (void *pudev, usb_device_req_struct *req)
{uint16_t len = CDC_ACM_DESC_SIZE;uint8_t  *pbuf= (uint8_t*)(&configuration_descriptor) + 9;switch (req->bmRequestType & USB_REQ_MASK) {case USB_CLASS_REQ:switch (req->bRequest) {case SEND_ENCAPSULATED_COMMAND:break;case GET_ENCAPSULATED_RESPONSE:break;case SET_COMM_FEATURE:break;case GET_COMM_FEATURE:break;case CLEAR_COMM_FEATURE:break;case SET_LINE_CODING:/* set the value of the current command to be processed */cdc_cmd = req->bRequest;/* enable EP0 prepare to receive command data packet */usbd_ep_rx (pudev, EP0_OUT, usb_cmd_buffer, req->wLength);break;case GET_LINE_CODING:usb_cmd_buffer[0] = (uint8_t)(linecoding.dwDTERate);usb_cmd_buffer[1] = (uint8_t)(linecoding.dwDTERate >> 8);usb_cmd_buffer[2] = (uint8_t)(linecoding.dwDTERate >> 16);usb_cmd_buffer[3] = (uint8_t)(linecoding.dwDTERate >> 24);usb_cmd_buffer[4] = linecoding.bCharFormat;usb_cmd_buffer[5] = linecoding.bParityType;usb_cmd_buffer[6] = linecoding.bDataBits;/* send the request data to the host */usbd_ep_tx (pudev, EP0_IN, usb_cmd_buffer, req->wLength);break;case SET_CONTROL_LINE_STATE:break;case SEND_BREAK:break;default:break;}break;case USB_STANDARD_REQ:/* standard device request */switch(req->bRequest) {case USBREQ_GET_INTERFACE:usbd_ep_tx(pudev, EP0_IN, (uint8_t *)&usbd_cdc_altset, 1);break;case USBREQ_SET_INTERFACE:if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM) {usbd_cdc_altset = (uint8_t)(req->wValue);} else {/* call the error management function (command will be nacked */usbd_enum_error (pudev, req);}break;case USBREQ_GET_DESCRIPTOR:if(CDC_ACM_DESC_TYPE == (req->wValue >> 8)){len = MIN(CDC_ACM_DESC_SIZE, req->wLength);pbuf = (uint8_t*)(&configuration_descriptor) + 9 + (9 * USBD_ITF_MAX_NUM);}usbd_ep_tx(pudev, EP0_IN, pbuf, len);break;default:break;}default:break;}return USBD_OK;
}

数据接收通过cdc_acm_data_receive()函数实现,该函数的程序如下所示。在该函数中,首先将packet_receive标志位设置为0,表明接下来将进行接收数据,当接收完成时,在cdc_acm_data_handler ()函数中,将packet_receive标志位置1,表明数据接收完成。usbd_ep_rx()用于配置接收操作,利用CDC_OUT_EP端点,将接收到的数据放置在用户缓冲区中。

/*!\brief      receive CDC ACM data\param[in]  pudev: pointer to USB device instance\param[out] none\retval     USB device operation status
*/
void cdc_acm_data_receive(void *pudev)
{packet_receive = 0;usbd_ep_rx(pudev, CDC_ACM_DATA_OUT_EP, (uint8_t*)(usb_data_buffer), CDC_ACM_DATA_PACKET_SIZE);
}/*!\brief      endpoint prepare to receive data\param[in]  pudev: pointer to usb core instance\param[in]  ep_addr: endpoint addressin this parameter:bit0..bit6: endpoint number (0..7)bit7: endpoint direction which can be IN(1) or OUT(0)\param[in]  pbuf: user buffer address pointer\param[in]  buf_len: buffer length\param[out] none\retval     none
*/
void  usbd_ep_rx (usbd_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len)
{usb_ep_struct *ep;uint8_t ep_num = ep_addr & 0x7FU;ep = &pudev->out_ep[ep_num];/* configure the transaction level parameters */ep->trs_buf = pbuf;ep->trs_len = buf_len;/* enable endpoint to receive */USBD_ENDP_RX_STATUS_SET(ep_num, EPRX_VALID);
}
/*!\brief      handle CDC ACM data\param[in]  pudev: pointer to USB device instance\param[in]  rx_tx: data transfer direction:\arg        USBD_TX\arg        USBD_RX\param[in]  ep_id: endpoint identifier\param[out] none\retval     USB device operation status
*/
usbd_status_enum  cdc_acm_data_handler (void *pudev, usbd_dir_enum rx_tx, uint8_t ep_id)
{if ((USBD_TX == rx_tx) && ((CDC_ACM_DATA_IN_EP & 0x7F) == ep_id)) {packet_sent = 1;return USBD_OK;} else if ((USBD_RX == rx_tx) && ((EP0_OUT & 0x7F) == ep_id)) {cdc_acm_EP0_RxReady (pudev);} else if ((USBD_RX == rx_tx) && ((CDC_ACM_DATA_OUT_EP & 0x7F) == ep_id)) {packet_receive = 1;receive_length = usbd_rx_count_get(pudev, CDC_ACM_DATA_OUT_EP);return USBD_OK;}return USBD_FAIL;
}

数据发送通过cdc_acm_data_send()函数实现,该函数的程序如下所示。在该函数中,首先将packet_sent标志位设置为0,表明接下来将进行发送数据,当数据发送完成时,在cdc_acm_data_handler ()函数中,将packet_sent标志位设置为1,表明数据发送完成。usbd_ep_tx()用于配置发送操作,利用CDC_IN_EP端点,将以 ep->trs_buf地址为起始trs_len 长度的数据发送给主机。

void cdc_acm_data_send (void *pudev, uint32_t data_len)
{/* limit the transfer data length */if (data_len <= CDC_ACM_DATA_PACKET_SIZE) {packet_sent = 0;usbd_ep_tx(pudev, CDC_ACM_DATA_IN_EP, (uint8_t*)(usb_data_buffer), data_len);}
}usbd_status_enum  cdc_acm_data_handler (void *pudev, usbd_dir_enum rx_tx, uint8_t ep_id)
{if ((USBD_TX == rx_tx) && ((CDC_ACM_DATA_IN_EP & 0x7F) == ep_id)) {packet_sent = 1;return USBD_OK;} else if ((USBD_RX == rx_tx) && ((EP0_OUT & 0x7F) == ep_id)) {cdc_acm_EP0_RxReady (pudev);} else if ((USBD_RX == rx_tx) && ((CDC_ACM_DATA_OUT_EP & 0x7F) == ep_id)) {packet_receive = 1;receive_length = usbd_rx_count_get(pudev, CDC_ACM_DATA_OUT_EP);return USBD_OK;}return USBD_FAIL;
}
void  usbd_ep_tx (usbd_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len)
{__IO uint32_t len = 0U;uint8_t ep_num = ep_addr & 0x7FU;usb_ep_struct *ep = &pudev->in_ep[ep_num];/* configure the transaction level parameters */ep->trs_buf = pbuf;ep->trs_len = buf_len;ep->trs_count = 0U;/* transmit length is more than one packet */if (ep->trs_len > ep->maxpacket) {len = ep->maxpacket;} else {len = ep->trs_len;}usbd_ep_data_write(ep->trs_buf, (pbuf_reg + ep_num)->tx_addr, (uint16_t)len);(pbuf_reg + ep_num)->tx_count = (uint16_t)len;/* enable endpoint to transmit */USBD_ENDP_TX_STATUS_SET(ep_num, EPTX_VALID);
}

六.配置一个USB虚拟串口收发例程

STLINK接GD32F103C8T6开发板,STLINK接电脑USB口。

在这里插入图片描述

主要代码

#include "gd32f10x.h"
#include "gd32f10x_libopt.h"
#include "systick.h"
#include "cdc_acm_core.h"extern uint8_t packet_sent, packet_receive;
extern uint32_t receive_length;
extern uint8_t usb_data_buffer[CDC_ACM_DATA_PACKET_SIZE];//定义 CDC-ACM 类的 USB 设备
usbd_core_handle_struct  usb_device_dev = 
{.dev_desc = (uint8_t *)&device_descriptor,.config_desc = (uint8_t *)&configuration_descriptor,.strings = usbd_strings,.class_init = cdc_acm_init,.class_deinit = cdc_acm_deinit,.class_req_handler = cdc_acm_req_handler,.class_data_handler = cdc_acm_data_handler
};//中断使能
void nvic_config(void)
{/* 1 bit for pre-emption priority, 3 bits for subpriority */nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);/* enable the USB low priority interrupt */nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 1, 0);
}
int main(void)
{rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1);//设置主频72M(#define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000)),8M外部晶振  (#define HXTAL_VALUE    ((uint32_t)8000000))systick_config();//配置1ms SysTickrcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_AF);//AF时钟使能 /* configure USB model clock from PLL clock */rcu_usb_clock_config(RCU_CKUSB_CKPLL_DIV1_5);//72M主频,1.5分频,就是48M/* enable USB APB1 clock */rcu_periph_clock_enable(RCU_USBD);/* USB device configuration */usbd_core_init(&usb_device_dev);/* NVIC configuration */nvic_config();/* now the usb device is connected */usb_device_dev.status = USBD_CONNECTED;while (1){if (USBD_CONFIGURED == usb_device_dev.status) {if (1 == packet_receive && 1 == packet_sent) {//有数据接收到packet_sent = 0;/* receive datas from the host when the last packet datas have sent to the host */cdc_acm_data_receive(&usb_device_dev);//接收数据} else {if (0 != receive_length) {/* send receive datas */cdc_acm_data_send(&usb_device_dev, receive_length);//发送接收到的数据receive_length = 0;}}}}}

实验效果
下载完程序,用 USB 线接板子USB 口,再接电脑,打开电脑上串口调试器,9600 波特率,8 位数据,无校验,发送 HELLOWORLD,板子就会返回 HELLOWORLD。
在这里插入图片描述

七.工程源代码下载

通过网盘分享的文件:27.USB虚拟串口通信实验.zip
链接: https://pan.baidu.com/s/1MDB8vX7EtFcuV_LcKmBh_Q 提取码: cp9x

如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行

八.小结

USB虚拟串口可以实现与电脑的通信,还可以实现与外部设备的通信,广泛应用于工业控制、智能家居、智能硬件等领域。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode中使用go环境配置细节

1、在docker容器中下载了go的sdk 2、在/etc/profile.d/go.sh里填入如下内容&#xff1a; #!/bin/bashexport GOROOT/home/ud_dev/go export PATH$GOROOT/bin:$PATH3、设置go env go env -w GOPROXYhttps://goproxy.cn,direct go env -w GO111MODULEon 4、重启这个容器&#…

Java之ArrayList

1.ArrayList的简介 在集合框架中&#xff0c;ArrayList是一个普通的类&#xff0c;实现了List接口&#xff0c;具体框架图如下&#xff1a; ArrayList是以泛型方式实现的&#xff0c;使用时必须要先实例化ArrayList实现了RandomAccess接口&#xff0c;表明ArrayList支持随机…

springboot对数据库进行备份+对一个文件夹内的文件按时间排序,只保留最近的8个文件

首先&#xff0c;对数据库进行备份&#xff0c;用到的命令&#xff1a; mysqldump --opt -h 192.168.1.200 --userroot --passwordxxx --result-fileE://data//20240911141400.sql --default-character-setutf8 xxx&#xff08;数据库名&#xff09; 直接上代码 配置文件部分…

速通GPT-3:Language Models are Few-Shot Learners全文解读

文章目录 GPT系列论文速通论文实验总览1. 任务设置与测试策略2. 任务类别3. 关键实验结果4. 数据污染与实验局限性5. 总结与贡献 Abstract1. 概括2. 具体分析3. 摘要全文翻译4. 为什么不需要梯度更新或微调⭐ Introduction1. 概括2. 具体分析3. 进一步分析 Approach1. 概括2. 具…

app抓包 chrome://inspect/#devices

一、前言&#xff1a; 1.首先不支持flutter框架&#xff0c;可支持ionic、taro 2.初次需要翻墙 3.app为debug包&#xff0c;非release 二、具体步骤 1.谷歌浏览器地址&#xff1a;chrome://inspect/#devices qq浏览器地址&#xff1a;qqbrowser://inspect/#devi…

C++:C++的IO流

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 C语言的输入与输出 二 流 三 CIO流 ​编辑 3.1 C标准IO流 3.2 C文件IO流 3.3 stringstream的简单介绍 四 CIO流的效率问题 总结 前言 本篇详细介绍了进一步介绍C中的IO流&#…

点可云ERP进销存V8版本PHPstudy(小皮)安装讲解

安装视频讲解链接&#xff1a; 点可云ERP教程 - PHPstudy安装篇_哔哩哔哩_bilibili 1、下载准备 PHPstudy可在官网下载&#xff08;https://www.xp.cn/&#xff09;不推荐在Linux系统安装小皮面板&#xff0c;Linux系统还是使用宝塔较好&#xff0c; 在PHPstudy官网下载时需要…

Rust运算符

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) https://blog.csdn.net/brucexia/category_12779443.html 前面已经学习了变量和常量&#xff0c;本节开始对它们进行操作&#xff0c…

第三方软件测评机构分享:软件性能测试的测试方法和内容

软件性能测试是对软件系统在特定负载和条件下的性能进行评估的过程。它旨在确定软件的响应时间、稳定性、资源消耗及其可扩展性&#xff0c;以确保其在实际环境中能够满足用户的需求。通过性能测试&#xff0c;开发团队能够发现潜在的瓶颈问题&#xff0c;优化应用程序架构&…

前端:JavaScript 实现类

文章目录 1. Es6-类-class2. Es6-class 实现继承3. Es6-class 静态属性和私有属性4. Es5-寄生组合式继承 1. Es6-类-class 类是创建对象的模板&#xff0c;用代码封装数据以处理该数据&#xff0c;js中的类建立在原型上。 如何定义类&#xff0c;首先需要关键字 class&#x…

聊天组件 Vue3-beautiful-chat

前言 最近很多公司都在搞大模型&#xff0c;类似于 chatgpt 的功能&#xff1b;而 chatgpt 的界面其实就是个对话框。今天就介绍一个不错的对话框组件 Vue3-beautiful-chat 项目框架 vite vue3 TS Vue3-beautiful-chat 使用流程 1、引用三方件 npm install Vue3-beaut…

【JAVA基础】实现Tomcat基本功能

文章目录 TCP/IP协议Socket编程ServletTomcat 在搜索了两三天之后&#xff0c;也是大概弄懂了Tomcat是个什么东西&#xff0c;我们在说Tomcat之前&#xff0c;先来了解一下下面这三个东西&#xff1a; TCP/IP协议 TCP/IP 是互联网通信的基础协议。TCP&#xff08;传输控制协议…

SpringBoot框架下的房产销售系统开发

第一章 绪 论 1.1背景及意义 房产销售也都将通过计算机进行整体智能化操作&#xff0c;对于房产销售系统所牵扯的管理及数据保存都是非常多的&#xff0c;例如管理员&#xff1b;首页、个人中心、用户管理、销售经理管理、房源信息管理、房源类型管理、房子户型管理、交易订单管…

《Python青少年趣味编程108例》书籍介绍

文章目录 前言为什么选择Python&#xff1f;书籍介绍文章目录配套资源 前言 在这个数字化飞速发展的时代&#xff0c;编程已经成为了一项不可或缺的技能。对于青少年而言&#xff0c;学习编程不仅能够培养逻辑思维、解决问题的能力&#xff0c;还能激发无限创意&#xff0c;让…

【吊打面试官系列-Redis面试题】如果有大量的 key 需要设置同一时间过期,一般需要注意什么?

大家好&#xff0c;我是锋哥。今天分享关于【如果有大量的 key 需要设置同一时间过期&#xff0c;一般需要注意什么&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 如果有大量的 key 需要设置同一时间过期&#xff0c;一般需要注意什么&#xff1f; 如果大量的…

Windows terminal使用说明

1 terminal基本介绍 1 下载 从微软商店上下载的方式网速比较慢&#xff0c;一种直接的方式是直接用命令行运行命令 winget install --idMicrosoft.WindowsTerminal -e# Window Terminal 安装以及使用(2021最新) 2 ssh配置 # 使用Windows Terminal进行SSH登录 1 通过label…

安泰功率放大器的使用方法及注意事项有哪些

功率放大器是一种用来增加输入信号功率的电子设备。它在各种电子设备和通信系统中被广泛应用&#xff0c;如音响设备、收发器、无线通信设备等。使用功率放大器时&#xff0c;有一些重要的注意事项需要注意&#xff0c;以确保其正常运行并保护设备。 首先&#xff0c;正确的功率…

【数据结构与算法 | 灵神题单 | 分治(链表)篇】力扣148

1. 力扣148&#xff1a;排序链表 1.1 题目&#xff1a; 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4…

Unity程序基础框架

概述 单例模式基类 没有继承 MonoBehaviour 继承了 MonoBehaviour 的两种单例模式的写法 缓存池模块 &#xff08;确实挺有用&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;/// <summary> /// 缓存池模块 /// 知识点 //…

C++STL~~stackqueue

文章目录 容器适配器一、stack&queue的概念二、stack&queue的使用三、stack&queue的练习四、总结 容器适配器 什么是适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将一个类…