GD32F407單片機開發入門(二十八)USB口介紹及CDC類虛擬串口通訊詳解及源碼

文章目錄

    • 一.概要
    • 二.USB2.0基本介紹及虛擬串口介紹
    • 三.GD32單片機USB模塊框圖
    • 四.GD32單片機USB設備模式
    • 五.GD32F407VET6 USB設備CDC類
    • 六.配置一個USB虛擬串口收發例程
    • 七.工程源代碼下載
    • 八.小結

一.概要

GD32F407VET6USB虛擬串口是一種采用GD32F407VET6單片機,通過USB接口連接電腦,將電腦的USB接口轉換成串口接口,實現與電腦的通信的一種轉換器。它可以實現與電腦的通信,還可以實現與外部設備的通信,廣泛應用于工業控制、智能家居、智能硬件等領域。

本文介紹了GD32單片機USB口的基本概念,內部結構,以及用USB虛擬串口進行數據通訊的例程。

二.USB2.0基本介紹及虛擬串口介紹

USB2.0使用一對差分信號傳輸數據,并可以為USB設備提供電源。差分信號名稱一般標示為“D+”和“D-”。
USB2.0可以支持三種傳輸速率:低速USB設備傳輸速率為1.5Mbps,全速USB設備傳輸速率為12Mbps,高速USB設備傳輸速率為480Mbps。GD32F407VET6支持全速USB設備傳輸,最快12Mbps。
在硬件電路方面,全速USB設備內部的“D+”信號應該通過1.5K的電阻上拉到3~3.6V,單片機USB口原理圖如下所示,PA11,PA12連接單片機對應的引腳。
在這里插入圖片描述

USB虛擬串口,簡稱VCP,是Virtual COM Port的簡寫,它是利用 USB的 CDC類來實現的一種通信接口。我們可以利用GD32自帶的USB功能,來實現一個USB虛擬串口,從而通過USB,實現電腦與GD32單片機的數據互傳。

三.GD32單片機USB模塊框圖

USB全速(USBFS)控制器為便攜式設備提供了一套USB通信解決方案。USBFS不僅提供了主機模式和設備模式,也提供了遵循HNP(主機協商協議)和SRP(會話請求協議)的OTG模式。USBFS包含了一個內部的全速USB PHY,并且不再需要外部PHY芯片。USBFS可提供USB 2.0協議所定義的所有四種傳輸方式(控制傳輸、批量傳輸、中斷傳輸和同步傳輸)。

在這里插入圖片描述

SIE
硬件識別同步信號、進行比特填充、產生以及校驗CRC、產生以及驗證PID、握手 。根據外設事件來產生SOF、復位信號等。

USB FS PHY
內部PHY支持主機模式下的全速和低速、設備模式下全速以及具備HNP和SRP的OTG協議。USBFS所使用的USB時鐘需要配置為48MHz。該48MHz USB時鐘從系統內部時鐘產生,并且其時鐘源和分頻器需要在RCU模塊中配置。

OTG Control
OTG Control模塊主要用于管理其集成的USB On-The-Go(OTG)功能,實現設備在主機(Host)和從設備(Device)模式間的動態切換及控制。主要功能有模式切換(主機/設備)、電源管理(比如VBUS供電的控制)、會話請求協議(Session Request Protocol, SRP)和主機協商協議(Host Negotiation Protocol, HNP),以及相關的寄存器配置。

Host Port Control
Host Port Control模塊專門用于管理和控制其USB OTG(On-The-Go)功能中的主機模式(Host Mode)操作。當單片機作為USB主機時,該模塊負責與連接的USB從設備(如U盤、鍵盤、鼠標等)進行通信、供電及數據傳輸的底層控制。

根據USB標準定義,USB全速模塊采用了固定的48MHz時鐘。要使用USBD,需要打開兩個時鐘,一個是USB控制器時鐘,它的頻率必須配到48MHz,另一個是APB1到USB接口時鐘,它也是APB1的總線時鐘,其頻率可以高于也可以低于48MHz。

四.GD32單片機USB設備模式

USB一般有兩種模式,主機模式,設備模式。

USB主機模式:?在主機模式下,?單片機能夠枚舉外部USB設備,?如鍵盤、?鼠標、?閃存盤等,?并對其進行配置和管理。?這種模式適用于需要同時連接多個外部設備并進行數據交換的復雜應用場景。

USB設備模式:?在設備模式下,?單片機作為USB設備的角色,?可以與主機進行通信。?這包括配置USB設備描述符、?初始化USB控制器、?編寫類處理函數等,?以實現特定的通信需求。?GD32支持多種USB類,?如CDC(?通信設備類)?、?HID(?人機接口設備類)?、?MSC(?大容量存儲類)?等,?以滿足不同的應用場景。

GD32F407VET6支持主機模式也支持設備模式,在設備模式下,GD32可以模擬各種USB類設備,如鍵盤、鼠標、存儲設備等,開發者需要配置USB接口并實現特定的USB類。

在這里插入圖片描述

五.GD32F407VET6 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(Communication Device Class)類的枚舉是USB設備插入主機時,主機識別其為通信設備(如虛擬串口)并完成配置的關鍵過程。其核心在于描述符的聲明和接口的劃分,確保主機能夠正確加載驅動并建立通信通道。
CDC枚舉的主要流程
1.設備插入與復位
2.設備描述符(Device Descriptor)
3.配置描述符(Configuration Descriptor)
4.CDC類特定描述符(Class-Specific Descriptors)
5.端點描述符(Endpoint Descriptor)
6.主機響應流程

CDC軟件框架簡介
當USBD設備初始化且枚舉完成后,USB設備首先通過cdc_acm_check_ready()函數check是否準備數據發送,如果不需要發送就調用cdc_acm_data_receive()函數接收上位機發送的數據,如果需要發送就調用cdc_acm_data_send()將接收到的數據發送給主機。

設備描述符如下所示,其中bDeviceClass 為0x02,表明當前設備為CDC設備類。

__ALIGN_BEGIN const usb_desc_dev cdc_dev_desc __ALIGN_END =
{.header = {.bLength          = USB_DEV_DESC_LEN, .bDescriptorType  = USB_DESCTYPE_DEV,},.bcdUSB                = 0x0200U,.bDeviceClass          = USB_CLASS_CDC,.bDeviceSubClass       = 0x00U,.bDeviceProtocol       = 0x00U,.bMaxPacketSize0       = USB_FS_EP0_MAX_LEN,.idVendor              = USBD_VID,.idProduct             = USBD_PID,.bcdDevice             = 0x0100U,.iManufacturer         = STR_IDX_MFC,.iProduct              = STR_IDX_PRODUCT,.iSerialNumber         = STR_IDX_SERIAL,.bNumberConfigurations = USBD_CFG_MAX_NUM,
};

由配置描述符可知,該USB虛擬串口設備包含兩個接口:CMD命令接口和data數據接口。CMD命令接口包含一個IN端點,用于傳輸命令,該端點采用中斷傳輸方式,輪詢間隔為5ms,最大包長為8字節。data數據接口包含一個OUT端點和一個IN端點,這兩個端點均采用批量傳輸方式,最大包長為USB_CDC_DATA_PACKET_SIZE(64)字節。另外,該配置描述符中包含了一些類特殊接口描述符,具體請讀者參閱CDC類標準協議。

/* USB device configuration descriptor */
__ALIGN_BEGIN const usb_cdc_desc_config_set cdc_config_desc __ALIGN_END = 
{.config = {.header = {.bLength         = sizeof(usb_desc_config), .bDescriptorType = USB_DESCTYPE_CONFIG,},.wTotalLength         = USB_CDC_ACM_CONFIG_DESC_SIZE,.bNumInterfaces       = 0x02U,.bConfigurationValue  = 0x01U,.iConfiguration       = 0x00U,.bmAttributes         = 0x80U,.bMaxPower            = 0x32U},.cmd_itf = {.header = {.bLength         = sizeof(usb_desc_itf), .bDescriptorType = USB_DESCTYPE_ITF },.bInterfaceNumber     = 0x00U,.bAlternateSetting    = 0x00U,.bNumEndpoints        = 0x01U,.bInterfaceClass      = USB_CLASS_CDC,.bInterfaceSubClass   = USB_CDC_SUBCLASS_ACM,.bInterfaceProtocol   = USB_CDC_PROTOCOL_AT,.iInterface           = 0x00U},.cdc_header = {.header ={.bLength         = sizeof(usb_desc_header_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE},.bDescriptorSubtype  = 0x00U,.bcdCDC              = 0x0110U},.cdc_call_managment = {.header = {.bLength         = sizeof(usb_desc_call_managment_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE},.bDescriptorSubtype  = 0x01U,.bmCapabilities      = 0x00U,.bDataInterface      = 0x01U},.cdc_acm = {.header = {.bLength         = sizeof(usb_desc_acm_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE},.bDescriptorSubtype  = 0x02U,.bmCapabilities      = 0x02U,},.cdc_union = {.header = {.bLength         = sizeof(usb_desc_union_func), .bDescriptorType = USB_DESCTYPE_CS_INTERFACE},.bDescriptorSubtype  = 0x06U,.bMasterInterface    = 0x00U,.bSlaveInterface0    = 0x01U,},.cdc_cmd_endpoint = {.header = {.bLength         = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP,},.bEndpointAddress    = CDC_CMD_EP,.bmAttributes        = USB_EP_ATTR_INT,.wMaxPacketSize      = USB_CDC_CMD_PACKET_SIZE,.bInterval           = 0x0AU},.cdc_data_interface = {.header = {.bLength         = sizeof(usb_desc_itf), .bDescriptorType = USB_DESCTYPE_ITF,},.bInterfaceNumber    = 0x01U,.bAlternateSetting   = 0x00U,.bNumEndpoints       = 0x02U,.bInterfaceClass     = USB_CLASS_DATA,.bInterfaceSubClass  = 0x00U,.bInterfaceProtocol  = USB_CDC_PROTOCOL_NONE,.iInterface          = 0x00U},.cdc_out_endpoint = {.header = {.bLength         = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP, },.bEndpointAddress     = CDC_DATA_OUT_EP,.bmAttributes         = USB_EP_ATTR_BULK,.wMaxPacketSize       = USB_CDC_DATA_PACKET_SIZE,.bInterval            = 0x00U},.cdc_in_endpoint = {.header = {.bLength         = sizeof(usb_desc_ep), .bDescriptorType = USB_DESCTYPE_EP },.bEndpointAddress     = CDC_DATA_IN_EP,.bmAttributes         = USB_EP_ATTR_BULK,.wMaxPacketSize       = USB_CDC_DATA_PACKET_SIZE,.bInterval            = 0x00U}
};

為了實現CDC設備類,設備需要支持一些設備類專用請求,這些類專用請求的處理在cdc_acm_req ()函數中,該函數的定義如下所示,其中SET_LINE_CODING命令用于響應主機向設備發送設備配置,包括波特率、停止位、字符位數等,收到的數據保存在noti_bu內。GET_LINE_CODING命令用于主機請求設備當前的波特率、停止位、奇偶校驗位和字符位數,但在本例程中,主機并未請求該命令,所以設備所設置的串口數據并沒有作用,主機可以選擇任意波特率與設備進行通信。

static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];usb_transc *transc = NULL;switch (req->bRequest) {case SEND_ENCAPSULATED_COMMAND:/* no operation for this driver */break;case GET_ENCAPSULATED_RESPONSE:/* no operation for this driver */break;case SET_COMM_FEATURE:/* no operation for this driver */break;case GET_COMM_FEATURE:/* no operation for this driver */break;case CLEAR_COMM_FEATURE:/* no operation for this driver */break;case SET_LINE_CODING:transc = &udev->dev.transc_out[0];/* set the value of the current command to be processed */udev->dev.class_core->alter_set = req->bRequest;/* enable EP0 prepare to receive command data packet */transc->remain_len = req->wLength;transc->xfer_buf = cdc->cmd;break;case GET_LINE_CODING:transc = &udev->dev.transc_in[0];cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate);cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8);cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16);cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24);cdc->cmd[4] = cdc->line_coding.bCharFormat;cdc->cmd[5] = cdc->line_coding.bParityType;cdc->cmd[6] = cdc->line_coding.bDataBits;transc->xfer_buf = cdc->cmd;transc->remain_len = 7U;break;case SET_CONTROL_LINE_STATE:/* no operation for this driver */break;case SEND_BREAK:/* no operation for this driver */break;default:break;}return USBD_OK;
}

數據接收
通過cdc_acm_data_receive()函數實現,該函數的程序如下所示。在該函數中,首先將packet_receive標志位設置為0,表明接下來將進行接收數據,當接收完成時,在cdc_acm_out ()函數中,將packet_receive標志位置1,表明數據接收完成。usbd_ep_recev()用于配置接收操作,利用CDC_OUT_EP端點,將接收到的數據放置在用戶緩沖區中。

/*!\brief      receive CDC ACM data\param[in]  udev: pointer to USB device instance\param[out] none\retval     USB device operation status
*/
void cdc_acm_data_receive (usb_dev *udev)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];cdc->packet_receive = 0U;cdc->packet_sent = 0U;usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE);
}
/*!\brief      handle CDC ACM data\param[in]  udev: pointer to USB device instance\param[in]  ep_num: endpoint identifier\param[out] none\retval     USB device operation status
*/
static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];cdc->packet_receive = 1U;cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count;return USBD_OK;
}

數據發送
通過cdc_acm_data_send()函數實現,該函數的程序如下所示。在該函數中,首先將packet_sent標志位設置為0,表明接下來將進行發送數據,當數據發送完成時,在cdc_acm_in ()函數中,將packet_sent標志位設置為1,表明數據發送完成。usbd_ep_send ()用于配置發送操作,利用CDC_IN_EP端點,將以 cdc->data地址為起始,cdc->receive_length長度的數據發送給主機。

/*!\brief      send CDC ACM data\param[in]  udev: pointer to USB device instance\param[out] none\retval     USB device operation status
*/
void cdc_acm_data_send (usb_dev *udev)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];if (0U != cdc->receive_length) {cdc->packet_sent = 0U;usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length);cdc->receive_length = 0U;}
}
/*!\brief      handle CDC ACM data\param[in]  udev: pointer to USB device instance\param[in]  ep_num: endpoint identifier\param[out] none\retval     USB device operation status
*/
static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num)
{usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)];usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) {usbd_ep_send (udev, ep_num, NULL, 0U);} else {cdc->packet_sent = 1U;}return USBD_OK;
}

六.配置一個USB虛擬串口收發例程

STLINK接GD32F407VET6開發板,STLINK接電腦USB口,5V USB線接板子與電腦。

在這里插入圖片描述

主要代碼

#include "gd32f4xx.h"
#include "gd32f4xx_libopt.h"
#include "systick.h"
#include "usbd_conf.h"
#include "drv_usb_hw.h"
#include "cdc_acm_core.h"
usb_core_driver cdc_acm;
int main(void)
{usb_gpio_config();usb_rcu_config();usb_timer_init();usbd_init (&cdc_acm,
#ifdef USE_USB_FSUSB_CORE_ENUM_FS,
#elif defined(USE_USB_HS)USB_CORE_ENUM_HS,
#endif /* USE_USB_FS */&cdc_desc,&cdc_class);usb_intr_config();#ifdef USE_IRC48M/* CTC peripheral clock enable */rcu_periph_clock_enable(RCU_CTC);/* CTC configure */ctc_config();while (ctc_flag_get(CTC_FLAG_CKOK) == RESET) {}
#endif /* USE_IRC48M *//* main loop */while (1) {if (USBD_CONFIGURED == cdc_acm.dev.cur_status) {if (0U == cdc_acm_check_ready(&cdc_acm)) {cdc_acm_data_receive(&cdc_acm);//接收數據} else {cdc_acm_data_send(&cdc_acm);//發送數據}}}
}/*!\brief      receive CDC ACM data\param[in]  udev: pointer to USB device instance\param[out] none\retval     USB device operation status
*/
void cdc_acm_data_receive (usb_dev *udev)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];cdc->packet_receive = 0U;cdc->packet_sent = 0U;usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE);
}/*!\brief      send CDC ACM data\param[in]  udev: pointer to USB device instance\param[out] none\retval     USB device operation status
*/
void cdc_acm_data_send (usb_dev *udev)
{usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];if (0U != cdc->receive_length) {cdc->packet_sent = 0U;usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length);cdc->receive_length = 0U;}
}

實驗效果
下載完程序,用 USB 線接板子USB 口,再接電腦,打開電腦上串口調試器,9600 波特率,8 位數據,無校驗,發送 HELLOWORLD,板子就會返回 HELLOWORLD。
在這里插入圖片描述

七.工程源代碼下載

源代碼下載鏈接如下:
CSDN

八.小結

USB虛擬串口可以實現與電腦的通信,還可以實現與外部設備的通信,廣泛應用于工業控制、智能家居、智能硬件等領域。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79978.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79978.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79978.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL 主從配置超詳細教程

文章目錄 前言一、安裝 MySQL二、主服務器(Master)配置三、從服務器(Slave)配置四、測試主從復制五、注意事項 前言 MySQL 主從配置是一種實用的數據庫架構,主服務器處理寫入操作,從服務器負責只讀操作&am…

Python爬蟲實戰:獲取百度學術專題文獻數據并分析,為讀者課題研究做參考

一、引言 在信息爆炸的當下,學術研究需要大量相關資料支撐。百度學術作為重要學術資源平臺,蘊含豐富學術文獻。利用爬蟲技術獲取百度學術特定主題文章數據,能為學術研究提供全面、及時信息。本研究旨在用 Python 實現對百度學術 “主題爬蟲” 相關文章的爬取,并對數據深入…

手撕基于AMQP協議的簡易消息隊列-6(服務端模塊的編寫)

在MQServer中編寫服務端模塊代碼 在MQServer中編寫makefile文件來編譯服務端模塊 .PHONY: server CFLAG -I../ThirdLib/lib/include LFLAG -L../ThirdLib/lib/lib -lgtest -lprotobuf -lsqlite3 -pthread -lmuduo_net -lmuduo_base -lz server:server.cpp ../MQCommon/messag…

linux tar命令詳解。壓縮格式對比

1.壓縮格式對比 壓縮格式命令選項文件擴展名壓縮率速度無壓縮-cvf.tar無最快gzip-czvf.tar.gz中等較快bzip2-cjvf.tar.bz2較高較慢xz-cJvf.tar.xz最高最慢 9. 更多參考 【Linux基礎】文件壓縮tar命令指南tar壓縮方式對比

解鎖跨平臺開發的新時代——Compose Multiplatform

解鎖跨平臺開發的新時代——Compose Multiplatform 在當今移動和桌面應用程序開發領域,跨平臺解決方案是開發者們夢寐以求的工具。而由JetBrains打造的Compose Multiplatform正是這樣一款現代UI框架,它基于Kotlin技術,為開發者構建高性能且美觀的用戶界面提供了極大的便利和…

【算法學習】遞歸、搜索與回溯算法(二)

算法學習: https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言: 在(一)中我們挑了幾個經典例題,已經對遞歸、搜索與回溯算法進行了初步講解,今天我們來進一步講解…

HTTP請求與緩存、頁面渲染全流程

文章目錄 前言**1. HTTP請求與緩存處理****緩存機制**? 強緩存(Cache-Control / Expires)? 協商緩存(Last-Modified / ETag) **2. 服務器響應與數據解析****3. HTML DOM 構建****4. CSSOM 構建****5. 渲染樹(Render …

限流算法學習筆記(一)Go Rate Limiter

文章目錄 1. 背景與概述1.1 什么是速率限制1.2 Go Rate Limiter 的定義與價值 2. 核心思想與設計理念2.1 令牌桶算法的基本原理2.2 惰性評估設計2.3 多種處理策略的平衡2.4 簡單易用的偶發控制 3. 架構設計與組件3.1 整體架構3.2 Limiter 組件3.3 Reservation 組件3.4 Limit 類…

n8n工作流自動化平臺的實操:生成統計圖的兩種方式

1.成果展示 1.1n8n的工作流 牽涉節點:Postgres、Code、QuickChart、Edit Fields、HTTP Request 12.顯示效果 2.實操過程 2.1節點說明 2.1.1Postgres節點: 注:將明細數據進行匯總。 2.1.2code節點: 注:將 查詢的數…

JavaScript中數組和對象不同遍歷方法的順序規則

在JavaScript中,不同遍歷方法的順序規則和適用場景存在顯著差異。以下是主要方法的遍歷順序總結: 一、數組遍歷方法 for循環 ? 嚴格按數組索引順序遍歷(0 → length-1) ? 支持break和continue中斷循環 ? 性能最優,…

緩存(1):三級緩存

三級緩存是指什么 我們常說的三級緩存如下: CPU三級緩存Spring三級緩存應用架構(JVM、分布式緩存、db)三級緩存 CPU 基本概念 CPU 的訪問速度每 18 個月就會翻 倍,相當于每年增? 60% 左右,內存的速度當然也會不斷…

Android setContentView()源碼分析

文章目錄 Android setContentView()源碼分析前提setContentView() 源碼分析總結 Android setContentView()源碼分析 前提 Activity 的生命周期與 ActivityThread 相關,調用 startActivity() 時,會調用 ActivityThread#performLaunchActivity()&#xf…

uniapp自定義步驟條(可二開進行調試)

前言 有一個業務需求是需要一個步驟條&#xff0c;但是發現開源的都不太合適&#xff0c;所以就自己寫了一個。 開始 test.vue <template><view class"authenticateRecordDetails_container"><!-- 進度 --><view class"authenticateSte…

22、近端策略優化算法(PPO)論文筆記

近端策略優化算法&#xff08;PPO&#xff09;論文筆記 一、研究背景與目標二、**方法****3.1 策略梯度基礎****3.2 信任區域方法&#xff08;TRPO&#xff09;****3.3 剪切代理目標函數&#xff08;LCLIP&#xff09;****3.4 自適應KL懲罰系數****3.5 算法實現** 三、 L CLIP…

web 自動化之 Selenium 元素定位和瀏覽器操作

文章目錄 一、元素定位的八大方法1、基于 id/name/class/tag_name 定位2、基于 a 標簽元素的鏈接文本定位3、基于xpath定位4、css定位 二、瀏覽器操作1、信息獲取2、 瀏覽器關閉3、 瀏覽器控制 一、元素定位的八大方法 web 自動化測試就是通過代碼對網頁進行測試&#xff0c;在…

前端面經 作用域和作用域鏈

含義&#xff1a;JS中變量生效的區域 分類&#xff1a;全局作用域 或者 局部作用域 局部作用域&#xff1a;函數作用域 和 塊級作用域ES6 全局作用域:在代碼中任何地方都生效 函數中定義函數中生效&#xff0c;函數結束失效 塊級作用域 使用let或const 聲明 作用域鏈:JS查…

【C/C++】RPC與線程間通信:高效設計的關鍵選擇

文章目錄 RPC與線程間通信&#xff1a;高效設計的關鍵選擇1 RPC 的核心用途2 線程間通信的常規方法3 RPC 用于線程間通信的潛在意義4 主要缺點與限制4.1 缺點列表4.2 展開 5 替代方案6 結論 RPC與線程間通信&#xff1a;高效設計的關鍵選擇 在C或分布式系統設計中&#xff0c;…

兩種方法求解最長公共子序列問題并輸出所有解

最長公共子序列&#xff08;Longest Common Subsequence, LCS&#xff09;是動態規劃領域的經典問題&#xff0c;廣泛應用于生物信息學&#xff08;如DNA序列比對&#xff09;、文本差異比對&#xff08;如Git版本控制&#xff09;等領域。本文將通過??自頂向下遞歸記憶化??…

SpringBoot應急知識學習系統開發實現

概述 一個基于SpringBoot開發的應急知識學習系統&#xff0c;該系統提供了完整的用戶注冊、登錄、知識學習與測評功能。對于開發者而言&#xff0c;這是一個值得參考的免費Java源碼項目&#xff0c;可以幫助您快速構建類似的教育平臺。 主要內容 5.2 注冊模塊的實現 系統采…

【Python 字符串】

Python 中的字符串&#xff08;str&#xff09;是用于處理文本數據的基礎類型&#xff0c;具有不可變性、豐富的內置方法和靈活的操作方式。以下是 Python 字符串的核心知識點&#xff1a; 一、基礎特性 定義方式&#xff1a; s1 單引號字符串 s2 "雙引號字符串" s…