STM32移植U8G2

STM32 移植 U8G2

u8g2 (Universal 8bit Graphics Library version2 的縮寫)是用于嵌入式設備的單色圖形庫,可以在單色屏幕中繪制 GUI。u8g2 內部附帶了例如 SSD13xx,ST7xx 等很多 OLED,LCD 驅動。內置多種不同大小和風格的字體,可以顯示中文,其次就是圖形程序實現線,框,圓等圖形繪制。

1. 建立裸機工程

在移植 u8g2 之前先創建 STM32F103 的 Keil5 工程模板(如何搭建 Keil 模板這里不多介紹),用來編譯 STM32 驅動源碼和 u8g2 源碼。這也是支持 u8g2 開發的一個單片機運行環境,并且調試好屏幕驅動,確保屏幕初始化成功。

屏幕驅動只是為了驗證屏幕可行性,移植后方便排除因屏幕不顯示的問題,u8g2 附帶屏幕驅動程序,受支持的屏幕可以使用里面的驅動程序 。整體移植操作和芯片無關,所以無論什么芯片移植方法都相同。

2. 下載源碼

在 Github 官網搜索 u8g2 進行下載,或通過 https://github.com/olikraus/u8g2 鏈接下載,u8g2 沒有發行版,所以直接下載 master 分支源碼,下載后可以得到一個 u8g2-master.zip 這樣的源碼壓縮包,如下圖。

請添加圖片描述

3. u8g2 文件概覽

u8g2 源碼主要需要使用 cppsrc/csrc/ 這兩個文件夾。分別為 u8g2 對 C++ 兼容支持庫,u8g2 源碼文件夾

請添加圖片描述

cppsrc 對 C++ 兼容支持,方便把 u8g2 移植到 C++ 應用。cppsrc 用 C++ 類簡單封裝了 u8g2 普通操作函數(實際還是依賴 csrc),如下所示,把 u8g2 移植到 C++ 應用才需要這部分代碼。

/*u8g2_line.c */
void U8G2::drawLine(u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2) 
{u8g2_DrawLine(&u8g2, x1, y1, x2, y2);
}

其他就是一些說明文檔,輔助工具程序,版本變更信息,LICENSE 等等,這部分保留 LICENSE(開源許可) 其余可以刪除精簡工程。

4. 移植 u8g2

在 Keil 項目管理器新建一個 u8g2 文件夾,添加 u8g2 目錄 u8g2/csrc/ 下所有的.c 文件。即使 u8g2 移植到 C++ 應用,這部分也是需要的(u8g2 C++ 部分實際還是依賴 csrc 的源碼)。

請添加圖片描述

添加 u8g2 的頭文件目錄 u8g2/csrc/,即 u8g2 源碼和頭文件在同一個目錄。

5. 驅動函數選擇

csrc 目錄下屏幕驅動文件以 u8x8_d_xx_yy_zz.c 格式命名,其中 xx 芯片型號,yy 屏幕分辨率,zz 識別名稱,zz 不是一定的,可以為空或 noname。

例如:SSD1312 芯片驅動,128x64 分辨率的 OLED,使用的驅動文件為 u8x8_d_ssd1312_128x64_noname.c

驅動配置函數通常和文件同名,在驅動文件中找到同名函數即可,比如這里就是:

uint8_t u8x8_d_ssd1312_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)

注意:驅動文件和驅動函數也可能不對應,例如 ssd1312 的驅動函數可能定義在 ssd1306 的驅動文件,這是 u8g2 為了把相近屏幕的驅動函數統一到一個文件。

如果要減小代碼量,其它型號屏幕驅動和分辨率對應的 .c 驅動文件可以刪除。

6. u8g2_d_setup.c

csrc 目錄下找到這個文件,文件包含各種屏幕的配置函數,實上選擇的屏幕驅動函數就會被這些配置函數調用。

屏幕配置函數以 u8g2_Setup_xx_yy_zz_gg_[1/2/f].c 命名,具體字段解釋如下:

xx 芯片型號,ssd1306,sh1106 等等。

yy 通信方式,識不是一定的,i2c 表示為 i2c 接口,如果沒有則表示 spi 通信。

zz 屏幕分辨率,128x64,128x80 等等。

gg 識別名稱,gg 不是一定的,可以為 noname 也可以為空。

[1/2/f] 顯存 BUF 大小,1:128字節,2:256 字節,f:1024 字節。

例如:SSD1312 芯片驅動,128x64 分辨率 SPI 通信的 OLED,希望使用 1024 字節顯存,使用的配置函數為 u8g2_Setup_ssd1312_128x64_noname_f

/*ssd1312 f*/
void u8g2_Setup_ssd1312_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{uint8_t tile_buf_height;uint8_t *buf;u8g2_SetupDisplay(u8g2, u8x8_d_ssd1312_128x64_noname, u8x8_cad_001, byte_cb, gpio_and_delay_cb);buf = u8g2_m_16_8_f(&tile_buf_height);u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}

可以看到上方函數調用了 u8x8_d_ssd1312_128x64_noname(),如果要減小代碼量,其它的配置函數可以刪除或注釋,只留下選擇的即可。

7. u8g2_d_memory.c

csrc 目錄下找到 u8g2_d_memory.c,文件里面是 u8g2 對顯存的定義。在屏幕配置函數中,只調用了 u8g2_m_16_8_f(),所以如果編譯 u8g2 時如果提示內存不足,除此之外其它顯存函數可以刪除或注釋。

uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{#ifdef U8G2_USE_DYNAMIC_ALLOC*page_cnt = 8;return 0;#elsestatic uint8_t buf[1024];*page_cnt = 8;return buf;#endif
}

8. 對接屏幕驅動

把屏幕相關的硬件控制對接給 u8g2,需要我們實現 GPIO 控制和數據發送這 2 個統一驅動函數,函數原型如下,函數名稱可以自定義:

uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);

最終通過注冊的的方式提供給 u8g2。

8.1 對接 GPIO

把屏幕的 GPIO 控制函數按照用途對接到指定位置,比如 SPI 屏幕要對接 CSDCRESET 對應的 GPIO。

uint8_t u8x8_stm32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{/**STM32 supports HW SPI, Remove unused cases like U8X8_MSG_DELAY_XXX & U8X8_MSG_GPIO_XXX */switch (msg) {case U8X8_MSG_GPIO_AND_DELAY_INIT:/*Insert codes for initialization*/break;case U8X8_MSG_DELAY_MILLI:/* ms Delay */sleep_ms(arg_int);break;#ifdef _USE_SPI/*SPI Interface*/case U8X8_MSG_GPIO_CS:/*Insert codes for SS pin control */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, arg_int);break;case U8X8_MSG_GPIO_DC:/*Insert codes for DC pin control */HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, arg_int);break;case U8X8_MSG_GPIO_RESET:/*Insert codes for RST pin control*/HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, arg_int);break;case U8X8_MSG_GPIO_SPI_CLOCK:/*Insert codes for CLOCK pin control */break;case U8X8_MSG_GPIO_SPI_DATA:/*Insert codes for DATA pin control */break;#endif /*_USE_SPI*/#ifdef _USE_I2Ccase U8X8_MSG_GPIO_I2C_CLOCK:/*Insert codes for CLOCK pin control */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, arg_int);break;case U8X8_MSG_GPIO_I2C_DATA:/*Insert codes for CLOCK pin control */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, arg_int);break;
#endif /*_USE_I2C*/}return 1;
}

如果使用 GPIO 模擬時序通信還要對接模擬通信 GPIO,比如軟件模擬 I2C 還要對接 SCLSDA 對應 GPIO,同時還要對接延時函數,u8g2 才能模擬時序。

8.2 對接數據

把屏幕的數據發送函數對接到指定位置,如果屏幕使用 SPI 接口,U8X8_MSG_BYTE_SEND 對應的是 SPI 數據發送函數,可以參考如下寫法:

uint8_t u8x8_byte_stm32_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{HAL_StatusTypeDef _res = HAL_ERROR;switch (msg) {case U8X8_MSG_BYTE_SEND:/*Insert codes to transmit data*/_res = HAL_SPI_Transmit(&hspi3, arg_ptr, arg_int, TX_TIMEOUT);if (_res != HAL_OK) return 0;break;case U8X8_MSG_BYTE_INIT:/*Insert codes to begin SPI transmission*/break;case U8X8_MSG_BYTE_SET_DC:/*Control DC pin, U8X8_MSG_GPIO_DC will be called*/u8x8_gpio_SetDC(u8x8, arg_int);break;case U8X8_MSG_BYTE_START_TRANSFER:/* Select slave, U8X8_MSG_GPIO_CS will be called */u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);sleep_ms(2);break;case U8X8_MSG_BYTE_END_TRANSFER:sleep_ms(2);/* Insert codes to end SPI transmission */u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);break;}return 1;
}

如果屏幕使用 I2C 接口,U8X8_MSG_BYTE_SEND 對應的是 I2C 數據發送函數,可以參考如下寫法:

uint8_t u8x8_byte_stm32_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{/**u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */static uint8_t buffer[32] = {0};static uint8_t buf_idx = 0;uint8_t * data = NULL;switch (msg) {case U8X8_MSG_BYTE_SEND:data = (uint8_t *) arg_ptr;while (arg_int > 0) {buffer[buf_idx++] = *data;data++;arg_int--;}break;case U8X8_MSG_BYTE_INIT:/*add your custom code to init i2c subsystem*/break;case U8X8_MSG_BYTE_SET_DC:break;case U8X8_MSG_BYTE_START_TRANSFER:buf_idx = 0;break;case U8X8_MSG_BYTE_END_TRANSFER:HAL_I2C_Master_Transmit(_I2C_DEV, (DEV_ADDR << 1), buffer, buf_idx, TX_TIMEOUT);break;}return 1;
}

8.3 初始化外設

如果數據發送是通過單片機外設硬件實現實現的,初始化 u8g2 前先初始化外設和對應的 GPIO,例如這里初始化 SPI 接口,還有相應 GPIO。

void oled_spi3_init(void)
{/* USER CODE BEGIN SPI3_Init 0 *//* USER CODE END SPI3_Init 0 *//* USER CODE BEGIN SPI3_Init 1 *//* USER CODE END SPI3_Init 1 */hspi3.Instance = SPI3;hspi3.Init.Mode = SPI_MODE_MASTER;hspi3.Init.Direction = SPI_DIRECTION_2LINES;hspi3.Init.DataSize = SPI_DATASIZE_8BIT;hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;hspi3.Init.NSS = SPI_NSS_SOFT;hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi3.Init.TIMode = SPI_TIMODE_DISABLE;hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi3.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi3) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI3_Init 2 *//* USER CODE END SPI3_Init 2 */
}

8.4 初始化 u8g2

u8g2 沒有對象初始化函數,自定義 u8g2 對象初始化函數,函數名稱可以自定義,在初始化函數調用顯示初始化及對應的屏幕配置函數,如下。

void u8g2_init(u8g2_t *u8g2)
{u8g2_Setup_ssd1312_128x64_noname_f(u8g2, U8G2_R2, u8x8_byte_stm32_hw_spi, u8x8_stm32_gpio_and_delay);u8g2_SetPowerSave(u8g2, 1);u8g2_InitDisplay(u8g2);u8g2_ClearDisplay(u8g2);u8g2_ClearBuffer(u8g2);u8g2_SetPowerSave(u8g2, 0);
}

可以看到這個就是前面講解屏幕的配置函數,如下。

void u8g2_Setup_ssd1312_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);

該函數的 4 個參數含義:

(1) u8g2,指定待初始化的 u8g2 對象,即 u8g2 結構體。
(2) rotation,配置屏幕旋轉方向,支持 U8G2_R0,U8G2_R1,U8G2_R2,U8G2_R3 四種旋轉方向。
(3) byte_cb,注冊數據通信發送函數。
(4) gpio_and_delay_cb:注冊屏幕 GPIO 控制函數。

8.5 總結

把對接屏幕驅動用到的這些自定義函數統一編寫到一個文件中,文件可自行命名,例如命名為 u8g2_stm32.c,并添加到 u8g2 之外的用戶目錄。

9. 測試函數

移植完成后編寫應用程序測試 u8g2 是否正常,調用 u8g2 繪圖函數在顯存繪制內容,在 main 函數調用初始化 SPI 和 u8g2,注意在主循環中調用 u8g2 顯存發送函數 u8g2_SendBuffer 將顯存內容更新至屏幕,在此附上 u8g2 測試程序。

#include "u8g2.h"static u8g2_t u8g2 = {0};void draw(u8g2_t * u8g2_p)
{u8g2_SetFontMode(u8g2_p, 1);u8g2_SetFontDirection(u8g2_p, 0);u8g2_SetFont(u8g2_p, u8g2_font_inb24_mf);u8g2_DrawStr(u8g2_p, 0, 20, "U");u8g2_SetFontDirection(u8g2_p, 1);u8g2_SetFont(u8g2_p, u8g2_font_inb30_mn);u8g2_DrawStr(u8g2_p, 21, 8, "8");u8g2_SetFontDirection(u8g2_p, 0);u8g2_SetFont(u8g2_p, u8g2_font_inb24_mf);u8g2_DrawStr(u8g2_p, 51, 30, "g");u8g2_DrawStr(u8g2_p, 67, 30,"\xb2");u8g2_DrawHLine(u8g2_p, 2, 35, 47);u8g2_DrawHLine(u8g2_p, 3, 36, 47);u8g2_DrawVLine(u8g2_p, 45, 32, 12);u8g2_DrawVLine(u8g2_p, 46, 33, 12);u8g2_SetFont(u8g2_p, u8g2_font_4x6_tr);u8g2_DrawStr(u8g2_p, 1, 54, "github.com/olikraus/u8g2");
}void main()
{oled_spi_init();u8g2_init(&u8g2);for (;;) {u8g2_ClearBuffer(&u8g2);draw(&u8g2);u8g2_SendBuffer(&u8g2);}
}

10. 移植 C++ 版本

移植 C++ 版本基礎步驟和前面小節介紹的步驟相同,除此之外現在繼續在 Keil 項目管理器再新建一個 u8g2cpp 文件夾,然后添加 u8g2 目錄 u8g2/cppsrc/ 下所有的 .cpp 文件。

請添加圖片描述

10.1 u8g2 繼承類

自定義 u8g2 對象初始化類,繼承 U8G2 不是必須的。可以把類定義在 U8g2lib.h 文件中,或其他文件,類名稱可以自定義。在類的構造函數調用對應的屏幕配置函數,例如調用 ssd1312 屏幕配置。

void u8g2_Setup_ssd1312_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);

再自定義初始化函數 SSD1312::Init(),調用 u8g2 顯示初始化來初始化 u8g2。

extern "C" uint8_t u8x8_stm32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
extern "C" uint8_t u8x8_byte_stm32_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);class SSD1312 : public U8G2 {
private:public: SSD1312(const u8g2_cb_t *rotation = U8G2_R2) : U8G2() {u8g2_Setup_ssd1312_128x64_noname_f(&u8g2, rotation, u8x8_byte_stm32_hw_spi, u8x8_stm32_gpio_and_delay);}bool Init() {/**note: call to u8x8_utf8_init is not required here, this is done in the setup procedures before*/setPowerSave(1); initDisplay(); clearDisplay(); clearBuffer(); setPowerSave(0);return 1;}
};

10.2 測試程序

調用 SSD1312 類對象方法,編寫應用程序測試 u8g2 是否正常,調用 u8g2 繪圖函數在顯存繪制內容,初始化 u8g2 對象,在主循環中調用 sendBuffer 將顯存內容更新至屏幕。

#include "U8g2lib.h"SSD1312 oled;void draw(SSD1312 * oled_p)
{oled_p->setFontMode(1);oled_p->setFontDirection(0);oled_p->setFont(u8g2_font_inb24_mf);oled_p->drawStr(0, 20, "U");oled_p->setFontDirection(1);oled_p->setFont(u8g2_font_inb30_mn);oled_p->drawStr(21, 8, "8");oled_p->setFontDirection(0);oled_p->setFont(u8g2_font_inb24_mf);oled_p->drawStr(51, 30, "g");oled_p->drawStr(67, 30,"\xb2");oled_p->drawHLine(2, 35, 47);oled_p->drawHLine(3, 36, 47);oled_p->drawVLine(45, 32, 12);oled_p->drawVLine(46, 33, 12);oled_p->setFont(u8g2_font_4x6_tr);oled_p->drawStr(1, 54, "github.com/olikraus/u8g2");
}void main()
{oled.Init();for (;;) {oled.clearBuffer();draw(&oled);oled.sendBuffer();}
}

詳細查看:

https://blog.csdn.net/qq_51183186/article/details/120348070

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

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

相關文章

Langchain,為何要名為langchian?

來聽聽 DeepSeek 怎么說 Human 2025-05-02T01:13:43.627Z langchain 是一個大語言模型開發框架。我的理解中&#xff0c;lang 是詞根"語言"&#xff0c;chain是單詞"鏈"&#xff0c;langchain 便是將語言模型和組件串聯成鏈的框架。而 langchain 的圖標是…

Windows下Python3腳本傳到Linux下./example.py執行失敗

1. 背景 大多數情況下通過pycharm編寫Python代碼&#xff0c;編寫調試完&#xff0c;到Linux下發布執行。 以example.py腳本為例 #! /usr/bin/env python3 #! -*- encoding: utf-8 -*- def test(x,y): xint x yint y cxy return c if _name_"__main__": print(test(2…

當MCP撞進云宇宙:多芯片封裝如何重構云計算的“芯“未來?

當MCP撞進云宇宙:多芯片封裝如何重構云計算的"芯"未來? 2024年3月,AMD發布了震撼業界的MI300A/B芯片——這顆為AI計算而生的"超級芯片",首次在單封裝內集成了13個計算芯片(包括3D V-Cache緩存、CDNA3 GPU和Zen4 CPU),用多芯片封裝(Multi-Chip Pac…

用定時器做微妙延時注意事項

注意定時器來著APB1還是APB2&#xff0c;二者頻率不一樣&#xff0c;配置PSC要注意 &#xff08;1&#xff09;高級定時器timer1&#xff0c; timer8以及通用定時器timer9&#xff0c; timer10&#xff0c; timer11的時鐘來源是APB2總線 &#xff08;2&#xff09;通用定時器ti…

三類思維坐標空間與時空序位信息處理架構

三類思維坐標空間與時空序位信息處理架構 一、靜態信息元子與元組的數據結構設計 三維思維坐標空間定義 形象思維軸&#xff08;x&#xff09;&#xff1a;存儲多媒體數據元子&#xff08;圖像/音頻/視頻片段&#xff09; 元子結構&#xff1a;{ID, 數據塊, 特征向量, 語義…

spring boot中@Validated

在 Spring Boot 中&#xff0c;Validated 是用于觸發參數校驗的注解&#xff0c;通常與 ??JSR-303/JSR-380??&#xff08;Bean Validation&#xff09;提供的校驗注解一起使用。以下是常見的校驗注解及其用法&#xff1a; ?1. 基本校驗注解?? 這些注解可以直接用于字段…

Hadoop 單機模式(Standalone Mode)部署與 WordCount 測試

通過本次實驗&#xff0c;成功搭建了 Hadoop 單機環境并運行了基礎 MapReduce 程序&#xff0c;為后續分布式計算學習奠定了基礎。 掌握 Hadoop 單機模式的安裝與配置方法。 熟悉 Hadoop 環境變量的配置及 Java 依賴管理。 使用 Hadoop 自帶的 WordCount 示例程序進行簡單的 …

歷史數據分析——運輸服務

運輸服務板塊簡介: 運輸服務板塊主要是為貨物與人員流動提供核心服務的企業的集合,涵蓋鐵路、公路、航空、海運、物流等細分領域。該板塊具有強周期屬性,與經濟復蘇、政策調控、供需關系密切關聯,尤其是海運領域。有不少國內股市的鐵路、公路等相關的上市公司同時屬于紅利…

openEuler 22.03 安裝 Mysql 5.7,TAR離線安裝

目錄 一、檢查系統是否安裝其他版本Mariadb數據庫二、環境檢查2.1 必要環境檢查2.2 在線安裝&#xff08;有網絡&#xff09;2.3 離線安裝&#xff08;無網絡&#xff09; 三、下載Mysql2.1 在線下載2.2 離線下載 四、安裝Mysql五、配置Mysql六、開放防火墻端口七、數據備份八、…

噴泉碼技術在現代物聯網中的應用 設計

噴泉碼技術在現代物聯網中的應用 摘 要 噴泉碼作為一種無速率編碼技術,憑借其動態生成編碼包的特性,在物聯網通信中展現出獨特的優勢。其核心思想在于接收端只需接收到足夠數量的任意編碼包即可恢復原始數據,這種特性使其特別適用于動態信道和多用戶場景。噴泉碼的實現主要…

GZIPInputStream 類詳解

GZIPInputStream 類詳解 GZIPInputStream 是 Java 中用于解壓縮 GZIP 格式數據的流類,屬于 java.util.zip 包。它是 InflaterInputStream 的子類,專門處理 GZIP 壓縮格式(.gz 文件)。 1. 核心功能 解壓 GZIP 格式數據(RFC 1952 標準)自動處理 GZIP 頭尾信息(校驗和、時…

網絡編程——TCP和UDP詳細講解

文章目錄 TCP/UDP全面詳解什么是TCP和UDP&#xff1f;TCP如何保證可靠性&#xff1f;1. 序列號&#xff08;Sequence Number&#xff09;2. 確認應答&#xff08;ACK&#xff09;3. 超時重傳&#xff08;Timeout Retransmission&#xff09;4. 窗口控制&#xff08;Sliding Win…

性能測試工具篇

文章目錄 目錄1. JMeter介紹1.1 安裝JMeter1.2 打開JMeter1.3 JMeter基礎配置1.4 JMeter基本使用流程1.5 JMeter元件作用域和執行順序 2. 重點組件2.1 線程組2.2 HTTP取樣器2.3 查看結果樹2.4 HTTP請求默認值2.5 JSON提取器2.6 用戶定義的變量2.7 JSON斷言2.8 同步定時器&#…

rabbitMQ如何確保消息不會丟失

rabbitmq消息丟失的三種情況 生產者將消息發送到RabbitMQ的過程中時&#xff0c;消息丟失。消息發送到RabbitMQ&#xff0c;還未被持久化就丟失了數據。消費者接收到消息&#xff0c;還未處理&#xff0c;比如服務宕機導致消息丟失。 解決方案 生產者發送過程中&#xff0c;…

Beetle-RP2350 擴展板設計

Beetle-RP2350 擴展板設計 本文介紹了 DFRobot Beetle RP2350 開發板的擴展板設計&#xff0c;包括參數特點、效果展示、原理圖、實物驗證、工程測試等&#xff0c;為 RP2350 系列產品的開發提供了便捷。 PCB 工程詳見&#xff1a;Beetle-RP2350擴展板 - 立創開源硬件平臺 . …

2025年一加7pro刷twpr / magisk / kali nethunter教程+資源下載+避坑指南

從二手市場500淘了一個一加7pro 12+256 ,根據網上教程刷機但很多坑,折騰一周后搞定,記錄下給后人避坑 資源下載:鏈接:https://pan.quark.cn/s/c16b972509f2 提取碼:mUW7 本文是主流程+避坑指南,沒有基礎的需要手把手教學的shell都不會的就別看了,直接放棄或者tb找人花錢…

java HashMap,高效 哈希

java HashMap 有獨特的設計。 哈希表數組的每個位置是一個哈希桶&#xff0c;里面由鏈表或紅黑樹實現。&#xff08;> 8 或 < 6 的變化時&#xff0c;避免頻繁切換&#xff09; 容量&#xff08;capacity&#xff09;&#xff1a; 哈希表中桶&#xff08;bucket&#xf…

【業務領域】計算機網絡基礎知識

《計算機網絡方面有哪些書籍值得推薦&#xff1f;》 知乎掃盲貼&#xff1a; 《網絡是怎么鏈接的》 初識RDMA技術——RDMA概念&#xff0c;特點&#xff0c;協議&#xff0c;通信流程 采樣 》 存儲 》傳輸 》處理 》反應 傳感器 存儲器 接口 算法/cpu 機器

List--鏈表

一、鏈表 1.1 什么是List&#xff1f; 在C語言中&#xff0c;我們需要使用結構體struct來進行List(鏈表&#xff09;的實現&#xff1a; struct ListNode {DataType Data;//DataType是任意類型的變量定義struct ListNode* next;//指向下一個結點的指針變量 }; 與之前的vect…

tensor 的計算操作

1、創建tensor 常見創建 tensor 的方法 函數 作用 torch.Tensor(*size) 通過指定尺寸&#xff0c;生成一個 值全為 0 的 tensor torch.tensor(*list) 直接通過指定數據&#xff0c;生成tensor&#xff0c;支持 List、Numpy數組 torch.eye(row, column) 按照指定的行列數…