STM32HAL庫 -- 8.串口UART通信并開啟printf功能

目錄

1.簡介

2.串口和UART?

2.1串口的簡介

2.2UART的簡介

2.3UART通信協議

2.3.1波特率

2.3.2空閑位

2.3.3起始位

2.3.4數據位

2.3.5校驗位

2.3.6停止位

3.STM32的UART

4.HAL庫中常用的操作UART的函數

4.1UART初始化函數 --?HAL_UART_Init

4.2硬件初始化回調函數 -- HAL_UART_MspInit

4.3發送數據函數 --?HAL_UART_Transmit?

4.4接收數據的函數 --?HAL_UART_Receive

4.5使能中斷源 --?__HAL_UART_ENABLE_IT

4.6獲取UART的狀態標志 --?__HAL_UART_GET_FLAG

4.7清除指定的 UART 狀態標志位 --?__HAL_UART_CLEAR_FLAG

5.發送接收數據實驗 并 打開串口printf功能

5.1硬件連接

5.2代碼編寫

5.2.1配置UART

5.2.2中斷函數

5.2.3重定義fputc -- 支持printf函數

6.整體代碼 && 實驗現象

6.1uart1.h

6.2uart1.c

6.3main.c

6.4實驗現象


1.簡介

? ? ? ? 這個文章會介紹串口通信,然后編寫代碼完成單片機通過串口發送到電腦,電腦發送數據到單片機的過程。

? ? ? ? 作者使用的開發板是正點原子的精英版,寫文章用于記錄學習和經驗分享。

2.串口和UART?

2.1串口的簡介

????????串口(Serial Port) 是一種常見的數據通信接口,用于實現設備之間的串行通信(Serial Communication)。所謂“串行”,是指數據是按 一位一位的順序進行發送或接收的,與并行通信(一次性傳輸多個比特)相對。

2.2UART的簡介

????????UART(Universal Asynchronous Receiver/Transmitter),UART 全稱是通用異步收發器,是一種硬件模塊,用于實現異步串行通信。它是實現串口通信的核心邏輯電路。

????????UART也是一種廣泛應用于嵌入式系統中的異步串行通信協議,通過定義數據幀格式和波特率實現設備之間的點對點數據傳輸。它僅需兩根信號線(TXD發送、RXD接收),無需共享時鐘,具有結構簡單、使用方便、兼容性強等優點,常用于調試輸出、傳感器通信、模塊交互等場景。

? ? ? ? 設備1的TX(發送端)接入設備2的RX(接收端),設備1的RX(接收端)接入設備2的(發送端),這樣就實現了全雙工通信。也可以單工通信,就是一發一收,接通一路TX、RX即可。

2.3UART通信協議

????????UART的一個完整的數據幀通常包括起始位、數據位、可選的校驗位和停止位,通信雙方必須保持波特率和數據格式一致才能正常工作。

2.3.1波特率

????????波特率(Baud Rate) 是串行通信中的一個關鍵參數,用于表示每秒傳輸的信號變化次數,單位是 bps(bits per second) 。在 UART 通信中,波特率決定了數據傳輸的速度。

????????在 UART 通信中,發送端和接收端必須設置相同的波特率,否則會導致數據接收不到或者接收內容與發送的內容不一致的問題。

2.3.2空閑位

????????空閑位(Idle State) 是指當串口未發送或接收任何數據時,數據線(通常是 TXD 或 RXD)處于高電平狀態。數據幀以一個起始位(Start Bit,低電平)開始,空閑位作為幀與幀之間的間隔,確保接收方能正確識別下一幀數據。

2.3.3起始位

????????起始位(Start Bit) 是 UART 數據幀中的第一個信號位,用于通知接收端:一幀數據即將開始傳輸。電平狀態固定為低電平(0);長度為 1 位。

2.3.4數據位

????????數據位(Data Bits) 是 UART 數據幀中承載實際信息的部分,表示一次通信中傳輸的有效數據內容。數據的長度通常為 5 到 8 位,8位用的最廣泛,因為正好是1字節的大小。

????????發送的順序是低位先發(LSB First)。例如字符 'A' 的 ASCII 碼為:0x41(十六進制)二進制表示為:01000001? ? ?UART 發送順序(LSB 先發):1 0 0 0 0 0 1 0

2.3.5校驗位

????????校驗位(Parity Bit)是 UART 數據幀中一個可選的錯誤檢測位,用于在通信過程中簡單判斷數據是否出錯。校驗位的位置在數據位之后、停止位之前。可以選擇無校驗(None)、偶校驗(Even)、奇校驗(Odd)。

校驗方式要求總“1”個數為...示例(數據位:01000001 → 有兩個“1”)
偶校驗(Even)偶數個“1”校驗位 =?0(使總數仍為偶數)
奇校驗(Odd)奇數個“1”校驗位 =?1(使總數變為奇數)

????????接收端收到后會重新計算并比對校驗位,若不一致則判定為傳輸錯誤。即使數據吃錯,也不會糾正錯誤,就僅僅簡單的校驗而已。

2.3.6停止位

????????停止位(Stop Bit) 是 UART 數據幀中的最后一個部分,用于標識一次數據傳輸的結束,同時為下一次通信提供時間間隔。電平狀態固定為高電平(1);長度可選為 1 位、1.5 位 或?2 位。

3.STM32的UART

? ? ? ? 作者使用的是STM32F103ZET6為微控制器的開發板,該微控制器內置了3個通用同步/異步收發器(USART1USART2USART3),和2個通用異步收發器(UART4UART5)。

????????UART 只支持異步串行通信,而USART 是 UART 的“升級版”,既支持異步也支持同步通信,功能更強大。在這里就把USART當作UART用就好。

? ? ? ? 附上框圖,雖然我沒咋看懂。

4.HAL庫中常用的操作UART的函數

? ? ? ? 打開HAL庫的stm32f1xx_hal_uart.c文件。

4.1UART初始化函數 --?HAL_UART_Init

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);

????????這個函數是 STM32 HAL 庫中用于 初始化 UART 外設 的核心函數。主要配置使用哪個UART、波特率、數據位、校驗位、停止位、CTS/RTS硬件流控位和收發模式。

? ? ? ? 函數的參數 UART_HandleTypeDef *huart 是指向一個 UART 句柄結構體的指針,該結構體包含了 UART 的配置信息和運行狀態。

? ? ? ? 函數的返回值(HAL_StatusTypeDef):

返回值含義
HAL_OK初始化成功
HAL_ERROR初始化失敗(如參數錯誤、硬件故障)
HAL_BUSYUART 正在被使用
HAL_TIMEOUT操作超時

4.2硬件初始化回調函數 -- HAL_UART_MspInit

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart);

? ? ? ? 這個函數是 HAL 庫中 UART 的底層硬件初始化函數,必須由用戶根據實際硬件平臺實現,用于配置 GPIO、時鐘、中斷等。這是一個公共的函數,通過HAL_UART_Init函數進行調用。同時也是虛函數,意思是要我們自己寫函數的內容。

????????函數的參數 UART_HandleTypeDef *huart 是指向一個 UART 句柄結構體的指針,該結構體包含了 UART 的配置信息和運行狀態。

4.3發送數據函數 --?HAL_UART_Transmit?

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

????????該函數用于 通過 UART 以阻塞方式發送一組數據(一個字節數組),直到全部發送完成或發生錯誤/超時。使用簡單,適合 不使用中斷或 DMA 的場景。

參數說明:

參數名類型說明
huartUART_HandleTypeDef*UART 句柄指針,指向已配置好的 UART 實例(如?&huart1
pDatauint8_t*指向要發送數據的緩沖區(字節數組)
Sizeuint16_t要發送的數據長度(字節數)
Timeoutuint32_t等待發送完成的最大時間(單位:ms),設為?HAL_MAX_DELAY?表示無限等待

4.4接收數據的函數 --?HAL_UART_Receive

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

????????該函數用于 通過 UART 以阻塞方式接收指定數量的字節數據。會一直等待直到:接收到指定數量的數據(Size 字節)或發生錯誤 / 超時。

參數說明:

huartUART_HandleTypeDef*UART 句柄指針(如?&huart1
pDatauint8_t*指向接收緩沖區的指針(用于存儲接收到的數據)
Sizeuint16_t要接收的數據長度(字節數)
Timeoutuint32_t接收等待最大時間(單位:ms),設為?HAL_MAX_DELAY?表示無限等待

4.5使能中斷源 --?__HAL_UART_ENABLE_IT

__HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__)

? ? ? ? 這是一個宏函數。該宏用于直接使能 UART 的某個中斷源。

參數說明:

__HANDLE__:就是 UART的句柄指針 UART_HandleTypeDef* 。

__INTERRUPT__:中斷源?

宏定義中斷名稱觸發條件是否常用
UART_IT_CTSCTS 變化中斷當 CTS 引腳電平變化時觸發(硬件流控相關)? 較少使用
UART_IT_LBDLIN 斷點檢測中斷檢測到 LIN 總線斷點標志(用于 LIN 協議)? 特定場景
UART_IT_TXE發送緩沖區空中斷當發送寄存器為空,可以寫入新數據時觸發? 常用
UART_IT_TC發送完成中斷整個數據幀傳輸完成后觸發? 常用
UART_IT_RXNE接收緩沖區非空中斷當收到一個字節數據時觸發? 最常用
UART_IT_IDLE空閑總線檢測中斷當 UART 接收線上檢測到空閑時觸發(常用于接收不定長數據幀)? 高級應用
UART_IT_PE校驗錯誤中斷接收到的數據發生奇偶校驗錯誤時觸發?? 錯誤檢測
UART_IT_ERR錯誤中斷(綜合)包括幀錯誤、噪聲錯誤、溢出錯誤等?? 錯誤處理

4.6獲取UART的狀態標志 --?__HAL_UART_GET_FLAG

__HAL_UART_GET_FLAG(__HANDLE__, __FLAG__)

????????用于讀取 UART 狀態標志位的宏,常用于輪詢或中斷中判斷事件是否發生,是實現串口通信控制和錯誤檢測的關鍵工具。

參數說明:

__HANDLE__:就是 UART的句柄指針 UART_HandleTypeDef* 。

__FLAG__:

宏定義對應標志描述
UART_FLAG_CTSCTS 標志位CTS 引腳狀態變化(硬件流控)
UART_FLAG_LBDLIN 斷點標志LIN 總線斷點檢測
UART_FLAG_TXE發送緩沖區空標志表示可以寫入新數據
UART_FLAG_TC發送完成標志整幀數據發送完成
UART_FLAG_RXNE接收緩沖區非空標志表示已接收到一個字節
UART_FLAG_IDLE空閑總線標志UART 總線空閑檢測(常用于不定長接收)
UART_FLAG_ORE溢出錯誤標志接收緩沖區溢出
UART_FLAG_NE噪聲錯誤標志接收到噪聲干擾
UART_FLAG_FE幀錯誤標志數據格式錯誤
UART_FLAG_PE校驗錯誤標志奇偶校驗失敗

4.7清除指定的 UART 狀態標志位 --?__HAL_UART_CLEAR_FLAG

__HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__)

????????該宏用于 清除指定的 UART 狀態標志位。在某些中斷或輪詢操作中,需要手動清除標志以避免重復觸發或狀態錯誤。

參數說明:

__HANDLE__:就是 UART的句柄指針 UART_HandleTypeDef* 。

__FLAG__:

宏定義對應標志是否需要手動清除說明
UART_FLAG_CTSCTS 標志? 是清除 CTS 中斷標志
UART_FLAG_LBDLIN 斷點標志? 是清除 LIN 檢測標志
UART_FLAG_TC發送完成標志? 是清除發送完成標志
UART_FLAG_IDLE空閑總線標志? 是常用于接收不定長數據幀后需清除
UART_FLAG_RXNE接收緩沖區非空標志? 否讀取 DR 寄存器自動清除
UART_FLAG_TXE發送緩沖區空標志? 否寫入 DR 自動清除
UART_FLAG_ORE溢出錯誤標志? 是清除溢出標志
UART_FLAG_NE噪聲錯誤標志? 是清除噪聲錯誤標志
UART_FLAG_FE幀錯誤標志? 是清除幀錯誤標志
UART_FLAG_PE校驗錯誤標志? 是清除奇偶校驗錯誤標志

5.發送接收數據實驗 并 打開串口printf功能

5.1硬件連接

? ? ? ? 一般地,STM32處理器的PA9和PA10就是對應的USART的TX和RX引腳。而且帶有type-c USB線直接連接到電腦上進行調試的功能。如果讀者使用的是最小系統板,就用USB轉TTL再進行連線到核心板就好,功能是一樣的。

5.2代碼編寫

5.2.1配置UART

????????使用上面介紹的HAL_UART_Init配置UART1。

UART_HandleTypeDef g_uart1_handle;						//UART1句柄
/*** @brief       串口1初始化函數* @param       baudrate: 波特率, 根據自己需要設置波特率值* @retval      無*/
void uart1_init(unsigned int baudrate)
{g_uart1_handle.Instance = USART1;						//配置的是USART1g_uart1_handle.Init.BaudRate = baudrate;				//波特率g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;	//數據位為8位g_uart1_handle.Init.StopBits = UART_STOPBITS_1;			//停止位為1位g_uart1_handle.Init.Parity = UART_PARITY_NONE;			//無校驗位g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;	//不使用CTS/RTS硬件流控位g_uart1_handle.Init.Mode = UART_MODE_TX_RX;				//UART發送和接收HAL_UART_Init(&g_uart1_handle);							//調用初始化函數進行初始化
}

????????再使用HAL_UART_MspInit進行底層硬件初始化,進行打開時鐘,配置GPIO和打開中斷。

? ? ? ? 對于發送數據引腳PA9,要求是推挽復用輸出模式,上拉模式,速度中速高速都行。

? ? ? ? 對于 接收數據引腳PA10,要求是復用輸入模式,上拉模式。

? ? ? ? 要使用HAL_NVIC_EnableIRQ函數打開USART1的中斷,并設置中斷優先級,然后再使用宏函數打開具體的UART中斷。這里打開的是空閑中斷和接收中斷。

*** @brief       UART底層初始化函數* @param       huart: UART句柄類型指針* @note        此函數會被HAL_UART_Init()調用*              完成時鐘使能,引腳配置,中斷配置* @retval      無*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){/*	1.打開時鐘	*/__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*	2.配置GPIO	*/GPIO_InitTypeDef gpio_handle = {0};gpio_handle.Pin = UART1_TX_PIN;gpio_handle.Mode = GPIO_MODE_AF_PP;gpio_handle.Pull = GPIO_PULLUP;gpio_handle.Speed = GPIO_SPEED_FREQ_MEDIUM;HAL_GPIO_Init(UART1_TX_PORT, &gpio_handle);gpio_handle.Pin = UART1_RX_PIN;gpio_handle.Mode = GPIO_MODE_AF_INPUT;gpio_handle.Pull = GPIO_PULLUP;HAL_GPIO_Init(UART1_RX_PORT, &gpio_handle);/*	3.打開中斷	*/HAL_NVIC_SetPriority(USART1_IRQn, 2, 2);HAL_NVIC_EnableIRQ(USART1_IRQn);__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);		//打開接收中斷__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);		//打開空閑中斷}
}

5.2.2中斷函數

? ? ? ? 打開了接收中斷之后,當接收到數據時,就跳到中斷函數進行接收數據。當接收完成后,即進入空閑中斷。在空閑中斷中可進行其他操作。

? ? ? ? 這里的邏輯比較簡單,當觸發了接收緩沖區非空中斷(接收到1字節數據),就進行接收數據的操作。數據一字節一字節的拷貝進g_uart1_rx_buf數組中,用于存儲接收的數據。接收中斷的標志會自動的清除。

? ? ? ? 當觸發空閑總線檢測中斷(數據接收完成),就進行打印操作,并且清空用于存儲接收數據的數組。然后要手動的清除空閑中斷標志,否則程序會一直在這里。

/*** @brief       串口1中斷服務函數* @note        在此使用接收中斷,實現不定長數據收發* @param       無* @retval      無*/
void USART1_IRQHandler(void)
{unsigned char recv_data;if(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_RXNE) != RESET){if(g_uart1_rx_len >= sizeof(g_uart1_rx_buf))g_uart1_rx_len = 0;HAL_UART_Receive(&g_uart1_handle, &recv_data, 1, 1000);g_uart1_rx_buf[g_uart1_rx_len++] = recv_data;}if(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_IDLE) != RESET){printf("recv:%s\r\n", g_uart1_rx_buf);uart1_clear_rx_buf();__HAL_UART_CLEAR_IDLEFLAG(&g_uart1_handle);}
}

5.2.3重定義fputc -- 支持printf函數

????????fputc() 是 printf() 的底層輸出函數通過重寫該函數,可以將 printf() 輸出重定向到串口,便于調試和日志輸出。

/*** @brief       重定義fputc函數* @note        printf函數最終會通過調用fputc輸出字符串到串口*/
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);                 /* 等待上一個字符發送完成 */USART1->DR = (uint8_t)ch;                         /* 將要發送的字符 ch 寫入到DR寄存器 */return ch;
}

????????USART1->SR 是 UART 的狀態寄存器(Status Register);0x40 對應的是 TXE(Transmit Data Register Empty)標志位。當 TXE=1 表示 DR 寄存器為空,即可以寫入新數據。將字符 ch 寫入數據寄存器(Data Register),開始通過USART1向外發送。

6.整體代碼 && 實驗現象

6.1uart1.h

? ? ? ? 主要進行了UART1的引腳宏定義和函數聲明。

#ifndef __UART1_H__
#define __UART1_H__#include "stdio.h"
#include "sys.h"/**********************宏定義**************************************/
/*		引腳定義	*/
#define		UART1_TX_PORT			GPIOA
#define		UART1_TX_PIN			GPIO_PIN_9#define		UART1_RX_PORT			GPIOA
#define		UART1_RX_PIN			GPIO_PIN_10/* UART收發緩沖大小 */
#define UART1_RX_BUF_SIZE            128
#define UART1_TX_BUF_SIZE            64/* 錯誤代碼 */
#define UART1_EOK                     0      /* 沒有錯誤 */
#define UART1_ERROR                   1      /* 通用錯誤 */
#define UART1_ETIMEOUT                2      /* 超時錯誤 */
#define UART1_EINVAL                  3      /* 參數錯誤 *//**********************函數聲明**************************************/
void uart1_init(unsigned int baudrate);            /* 串口初始化函數 */#endif

6.2uart1.c

? ? ? ? 操作USART1的函數。

#include "sys.h"
#include "uart1.h"
#include "string.h"/*		全局變量		*/
unsigned char g_uart1_rx_buf[UART1_RX_BUF_SIZE];		//保存接收的數據
unsigned short g_uart1_rx_len = 0;						//接收數據的長度
UART_HandleTypeDef g_uart1_handle;						//UART1句柄/*** @brief       重定義fputc函數* @note        printf函數最終會通過調用fputc輸出字符串到串口*/
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);                                       /* 等待上一個字符發送完成 */USART1->DR = (uint8_t)ch;                                               /* 將要發送的字符 ch 寫入到DR寄存器 */return ch;
}/*** @brief       串口1初始化函數* @param       baudrate: 波特率, 根據自己需要設置波特率值* @retval      無*/
void uart1_init(unsigned int baudrate)
{g_uart1_handle.Instance = USART1;						//配置的是USART1g_uart1_handle.Init.BaudRate = baudrate;				//波特率g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;	//數據位為8位g_uart1_handle.Init.StopBits = UART_STOPBITS_1;			//停止位為1位g_uart1_handle.Init.Parity = UART_PARITY_NONE;			//無校驗位g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;	//不使用CTS/RTS硬件流控位g_uart1_handle.Init.Mode = UART_MODE_TX_RX;				//UART發送和接收HAL_UART_Init(&g_uart1_handle);							//調用初始化函數進行初始化
}/*** @brief       UART底層初始化函數* @param       huart: UART句柄類型指針* @note        此函數會被HAL_UART_Init()調用*              完成時鐘使能,引腳配置,中斷配置* @retval      無*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){/*	1.打開時鐘	*/__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*	2.配置GPIO	*/GPIO_InitTypeDef gpio_handle = {0};gpio_handle.Pin = UART1_TX_PIN;gpio_handle.Mode = GPIO_MODE_AF_PP;gpio_handle.Pull = GPIO_PULLUP;gpio_handle.Speed = GPIO_SPEED_FREQ_MEDIUM;HAL_GPIO_Init(UART1_TX_PORT, &gpio_handle);gpio_handle.Pin = UART1_RX_PIN;gpio_handle.Mode = GPIO_MODE_AF_INPUT;gpio_handle.Pull = GPIO_PULLUP;HAL_GPIO_Init(UART1_RX_PORT, &gpio_handle);/*	3.打開中斷	*/HAL_NVIC_SetPriority(USART1_IRQn, 2, 2);HAL_NVIC_EnableIRQ(USART1_IRQn);__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);		//打開接收中斷__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);		//打開空閑中斷}
}/*** @brief       UART1接收緩沖區清除* @param       無* @retval      無*/
void uart1_clear_rx_buf(void)
{memset(g_uart1_rx_buf, 0, sizeof(g_uart1_rx_buf));g_uart1_rx_len = 0;
}/*** @brief       串口1中斷服務函數* @note        在此使用接收中斷,實現不定長數據收發* @param       無* @retval      無*/
void USART1_IRQHandler(void)
{unsigned char recv_data;if(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_RXNE) != RESET){if(g_uart1_rx_len >= sizeof(g_uart1_rx_buf))g_uart1_rx_len = 0;HAL_UART_Receive(&g_uart1_handle, &recv_data, 1, 1000);g_uart1_rx_buf[g_uart1_rx_len++] = recv_data;}if(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_IDLE) != RESET){printf("recv:%s\r\n", g_uart1_rx_buf);uart1_clear_rx_buf();__HAL_UART_CLEAR_IDLEFLAG(&g_uart1_handle);}
}

6.3main.c

? ? ? ? 在主函數中調用uart1_init函數,傳遞的參數115200是波特率。

#include "main.h"int main(void)
{HAL_Init();                         /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); 	/* 設置時鐘, 72Mhz */uart1_init(115200);while(1){delay_ms(10);}
}

6.4實驗現象

????????首先在KEIL5中魔術棒中勾選 Use MicroLIB選項。

? ? ? ? 寫好程序之后下載程序到開發板,然后打開電腦的串口調試助手,并且按照上面配置的波特率、停止位、數據位、校驗位打開串口。

? ? ? ? 之后發送數據,對應的接收區會有 recv:[數據]返回。就正常了。

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

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

相關文章

【PyTorch項目實戰】CycleGAN:無需成對訓練樣本,支持跨領域圖像風格遷移

文章目錄 一、風格遷移模型🎨1、發展時間線2、分類與優缺點3、選擇建議4、HuggingFace Demo(instruct-pix2pix) —— 在線測試 二、論文簡讀(1)FastStyleTransfer(快速風格遷移,Johnson et al.,…

C#Halcon從零開發_Day14_AOI缺陷檢測策略1_Bolb分析+特征分析_餅干破損檢測

一、引言 *缺陷檢測策略1:Blob分析特征分析 *Blob分析:閾值分割、開閉運算 (1) 圖像預處理 目的:增強目標與背景的對比度,抑制噪聲。 常用算子: threshold():通過閾值分割將圖像轉換為二值圖像。 mean_…

18年磨一劍!開利科技啟動數字化增量投資新時代

當傳統營銷陷入流量困局,當數字化轉型變成"面子工程",廣州開利網絡用18年技術積淀給出新答案——"蚓鏈數字化生態營銷系統",讓企業不再為數字化而數字化,而是通過數字化實現利潤增長! 核心亮點&am…

65-Oracle Undo機制

前一期看了Oracle在redo上保持事務前滾的一致性,同樣Oracle在Undo的管理機制也是現代事務型數據庫的工程典范。核心在于通過多版本并發控制(MVCC)技術,在保障數據一致性與提升系統性能之間實現精妙平衡。Undo機制構建了原子事務的…

【ESP32攝像頭開發實例】-實現遙控視頻小車

ESP32-CAM實現遙控視頻小車 文章目錄 ESP32-CAM實現遙控視頻小車1、硬件準備2、代碼實現3、代碼解析4、程序下載到開發板在本文中,將詳細介紹如何使用ESP32-CAM制作一輛Wi-Fi遠程控制的小車。 1、硬件準備 在開始這個項目之前,我們將強調用于構建機器人的最重要的特性和組件…

圖片加載優化(縮略圖)

縮略圖 系統目前的問題:首頁直接加載原圖,原圖文件通常比縮略圖大數倍甚至數十倍,不僅導致加載時間長,還會造成大量流量浪費。 解決方案:上傳圖片時,同時生成一份較小尺寸的縮略圖。用戶瀏覽圖片列表時加…

GO語言---數組

文章目錄 數組的基本特性數組的聲明和初始化數組元素的訪問和操作數組遍歷多維數組數組的長度和容量數組作為函數參數數組與切片的區別注意 數組是Go語言中最基本的數據結構之一,它是一組相同類型元素的固定長度序列。 數組的基本特性 1、固定長度:數組…

7.5.3_1處理沖突的方法-拉鏈法

知識總覽: 拉鏈法: 開始散列表中沒有存儲任何數據元素即散列地址上的元素是空的,散列地址可以視為鏈表的頭指針,即沒有插入任何元素前鏈表的頭指針是空的。一個散列地址對應一個鏈表,散列地址上實際沒有存數據元素&am…

鴻蒙運動項目開發:項目運行環境切換器

##鴻蒙核心技術##運動開發# 在開發鴻蒙運動項目時,管理不同運行環境(如開發環境、測試環境、生產環境)是一個常見的需求。通過合理地切換運行環境,開發者可以方便地進行調試、測試和部署。本文將介紹如何實現一個項目運行環境切換…

Linux內核中安全創建套接字:為何inet_create未導出及正確替代方案

引言 在Linux內核開發中,當驅動程序需要創建網絡套接字時,開發者常會遇到一個關鍵問題:核心函數inet_create(負責初始化IPv4套接字)并未導出到內核符號表。本文深入剖析這一設計決策背后的邏輯,并提供驅動程序安全創建套接字的實踐方案。 一、inet_create未導出的深層原…

63、不同路徑II

題目 解答: 初始化和特殊情況比較麻煩的dp obstacleGrid(0,0)1的,直接return 0即可。入口都被堵住了還怎么走。 mn1情況,直接判斷 第一行初始化:dp[1][0]->dp[i][0] 碰到有障礙物的,從當前格子開始到末尾全部置…

wx小程序登錄設置角色

背景。pc端登錄后在訪問業務鏈接時可以根據固定獲取用戶的方法LoginUser user LoginHelper.getLoginUser(); 獲取到用戶信息。但wx端登錄后無法獲取。原因處在登陸時對用戶信息的設置方面pc端和小程序端登錄沒有使用相同的登錄方法。排除得知wx端小程序登錄時沒有設置角色。所…

MySQL5.7 慢查詢SQL語句集合

文章目錄 1. 按平均執行時間排序的慢查詢2. 按總執行時長排序的慢查詢3. MySQL 5.7 慢查詢配置檢查4. 掃描行數分析(找出全表掃描)5. 高頻執行的慢查詢6. 當前正在執行的查詢7. 慢查詢統計匯總8. 表結構和索引分析8.1 表索引詳情查詢8.2 表大小統計 1. 按…

MySQL學習(1)——基礎庫操作

歡迎來到博主的專欄:MySQL學習 博主ID:代碼小豪 文章目錄 數據庫原理基礎庫操作增刪數據庫數據庫編碼與校驗規則驗證不同的校驗規則對于庫中數據的影響 備份與恢復數據庫 數據庫原理 mysql版本:mysql8.0 操作系統:ubuntu22.4 為了減少由于環境配置以及權限限制帶來的使用問題&…

C++法則12:右值引用的核心目的:支持移動語義(Move Semantics)

C法則12:右值引用的核心目的:支持移動語義(Move Semantics) 右值引用(Rvalue Reference)是C11引入的最重要特性之一,其主要設計目的就是支持移動語義(Move Semantics)。 …

【LLM學習筆記4】使用LangChain開發應用程序(上)

目錄 前言一、模型、提示和解析器(model、prompt、parsers)二、儲存三、模型鏈四、基于文檔的問答1.使用向量存儲查詢2. 結合表征模型和向量存儲使用檢索問答鏈回答問題 前言 在前面兩部分,我們分別學習了大語言模型的基礎使用準則&#xff…

Negative Contrastive Estimation Negative Sampling

1. 基本概念與問題背景 1.1 大規模分類問題 在自然語言處理中,給定上下文 c c c預測單詞 w w w的條件概率為: P ( w ∣ c ) exp ? ( s θ ( w , c ) ) ∑ w ′ ∈ V exp ? ( s θ ( w ′ , c ) ) P(w|c) \frac{\exp(s_\theta(w,c))}{\sum_{w\in V…

Flink SQL Connector Kafka 核心參數全解析與實戰指南

Flink SQL Connector Kafka 是連接Flink SQL與Kafka的核心組件,通過將Kafka主題抽象為表結構,允許用戶使用標準SQL語句完成數據讀寫操作。本文基于Apache Flink官方文檔(2.0版本),系統梳理從表定義、參數配置到實戰調優…

vscode內嵌瀏覽器實時預覽vue項目

安裝插件 web Preview 啟動vue項目 打開預覽 ctrl shift p 之后輸入并選擇 Open Web Preview 即可看到預覽窗口,但此時明明我的頁面是有內容的,但是窗口卻空白的。 因為默認訪問端口是3000,我們將其修改為vue項目默認的5173端口即可。 點…

計算機網絡:(四)物理層的基本概念,數據通信的基礎知識,物理層下面的傳輸媒體

計算機網絡:(四)物理層的基本概念,數據通信的基礎知識,物理層下面的傳輸媒體 前言一、物理層的基本概念1. 什么是物理層2. 物理層的核心使命3. 物理層的四大特性 二、數據通信的基礎知識1. 數據通信系統的基本模型1.1 …