STM32-15-DMA

STM32-01-認識單片機
STM32-02-基礎知識
STM32-03-HAL庫
STM32-04-時鐘樹
STM32-05-SYSTEM文件夾
STM32-06-GPIO
STM32-07-外部中斷
STM32-08-串口
STM32-09-IWDG和WWDG
STM32-10-定時器
STM32-11-電容觸摸按鍵
STM32-12-OLED模塊
STM32-13-MPU
STM32-14-FSMC_LCD

文章目錄

  • STM32-15-DMA
    • 1. DMA與中斷的區別
      • 1. DMA
      • 2. 中斷
    • 2. DMA介紹
    • 3. DMA結構框圖
      • 1. DMA框圖
      • 2. DMA處理過程
      • 3. DMA通道
    • 4. DMA相關寄存器
    • 5. DMA相關HAL庫驅動
    • 6. 代碼實現

STM32-15-DMA

1. DMA與中斷的區別

**DMADirect Memory Access,直接內存訪問)**和中斷是兩種不同的機制,用于管理計算機系統中外圍設備與處理器之間的數據傳輸和處理。

1. DMA

工作原理:

  • 獨立傳輸:DMA允許外設直接與系統內存交換數據,而不需要通過處理器(CPU)。當需要大量數據傳輸時,DMA控制器接管傳輸任務,釋放CPU去執行其他任務。
  • 傳輸過程:DMA傳輸數據時,CPU啟動DMA傳輸,然后DMA控制器接管整個傳輸過程。傳輸完成后,DMA控制器通過中斷通知CPU傳輸完成。

作用:

  • 提高效率:DMA減少了CPU在數據傳輸過程中的參與,使得CPU能夠執行其他任務,從而提高系統的整體效率。
  • 減少延遲:由于DMA可以獨立進行傳輸,因此數據傳輸的延遲更低,特別是在處理大塊數據時。
  • 應用場景:DMA廣泛應用于音頻視頻數據流網絡數據包的傳輸存儲設備的數據讀寫等場景。

對程序的影響:

  • 復雜度增加:引入DMA需要對DMA控制器進行配置,可能增加程序的復雜性。
  • 同步問題:在DMA傳輸過程中,程序需要處理好數據同步問題,避免數據不一致性問題。

2. 中斷

工作原理:

  • 中斷觸發:中斷是外設通過中斷信號通知CPU某個事件發生,如輸入設備有新數據可讀取,定時器到期等。
  • 中斷處理:CPU響應中斷后,暫停當前任務,跳轉到相應的中斷處理程序(ISR)執行。當中斷處理程序執行完畢后,CPU恢復先前任務的執行。

作用:

  • 實時響應:中斷機制使CPU能夠實時響應外設事件,保證系統對外部事件的快速反應。
  • 事件驅動:中斷使得程序可以基于事件驅動,而不是定期輪詢外設狀態,從而節省CPU資源。
  • 應用場景鍵盤輸入鼠標移動網絡數據包到達定時器事件等。

對程序的影響:

  • 中斷處理程序設計:中斷處理程序需要盡可能簡短、快速,避免長時間占用CPU。
  • 中斷優先級管理:系統中可能有多個中斷源,需要合理設計中斷優先級,以確保關鍵中斷能夠及時響應。
  • 上下文切換開銷:中斷會引起上下文切換,帶來一定的性能開銷。

總結

  • DMA:適用于大量數據傳輸,降低CPU負載,提高系統效率。
  • 中斷:適用于實時事件響應,保證系統對外部事件的快速處理。

兩者結合使用,可以構建高效、實時的嵌入式系統。例如,DMA用于大數據塊的傳輸,而中斷用于觸發DMA傳輸和處理傳輸完成事件。

2. DMA介紹

  • **DMA:**即直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAM與I/O設備開辟一條直接傳送數據的通路,能使CPU的效率大為提高。
  • STM32F103內部有2個DMA控制器,DMA17個通道,DMA25個通道。每個通道專門用來管理來自于一個或多個外設對存儲器訪問的請求,還有一個仲裁器來協調各個DMA請求的優先權。
  • 特性:
    • 每個通道都直接連接專用的硬件DMA請求,每個通道都支持軟件觸發。這些功能通過軟件來配置。
    • 在七個請求間的優先權可以通過軟件編程設置,當軟件相同時,由硬件決定。
    • 獨立的源和目標數據區的傳輸寬度,模擬打包和拆包的過程。源和目標地址必須按數據傳輸寬度對齊。
    • 支持循環的緩沖器管理。
    • 每個通道都有3個事件標志,這3個事件標志邏輯或成為一個單獨的中斷請求。
    • 存儲器和存儲器間的傳輸。
    • 外設和存儲器,存儲器和外設的傳輸。
    • 閃存、SRAM、外設的SRAM、APB1、APB2和AHB外設均可作為訪問的源和目標。
    • 可編程的數據傳輸數目最大為65535。

3. DMA結構框圖

1. DMA框圖

在這里插入圖片描述

  • DMA請求

    如果外設想要通過DMA來傳輸數據,必須先給DMA控制器發送DMA請求,DMA收到請求信號之后,控制器會給外設一個應答信號,當外設應答后且DMA控制器收到應答信號之后,就會啟動DMA的傳輸,直到傳輸完畢。

  • DMA通道

    DMA具有12個獨立可編程的通道,其中DMA1有7個通道,DMA2有5個通道,每個通道對應不同的外設的DMA請求。雖然每個通道可以接收多個外設的請求,但是同一時間只能接收一個,不能同時接收多個。

  • DMA優先級

    當發生多個DMA通道請求時,就意味著有先后響應處理的順序問題,這個就由仲裁器管理。仲裁器管理DMA通道請求分為兩個階段。第一階段屬于軟件階段,可以在DMA_CCRx寄存器中設置,有4個等級:非常高四個優先級。第二階段屬于硬件階段,如果兩個或以上的DMA通道請求設置的優先級一樣,則他們優先級取決于通道編號,編號越低優先權越高,比如通道0高于通道1。在大容量產品和互聯型產品中,DMA1控制器擁有高于DMA2控制器的優先級。

2. DMA處理過程

在這里插入圖片描述

DMA(Direct Memory Access,直接內存訪問)是一種允許外設直接與系統內存進行數據傳輸的機制,不需要CPU的直接干預。以下是DMA處理過程的詳細描述:

DMA處理過程

  1. 配置DMA控制器
    • 源地址:設置數據傳輸的源地址(可以是外設寄存器地址或內存地址)。
    • 目標地址:設置數據傳輸的目標地址(可以是外設寄存器地址或內存地址)。
    • 傳輸方向:指定數據傳輸的方向,是從外設到內存,還是從內存到外設。
    • 數據長度:設置需要傳輸的數據長度(字節數)。
    • 傳輸模式:選擇傳輸模式,可以是單次傳輸、塊傳輸或連續傳輸模式。
  2. 啟動DMA傳輸
    • 觸發傳輸:在配置完成后,通過設置DMA控制器的啟動位,開始數據傳輸。
    • 數據搬運:DMA控制器接管數據傳輸任務,將數據從源地址搬運到目標地址。這個過程中,DMA控制器直接與內存控制器和外設總線進行交互,不需要CPU干預。
  3. 中斷通知
    • 傳輸完成中斷:數據傳輸完成后,DMA控制器產生中斷信號,通知CPU傳輸已經完成。CPU執行相應的中斷服務程序(ISR)處理后續任務。
    • 錯誤處理:如果在傳輸過程中發生錯誤(如總線錯誤),DMA控制器也會產生中斷,通知CPU進行錯誤處理。

3. DMA通道

DMA1通道與外設的對應關系
在這里插入圖片描述

DMA2通道與外設的對應關系
在這里插入圖片描述

4. DMA相關寄存器

寄存器名稱作用
DMA_CCRxDMA通道x配置寄存器用于配置DMA(核心控制寄存器)
DMA_ISRDMA中斷狀態寄存器用于查詢當前DMA傳輸狀態
DMA_IFCRDMA中斷標志清除寄存器用來清除DMA_ISR對應位
DMA_CNDTRxDMA通道x傳輸數量寄存器用于控制DMA通道x每次傳輸的數據量
DMA_CPARxDMA通道x外設地址寄存器用于存儲STM32外設地址
DMA_CMARxDMA通道x存儲器地址寄存器用于存放存儲器的地址
USART_CR3USART控制寄存器3用于使能串口DMA發送
  • DMA通道x配置寄存器(DMA_CCRx)
    在這里插入圖片描述

  • DMA中斷狀態寄存器(DMA_ISR)
    在這里插入圖片描述

  • DMA 中斷標志清除寄存器(DMA_IFCR)
    在這里插入圖片描述

  • DMA通道x傳輸數量寄存器(DMA_CNDTRx)
    在這里插入圖片描述

    該寄存器控制著DMA通道x的每次傳輸所要傳輸的數據量。其設置范圍為0~65535。并且該寄存器的值隨著傳輸的進行而減少,當該寄存器的值為0的時候就代表此次數據傳輸己經全部發送完成。可以通過這個寄存器的值來獲取當前DMA傳輸的進度

  • DMA通道x外設地址寄存器(DMA_CPARx)
    在這里插入圖片描述

    用來存儲 STM32 外設的地址。

  • DMA通道x存儲器地址寄存器(DMA_CMARx)
    在這里插入圖片描述

    用來存放存儲器的地址。

5. DMA相關HAL庫驅動

  1. 使能DMA時鐘

    __HAL_RCC_DMA1_CLK_ENABLE();
    
  2. 初始化DMA

    HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);typedef struct
    { uint32_t Direction; /* 傳輸方向,例如存儲器到外設 DMA_MEMORY_TO_PERIPH */uint32_t PeriphInc; /* 外設(非)增量模式,非增量模式 DMA_PINC_DISABLE */ uint32_t MemInc; /* 存儲器(非)增量模式,增量模式 DMA_MINC_ENABLE */ uint32_t PeriphDataAlignment; /* 外設數據大小:8/16/32 位 */uint32_t MemDataAlignment; /* 存儲器數據大小:8/16/32 位 */uint32_t Mode; /* 模式:循環模式/普通模式 */ uint32_t Priority; /* DMA 優先級:低/中/高/非常高 */
    }DMA_InitTypeDef;__HAL_LINKDMA(&g_uart1_handler, hdmatx, g_dma_handle);
    
  3. 使能串口的DMA發送,啟動傳輸

    HAL_UART_Transmit_DMA()HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); /* 停止 */
    HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); /* 暫停 */
    HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); /* 恢復 */
    
  4. 查詢DMA傳輸狀態

    //查詢DMA傳輸通道的狀態
    __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4);//獲取當前傳輸剩余數據量
    __HAL_DMA_GET_COUNTER(&g_dma_handle);//設置對應的DMA數據流傳輸的數據量大小
    __HAL_DMA_SET_COUNTER (&g_dma_handle, 1000);
    
  5. DMA中斷使用

    //通用中斷處理函數
    void HAL_DMA_IRQHandler();//相關中斷回調函數
    //發送完成回調函數
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
    //發送一半回調函數
    void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
    //接收完成回調函數
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
    //接收一半回調函數
    void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
    //傳輸出錯回調函數
    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
    

6. 代碼實現

  • 功能

    每按下按鍵KEY0,串口1就會以DMA方式發送數據,同時在LCD上面顯示傳送進度。打開串口調試助手,可以收到DMA發送的內容。LED0閃爍用于提示程序正在運行。

  • DMA初始化函數

    void dma_init(DMA_Channel_TypeDef* DMAx_CHx)
    {if((uint32_t)DMAx_CHx > (uint32_t)DMA1_Channel7){__HAL_RCC_DMA2_CLK_ENABLE();}else{__HAL_RCC_DMA2_CLK_ENABLE();}//將DMA與USART1連接起來__HAL_LINKDMA(&g_uart1_handle, hdmatx, g_dma_handle); g_dma_handle.Instance = DMAx_CHx;                   //USART1_TX使用的DMA通道為DMA_Channel4g_dma_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; //模式選擇為從存儲器到外設g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;     //外設非增量模式g_dma_handle.Init.MemInc = DMA_MINC_ENABLE;         //存儲器增量模式g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外設數據長度為8位g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    //存儲器數據長度為8位g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;            //中等優先級HAL_DMA_Init(&g_dma_handle);
    }
    
  • 主函數

    int main(void)
    {uint16_t i, k;uint16_t len;uint8_t  mask = 0;float pro = 0;          /* 進度 */HAL_Init();                         /* 初始化HAL庫 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */delay_init(72);                     /* 延時初始化 */usart_init(115200);                 /* 串口初始化為115200 */led_init();                         /* 初始化LED */lcd_init();                         /* 初始化LCD */key_init();                         /* 初始化按鍵 */dma_init(DMA1_Channel4);            /* 初始化串口1 TX DMA */lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);lcd_show_string(30, 70, 200, 16, 16, "DMA TEST", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 16, 16, "KEY0:Start", RED);len = sizeof(TEXT_TO_SEND);k = 0;for (i = 0; i < SEND_BUF_SIZE; i++) /* 填充ASCII字符集數據 */{if (k >= len)   /* 入換行符 */{if (mask){g_sendbuf[i] = 0x0a;k = 0;}else{g_sendbuf[i] = 0x0d;mask++;}}else     /* 復制TEXT_TO_SEND語句 */{mask = 0;g_sendbuf[i] = TEXT_TO_SEND[k];k++;}}i = 0;while (1){if (key_scan(0) == 1)       /* KEY0按下 */{printf("\r\nDMA DATA:\r\n");lcd_show_string(30, 130, 200, 16, 16, "Start Transimit....", BLUE);lcd_show_string(30, 150, 200, 16, 16, "   %", BLUE);    /* 顯示百分號 */HAL_UART_Transmit_DMA(&g_uart1_handle, g_sendbuf, SEND_BUF_SIZE);/* 等待DMA傳輸完成,此時我們來做另外一些事情,比如點燈  * 實際應用中,傳輸數據期間,可以執行另外的任務 */while (1){if ( __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4))   /* 等待 DMA1_Channel4 傳輸完成 */{__HAL_DMA_CLEAR_FLAG(&g_dma_handle, DMA_FLAG_TC4);HAL_UART_DMAStop(&g_uart1_handle);                  /* 傳輸完成以后關閉串口DMA */break;}pro = DMA1_Channel4->CNDTR; /* 得到當前還剩余多少個數據 */len = SEND_BUF_SIZE;        /* 總長度 */pro = 1 - (pro / len);      /* 得到百分比 */pro *= 100;                 /* 擴大100倍 */lcd_show_num(30, 150, pro, 3, 16, BLUE);} lcd_show_num(30, 150, 100, 3, 16, BLUE);    /* 顯示100% */lcd_show_string(30, 130, 200, 16, 16, "Transimit Finished!", BLUE); /* 提示傳送完成 */}i++;delay_ms(10);if (i == 20){LED0_TOGGLE();  /* LED0閃爍,提示系統正在運行 */i = 0;}}
    }
    
  • 實驗結果


    在這里插入圖片描述

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

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

相關文章

[原創][Delphi多線程]TThreadedQueue的經典使用案例.

[簡介] 常用網名: 豬頭三 出生日期: 1981.XX.XX QQ: 643439947 個人網站: 80x86匯編小站 https://www.x86asm.org 編程生涯: 2001年~至今[共22年] 職業生涯: 20年 開發語言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 開發工具: Visual Studio、Delph…

悉數六大設計原則

悉數六大設計原則 目錄 悉數六大設計原則前言?誰發明了設計模式設計原則設計原則與設計模式的關系 單一職責什么是單一職責不遵循單一職責原則的設計遵循單一職責原則的設計單一職責的優點示例代碼&#xff1a; 里氏替換原則什么是里氏替換原則示例代碼&#xff1a;違反里氏替…

解讀信創產業根基,操作系統發展歷程

信創產業根基之一操作系統 操作系統是一個關鍵的控制程序&#xff0c;負責協調、管理和控制計算機硬件和軟件資源。作為硬件的首要軟件擴展&#xff0c;它位于裸機與用戶之間&#xff0c;充當了兩者之間的橋梁。通過其核心程序&#xff0c;操作系統高效地管理著系統中的各類資源…

static修飾變量和函數

static修飾的變量和函數只能在定義它的cpp源文件中使用&#xff0c;如果在頭文件中定義&#xff0c;則需要注意 在頭文件中定義static變量和static函數&#xff1a; 變量 如果在頭文件中定義了static變量&#xff0c;那么&#xff0c;所有包含這個頭文件的源文件都會定義自己…

vm-bhyve虛擬機安裝ubuntu22版本后進入grub無法啟動

問題&#xff1a;安裝ubuntu22版本后無法啟動 安裝好ubuntu22之后&#xff0c;重啟進入了grub模式&#xff0c;沒有自動啟動ubuntu 網上查了一下&#xff0c;這算一個通病。 問題解決 在grub模式下輸入boot命令&#xff1a; boot (lvm/ubuntu--vg-ubuntu--lv)/boot error: …

有哪些兼職軟件一天能賺幾十元?盤點十個能長期做下去的掙錢軟件

在當今這個信息泛濫的時代&#xff0c;眾人紛紛尋求迅速致富的捷徑。許多人在從事兼職或副業時&#xff0c;并不期望取得巨大的成就&#xff0c;只要每天能額外收入數十元&#xff0c;便已心滿意足。 今天&#xff0c;我將帶領大家深入探究&#xff0c;揭開那些隱藏在日常生活…

【小海實習日記】Git使用規范

1.Git使用流程 1.1 從master分支拉一個分支&#xff0c;命名要符合規范且清晰。 1.2 commit到本地&#xff0c;push 到遠端。 1.3 在Gitlab創建MR&#xff0c;選擇develp分支。 1.4 如果要修改的話&#xff0c;先把Gitlab上的MR修改為Draft(修改態)&#xff0c;然后在本地修改代…

Dubbo中的Invoker與Exporter機制詳解

Dubbo作為一款成熟的高性能、輕量級的Java RPC框架&#xff0c;其核心機制之一便是Invoker與Exporter機制&#xff0c;它們在服務提供端和服務消費端扮演著至關重要的角色&#xff0c;是實現服務調用和管理的基礎。下面將詳細解析這兩個核心組件的工作原理及其在Dubbo框架中的作…

9.1.1 簡述目標檢測領域中的單階段模型和兩階段模型的性能差異及其原因

9.1目標檢測 場景描述 目標檢測&#xff08;Object Detection&#xff09;任務是計算機視覺中極為重要的基礎問題&#xff0c;也是解決實例分割&#xff08;Instance Segmentation&#xff09;、場景理解&#xff08;Scene Understanding&#xff09;、目標跟蹤&#xff08;Ob…

詳解 Spark SQL 代碼開發之用戶自定義函數

一、UDF 一進一出函數 /**語法&#xff1a;SparkSession.udf.register(func_name: String, op: T > K) */ object TestSparkSqlUdf {def main(args: Array[String]): Unit {// 創建 sparksql 環境對象val conf new SparkConf().setMaster("local[*]").setAppNam…

subline text3安裝numpy,scipy,matplotlib,pandas,sklearn,ipynb

1&#xff0c;numpy&#xff08;基礎數值算法&#xff09; 安裝&#xff0c;要是在cmd直接安裝到最后會報錯, import numpy as np ModuleNotFoundError: No module named numpy 直接進入python環境&#xff0c;輸入python -m pip install numpy就不會報錯…

【SringBoot項目中MyBatis-Plus多數據源應用實踐】

文章目錄 前言 一、Mybatis-Plus是什么&#xff1f; 二、多數據源是什么&#xff1f; 三、使用步驟 1. 新建一個SpringBoot項目 2. 引入必要的MyBatis架包 3. 新建兩個數據庫及兩張表 3.3.1 新建數據庫&#xff1a;DB_A&#xff0c;并創建一張數據表alarm_kind&#xff0c;以及…

云端數據提取:安全、高效地利用無限資源

在當今的大數據時代&#xff0c;企業和組織越來越依賴于云平臺存儲和處理海量數據。然而&#xff0c;隨著數據的指數級增長&#xff0c;數據的安全性和高效的數據處理成為了企業最為關心的議題之一。本文將探討云端數據安全的重要性&#xff0c;并提出一套既高效又安全的數據提…

淺測 長亭雷池 WAF “動態防護”

本文首發于 Anyeの小站 前言 雷池 WAF 社區版的更新速度是真快啊&#xff0c;幾乎一周一個小版本&#xff0c;倆月一個大版本&#xff0c;攻城獅們真的狠啊&#xff0c;沒法測了。 廢話不多說&#xff0c;前兩天看到了 這篇文章&#xff0c;對雷池的“動態防護”功能挺感興趣…

Android應用的基本構造及威脅(apk)

目錄 APK文件是什么 apk文件解壓后的目錄結構 apk文件的存儲位置

去掉el-table表頭右側類名是gutter,width=17px的空白區域(包括表頭樣式及表格奇偶行樣式和表格自動滾動)

代碼如下&#xff1a; <el-table:data"tableData"ref"scroll_Table":header-cell-style"getRowClass":cell-style"styleBack"height"350px"style"width: 100%"><el-table-column prop"id" l…

Scrum團隊在迭代中如何處理計劃外的工作

認為 Scrum 團隊不做計劃其實是一個誤區&#xff0c;實際上很多 Scrum 團隊在沖刺計劃會議以及在細化工作項時均會進行詳細規劃。此外&#xff0c;他們還會創建一個路線圖&#xff0c;以便顯示他們在多個沖刺中的計劃。 Scrum 團隊需要經常進行計劃&#xff0c;以便在不斷變化…

linux學習:進程

目錄 例子1 獲取當前進程的進程標識符 例子2 創建一個新的子進程 例子3 展示了父進程和子進程的進程標識符 例子4 區分父進程和子進程 例子5 區分父進程和子進程的行為 例子6 比較進程標識符來區分父進程和子進程 例子7 子進程如何修改一個變量&…

混合動力電動汽車介紹(二)

接續前一章內容&#xff0c;本篇文章介紹混合動力汽車串聯、并聯和混聯的系統組成和工作原理。 一、串聯混合動力電動汽車的系統組成和工作原理 上圖為串聯混合動力電動汽車的結構簡圖。汽車由電動機-發電機驅動行駛&#xff0c;電機控制器的動力來自油箱-發動機-發電機-發電機…

Python 爬蟲零基礎:探索網絡數據的神秘世界

Python 爬蟲零基礎&#xff1a;探索網絡數據的神秘世界 在數字化時代&#xff0c;網絡數據如同無盡的寶藏&#xff0c;等待著我們去發掘。Python爬蟲&#xff0c;作為獲取這些數據的重要工具&#xff0c;正逐漸走進越來越多人的視野。對于零基礎的學習者來說&#xff0c;如何入…