串行通信接口USART,printf重定向數據發送,輪詢和中斷實現串口數據接收

目錄

UART通信協議的介紹

實現串口數據發送

CubeMX配置

printf重定向代碼編寫

實現串口數據接收

輪詢方式實現串口數據接收

接收單個字符

接收不定長字符串(接收的字符串以\n結尾)

中斷方式實現串口數據接收

CubeMX配置

UART中斷方式接收數據函數是一次性的

HAL_UART_Receive_IT() 調用位置

接收單個字符

接收不定長字符串


UART通信協議的介紹

UART (Universal Asynchronous Receiver/Transmitter) 是一種串行異步全雙工通信協議

UART通信的核心思想是異步串行,全雙工

  • 異步 (Asynchronous):通信雙方不需要共享一個時鐘信號來同步數據傳輸。取而代之的是,通過起始位 (Start Bit) 標記數據幀的開始,通過停止位 (Stop Bit) 標記數據幀的結束,以及預先約定好的波特率 (Baud Rate) 來協調數據的采樣時間。
    ?

  • 串行 (Serial):數據一位一位地按順序在線路上傳輸,而不是并行多位同時傳輸。這使得只需要兩根線。

異步詳細介紹

  • 發送方: 按照預設的波特率,精確地控制每個數據位、起始位和停止位的持續時間,并將其串行發送出去。
    ?

  • 接收方: 同樣按照預設的波特率,在檢測到起始位后,精確地計算每個數據位的采樣時間點,從而正確讀取數據。

進行異步通信,通信的每一方都必須擁有自己的內部時鐘,如果沒有各自的內部時鐘,發送方就無法知道何時發送下一個比特,接收方也無法知道何時去讀取數據線上的電平。

通信雙方的波特率必須相同,否則將導致數據錯亂。

使用串口助手進行串口通信的時候,是滿足這里的要求的,電腦上面有時鐘,同時開發板內部的UART也有時鐘。

串行,全雙工詳細介紹

標準的UART通信通常只需要兩根信號線:

  • TX (Transmit):發送數據線,用于發送數據。

  • RX (Receive):接收數據線,用于接收數據。

連接方式是交叉連接:發送方的TX連接到接收方的RX,發送方的RX連接到接收方的TX。

由于發送和接收使用不同的物理線路,它們互不干擾,所以發送方可以在向接收方發送數據的同時,接收方也可以向發送方發送數據。UART協議全雙工通信協議

實現串口數據發送

CubeMX配置

配置好時鐘源之后,選擇USART1之后選擇模式為異步模式就可以了,剩下的配置不需要動。

選完之后我們會發現這里多了兩個選中的引腳,?TX(發送)RX(接收)

如果選擇同步通信方式的話還會有一根時鐘線用于同步操作。

在USART協議中我們其實是可以選擇使用同步方式(synchronous)或者異步方式(Asynchronous)進行數據的發送和接收的 ,不過一般異步方式用的多,同步方式通信一般會選擇其他類型協議如 SPI、I2C。

printf重定向代碼編寫

串口調試助手在沒有顯示屏的嵌入式系統中有著很好的應用,可以利用函數重定向功能,調用printf函數,將開發板中獲取到的數據通過串口刷出到PC,為程序調試和串口通信提供了很大的便利。

我們不能直接調用printf將數據輸出到串口,要想實現printf重定向功能,還需要進行重寫一下fputc函數

為什么 printf 默認不能輸出到串口?

在 C 標準庫中,printf() 的本質是將格式化后的字符串輸出到一個默認的標準輸出設備,這個設備在 PC 上通常是終端(屏幕),但在 MCU(如 STM32)里:

  • 沒有默認的標準輸出設備(沒有屏幕、沒有操作系統);

  • 所以 printf() 其實調用的是底層函數如 fputc()_write(),但這些在裸機環境下是 空實現報錯實現

fputc的函數原型照抄就行,這里的第二個參數用不到,不需要處理。

fputc函數的作用是輸出單個字符,所以這里使用HAL_UART_Transmit實現fputc輸出字符的時候,參數選擇字節數為1就行。這樣實現出來的輸出字符串到串口助手的效果非常好,還很簡便,不需要我們判斷發送到串口的字符串長度邏輯(printf幫我們做了,我們只需要實現單個字符發送就可以!)

int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}

?HAL_UART_Transmit函數介紹

  1. UART_HandleTypeDef *huart (第一個參數):

    這是一個指向 UART_HandleTypeDef 結構體的指針。這個結構體包含了特定 UART 外設的所有配置信息和狀態。

    ?
  2. uint8_t *pData (第二個參數):

    這是一個指向要發送數據的緩沖區的指針。uint8_t 表示數據是以字節(8位)的形式傳輸。函數會從這個地址開始讀取數據并發送出去。

    ?
  3. uint16_t Size (第三個參數):

    這是一個 uint16_t 類型的變量,表示要發送的數據的字節數(長度)。

    ?
  4. uint32_t Timeout (第四個參數):
  • 這是一個 uint32_t 類型的變量,表示數據發送操作的超時時間,單位是毫秒(ms)。
  • 如果在指定的時間內數據沒有發送完成,函數將返回 HAL_TIMEOUT。
  • 使用 HAL_MAX_DELAY 表示無限等待,直到數據發送完成(或發生錯誤),這在不希望有超時限制的情況下很常用。

由于使用了printf這個函數,所以我們需要在main.c文件中包含對應的頭文件:

#include "stdio.h"

  /* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */uint16_t cnt=0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */printf("this is a message from stm32 cnt : %d\n", cnt++);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

Keil中對文件勾選配置:Use MicroLIB

效果展示:?

實現串口數據接收

輪詢方式實現串口數據接收

接收單個字符

uint8_t receive_data;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_UART_Receive(&huart1, &receive_data, 1, HAL_MAX_DELAY);printf("receive data: %c\r\n", receive_data);/* USER CODE BEGIN 3 */}

接收不定長字符串(接收的字符串以\n結尾)

    uint8_t receive_data;uint8_t receive_buf[256] = {0};uint8_t index = 0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_UART_Receive(&huart1, &receive_data, 1, HAL_MAX_DELAY);if(receive_data != '\n'){receive_buf[index++] = receive_data;}else{receive_buf[index++] = '\0';printf("receive data: %s\r\n", receive_buf);index = 0;memset(receive_buf, 0, sizeof(receive_buf));}/* USER CODE BEGIN 3 */}

代碼介紹?

這段代碼是典型的使用 HAL 庫的輪詢(阻塞)模式接收串口數據,并以換行符 \n 作為結束標志 的實現。

這段代碼的主要功能是:

  1. 在無限循環 while(1) 中,阻塞式地等待 接收 UART1 的一個字節數據。
    ?
  2. 如果接收到的字節不是換行符 \n,則將其存儲到 receive_buf 緩沖區中。
    ?
  3. 如果接收到換行符 \n,則認為一幀數據接收完畢:
    • 在緩沖區末尾添加字符串結束符 \0。
    • 通過 printf 打印接收到的字符串。
    • 重置 index 為 0,準備接收下一幀數據。
    • 清空 receive_buf 緩沖區。

代碼優缺點:

優點

  1. 簡單易懂: 對于初學者來說,這種輪詢加阻塞的模式是最容易理解和實現的。邏輯直接,容易跟蹤。

  2. 便于調試: 由于是阻塞式的,每次接收一個字節,單步調試時可以清晰地看到數據流。

  3. 處理明確的結束符: 使用 \n 作為幀結束符是文本協議中常見且有效的方式,使得數據包的邊界清晰。

缺點

CPU 效率極低(最主要的問題):

  • HAL_UART_Receive(&huart1, &receive_data, 1, HAL_MAX_DELAY); 這行代碼會無限期阻塞,直到接收到一個字節。這意味著在沒有數據到達時,CPU 會一直停在這里等待,無法執行其他任何任務

  • 這對于任何需要做其他事情(比如控制LED、讀取傳感器、處理按鍵等)的實時嵌入式系統來說都是不可接受的。CPU 的大部分時間都會被浪費在等待串口數據上。

注意看,我們在使用串口助手向開發板發送數據的時候,需要加上一個換行符,表示發送的這串字符串結束了。開發板內部的串口處理程序,順序收到/n之后,根據判斷邏輯就會輸出緩沖區積攢的字符串。

中斷方式實現串口數據接收

CubeMX配置

相比于上面采用非中斷模式來實現串口數據接收,采用中斷方式的話,需要將Uart1對應的中斷打開

UART中斷方式接收數據函數是一次性的

HAL_StatusTypeDef? HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

函數作用:啟動 UART1 的中斷接收,期望接收 uint16_t Size 個字節

HAL_UART_Receive_IT(&huart1, rx_buffer, 1); // 推薦每次只接收一個字節

雖然調用一次函數可以選擇接收多個字節數據,但是我們通常選擇調用一次UART中斷接收數據函數只接收一個字節,會在中斷回調里處理并再次啟動接收函數

為什么說UART 中斷接收函數為何說是“一次性的”?

  1. 這句話的意思是,當你調用 HAL_UART_Receive_IT(&huart, pData, Size); 這個函數后,它只會啟動一次中斷接收過程,并等待接收指定數量(Size)的字節
    ?
  2. 一旦 UART 接收到這 Size 個字節的數據,這個函數所啟動的當前接收任務就完成了。UART 接收中斷會相應地被觸發,執行你的回調函數 HAL_UART_RxCpltCallback()。
    ?
  3. 但是,此時 UART 并不會自動開始接收下一組數據 如果你想繼續接收數據,你需要再次調用 HAL_UART_Receive_IT() 來“重新武裝”UART 硬件,讓它準備好接收下一批數據,通常我們會選擇在回調函數HAL_UART_RxCpltCallback中再次啟動接收函數

HAL_UART_Receive_IT() 調用位置

HAL_UART_Receive_IT() 函數推薦在以下幾個地方調用:

1. main() 函數的初始化部分

這是最常見和推薦的調用位置。 在你的 main.c 文件中,通常在所有硬件初始化完成(例如 MX_GPIO_Init()、MX_USARTx_UART_Init() 等)之后,while(1) 無限循環之前,調用一次 HAL_UART_Receive_IT() 來啟動串口的首次接收。

int main(void)
{// ... 系統初始化 ...HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();// ... 其他外設初始化 .../* USER CODE BEGIN 2 */// 啟動 UART1 的中斷接收,期望接收 SOME_BUFFER_SIZE 個字節// 或者通常只接收一個字節,在中斷回調里處理并再次啟動HAL_UART_Receive_IT(&huart1, rx_buffer, 1); // 推薦每次只接收一個字節/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */

2.?UART 接收完成回調函數 HAL_UART_RxCpltCallback() 中

// 這個函數是弱聲明,你需要重寫它
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){// 假設這里處理了接收到的數據 rx_buffer// Process_Received_Data(rx_buffer);// 重新啟動下一次中斷接收HAL_UART_Receive_IT(&huart1, rx_buffer, 1); // 再次啟動接收一個字節}
}

接收單個字符

讓我們用一個小栗子來進行實現一下中斷接收單個字符吧。

代碼功能

這里我們想要實現的是通過串口助手,每次發送一個字符1/2/3/4來控制LED1/2/3/4,比如發送一個1,LED1電平就翻轉,再次輸入1LED1電平就再次翻轉。LED2/3/4同理。

這里為了展現出中斷方式接收數據不阻塞主程序執行,我們在main函數中還持續用向串口發送字符串"hello world"

代碼實現如下:

在main.c中定義成一個全局變量
/* USER CODE BEGIN PV */uint8_t receive_data;//存放UART1接收到的數據
/* USER CODE END PV */函數聲明部分
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
int fputc(int ch, FILE *f);
/* USER CODE END PFP */main函數里面
/* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, &receive_data, 1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */printf("hello world\r\n");HAL_Delay(1000);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}main函數中定義的函數的具體實現
/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if(huart->Instance == USART1){if(receive_data == '1'){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_10);}else if(receive_data == '2'){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);}else if(receive_data == '3'){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);}else if(receive_data == '4'){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);}}HAL_UART_Receive_IT(&huart1, &receive_data, 1);
}
/* USER CODE END 4 */

代碼編寫時候需要注意的就是

  • HAL_UART_Receive_IT()需要在main函數初始化的時候調用,
    ?
  • 還需要在?HAL_UART_RxCpltCallback中調用

接收不定長字符串

代碼實現思路

  1. 每次只接收一個字節: 在中斷模式下,將 HAL_UART_Receive_IT() 的 Size 參數設置為 1。這樣每接收到一個字節,就會觸發一次接收完成中斷。
    ?
  2. 使用緩沖區 (Buffer): 在中斷服務程序中,將接收到的每一個字節存入緩沖區。
    ?
  3. 在主循環中判斷數據完整性: 主循環會不斷地檢查緩沖區中是否有完整的字符串幀(通常通過查找特定的結束符,如 \n )。
    ?
  4. 重新啟動接收: 在每次接收完成中斷回調函數中,都需要再次調用 HAL_UART_Receive_IT() 來“重新武裝”串口,準備接收下一個字節。

CubeMX配置

上面已經說過了,主要需要注意的是記得在NVIC 設置中,勾選開啟對應 UART 全局中斷的 Enabled

代碼實現

額外包含頭文件
#include "stdio.h"
#include "string.h"main.c中定義的全局變量
/*
這里定義成全局變量的原因:
回調函數的實現以及main函數中都要用到這些變量
*/
/* USER CODE BEGIN PV */uint8_t receive_data;uint8_t receive_buf[256] = {0};uint8_t receive_buf_index = 0;
/* USER CODE END PV */函數聲明
/* USER CODE BEGIN PFP */
int fputc(int ch, FILE* f);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
/* USER CODE END PFP */main函數中代碼
HAL_UART_Receive_IT(&huart1, &receive_data, 1);/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */printf("hello world\r\n");HAL_Delay(1000);/* USER CODE BEGIN 3 */}代碼實現部分
int fputc(int ch, FILE* f){HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);	return ch;
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if(huart->Instance == USART1){if(receive_data != '\n'){receive_buf[receive_buf_index++] = receive_data;}else{receive_buf[receive_buf_index++] = '\0';printf("receive data: %s\r\n", receive_buf);receive_buf_index = 0;memset(receive_buf, 0, sizeof(receive_buf));}HAL_UART_Receive_IT(&huart1, &receive_data, 1);}
}

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

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

相關文章

Kafka 生產者和消費者高級用法

Kafka 生產者和消費者高級用法 1 生產者的事務支持 Kafka 從版本0.11開始引入了事務支持,使得生產者可以實現原子操作,確保消息的可靠性。 // 示例代碼:使用 Kafka 事務 producer.initTransactions(); try {producer.beginTransaction();pr…

k8s中crictl命令常報錯解決方法

解決使用crictl命令時報默認端點棄用的報錯 報錯核心原因 默認端點棄用: crictl 會默認嘗試多個容器運行時端點(如 dockershim.sock、containerd.sock 等),但這種 “自動探測” 方式已被 Kubernetes 棄用(官方要求手動…

回轉體水下航行器簡單運動控制的奧秘:PID 控制和水動力方程的運用

在水下航行器的控制領域中,回轉體水下航行器的運動控制是一個關鍵課題。 今天,就來深入探討一下其簡單運動控制中,PID 控制以及水動力方程的相關運用。 PID 控制的基本原理PID 控制(比例 - 積分 - 微分控制)是一種廣…

從入門到精通:npm、npx、nvm 包管理工具詳解及常用命令

目錄 1. 引言2. npm (Node Package Manager)2.1 定義與用途2.2 常見命令2.3 使用示例 3. npx (Node Package Execute)3.1 定義與用途3.2 常見命令3.3 使用示例3.4 npm 與 npx 的區別 4. nvm (Node Version Manager)4.1 定義與用途4.2 安裝 nvm4.3 常見命令4.4 使用示例 5. 工具…

es6特性-第二部分

Promise 介紹和基本使用 Promise是ES6引入的異步編程的新解決方案,主要用來解決回調地獄問題。語法上 Promise是一個構造函數,用來封裝異步操作并可以獲取其成功或失敗的結果。 Promise構造函數:new Promise() Promise.prototype.then方法 Promise.prototype.ca…

java:如何用 JDBC 連接 TDSQL 數據庫

要使用JDBC連接TDSQL數據庫&#xff08;騰訊云分布式數據庫&#xff0c;兼容MySQL協議&#xff09;&#xff0c;請按照以下步驟編寫Java程序&#xff1a; 1. 添加MySQL JDBC驅動依賴 在項目的pom.xml中添加依賴&#xff08;Maven項目&#xff09;&#xff1a; <dependenc…

2025年四川省高考志愿填報深度分析與專業導向策略報告——基于599分/24000位次考生-AI

2025年四川省高考志愿填報深度分析與專業導向策略報告——基于599分/24000位次考生 摘要 本報告旨在為預估高考成績599分、全省物理類位次在24,000名左右的2025年四川考生&#xff0c;提供一份兼具科學性、前瞻性與專業深度的志愿填報策略方案。報告嚴格遵循“位次法”為核心…

spring boot項目整合百度翻譯

本片文章教大家怎樣在spring boot項目中引入百度翻譯&#xff0c;并且優雅的使用百度翻譯。 首先&#xff0c;我們要了解為什么要使用翻譯插件。為了支持多語言的國際化&#xff1b; 目前市面上最常見的后端國際化就是在resource資源目錄下設置多個語言文檔&#xff0c;這些文…

凌晨2點自動備份mysql 數據庫,mysql_backup.sh

1、編寫備份腳本&#xff1a;vim mysql_backup.sh #!/bin/bash DATE$(date %Y%m%d_%H%M%S) BACKUP_DIR"/data/mysql/backup" USER"backup_user" PASSWORD"backup**"# 邏輯備份所有數據庫 mysqldump -u$USER -p$PASSWORD eblp | gzip > $BA…

Linux系統之Tomcat服務

目錄 一、Tomcat概述 1、Tomcat介紹 2、Tomcat歷史 二、Tomcat原理分析 1、Http工作原理 2、Tomcat整體架構 3、Coyote連接器架構 4、Catalina容器架構 5、Jasper處理流程 6、JSP編譯過程 7、Tomcat啟動流程 8、Tomcat請求處理流程 三、Tomcat安裝與配置 1、單實…

FPGA芯片的供電

FPGA芯片的供電 文章目錄 FPGA芯片的供電1. 外部端口供電機制2. 內部邏輯供電機制3. 專有電路供電機制4. 電源穩定性討論總結 1. 外部端口供電機制 FPGA是專門用于數字系統設計的芯片&#xff0c;能夠正確、可靠、高效地和外界其他數字電路進行通信是FPGA芯片必備的一個功能。…

構建可無限擴展的系統:基于 FreeMarker + 存儲過程 + Spring Boot 的元數據驅動架構設計

在構建面向多行業、多客戶的大型業務系統時&#xff0c;系統的靈活性與擴展能力成為架構設計的核心目標。傳統硬編碼的開發方式在面對高頻變化、復雜組合查詢、多租戶自定義字段時&#xff0c;往往難以適應。 為了解決上述問題&#xff0c;我們提出一種 以 FreeMarker 腳本托管…

2-深度學習挖短線股-3-訓練數據計算

2-3 合并輸入特征 首先定義了數據預處理函數&#xff0c;將連續 n 天的 K 線數據&#xff08;如開盤價、收盤價、成交量等&#xff09;合并為一行特征&#xff0c;同時保留對應的目標標簽&#xff08;buy 列&#xff0c;表示是否應該買入&#xff09;&#xff1b;然后讀取股票代…

SpringMVC系列(四)(請求處理的十個實驗(下))

0 引言 作者正在學習SpringMVC相關內容&#xff0c;學到了一些知識&#xff0c;希望分享給需要短時間想要了解SpringMVC的讀者朋友們&#xff0c;想用通俗的語言講述其中的知識&#xff0c;希望與諸位共勉&#xff0c;共同進步&#xff01; 本系列會持續更新&#xff01;&…

產線通信“變形記”:PROFIBUS-DP與ETHERNET/IP的食品飲料跨界融合

在食品飲料加工行業&#xff0c;為實現不同設備間高效通信&#xff0c;JH-PB-EIP疆鴻智能PROFIBUS DP轉ETHERNET/IP網關發揮著關鍵作用。西門子PLC常采用PROFIBUS DP協議&#xff0c;而碼垛機器人等設備多使用ETHERNET/IP協議&#xff0c;網關成為連接二者的橋梁。 將DP作為從站…

設計模式-觀察者模式(發布訂閱模式)

一、需要的類 一個發布類&#xff1a;里面一個是別人需要訂閱的屬性&#xff0c;以及用于存儲訂閱者的list&#xff0c;attach方法是往list集合里面添加元素&#xff0c;notifyObservers通知方法&#xff0c;也就是循環調用訂閱者里面的一個方法&#xff0c;這個notifyObserve…

Linux測試是否能聯網

ping百度看是否有返回包&#xff1a; ping www.baidu.com ping -c可以通過參數提前設置發送的包數量&#xff1a; ping -c 4 www.baidu.com 終止ping快捷鍵&#xff1a; 按下 Ctrl C&#xff1a;立即終止ping進程&#xff0c;并顯示統計信息。按下 Ctrl Z&#xff1a;將進…

TOGAF? 架構分區:優秀架構的秘密

TOGAF &#xff08;The Open Group架構框架&#xff09;已成為企業架構事實上的全球標準, 是世界上使用最廣泛的企業架構框架。 它為企業 IT 架構的設計、規劃、實施和管理提供了一套全面的方法和工具。但是&#xff0c;即使是經驗豐富的架構師也經常會忽略 TOGAF 中隱藏的寶…

如何讓視頻在特定的網站上播放/禁止播放?(常見的視頻防盜鏈技術之一)

一、需求背景 在各行各業中,不論是教育、貿易還是醫療領域,視頻內容都存在被盜用的風險。為加強視頻安全性,我們可以采取特殊設置措施,例如限制視頻僅在高安全性網站播放,或屏蔽高風險網站。那么,具體有哪些方法可以有效保護視頻安全呢? 二、需求解決 通過OVP防盜鏈技…

如何調鼠標的靈敏度 快速調節超簡單

鼠標靈敏度是指鼠標在移動時&#xff0c;指針在屏幕上移動的速度。適當的鼠標靈敏度不僅能夠提高工作效率&#xff0c;還能減少手部疲勞&#xff0c;優化游戲體驗。那么不同的使用場景&#xff0c;鼠標靈敏度怎么調呢&#xff1f;本文將詳細探討如何調整鼠標靈敏度&#xff0c;…