<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

串口DMA其實一點兒都不難

朱老師物聯網大講堂 ? 2024-04-29 08:10 ? 次閱讀

DMA一種在嵌入式實時任務處理中常用的功能。而UART發送數據包,使用DMA方式能大量減輕CPU處理的時間,使其CPU資源不被大量浪費,尤其在UART收發大量數據包(如高頻率收發指令)時具有明顯優勢。

一、簡述DMA

ecb153ba-05bc-11ef-9118-92fbcf53809c.pngDMA:Direct Memory Access,直接內存存取/訪問。簡單來說就是內存RAM直接和其他設備(外設)進行數據交互,而不需要CPU參與的一種控制器。DMA它允許不同速度的硬件裝置來溝通,而不需要依賴于 CPU 的大量中斷負載。否則,CPU 需要從來源把每一片段的數據復制到緩存器,然后把它們再次寫回到新的地方。在這個過程中,CPU不能做其他的工作。

二、DMA的優點

ecb153ba-05bc-11ef-9118-92fbcf53809c.pngDMA在系統中的角色好比一個公司的員工,CPU好比是公司的老板?;氐経ART發送數據,同樣的道理,CPU只需要簡單的操作(“安排任務”),就可把一串數據包丟給DMA直接發送,最后發送完成,收到一個發送完成中斷,通知CPU發送完成即可。說到這里相信大部分人都明白了,老板可以親自開車或者坐飛機送快遞,完成這件事情,但會耽擱老板很多時間。同樣,如果我們使用UART自己發送,CPU就會不停仲裁發送結果,占據CPU大量資源。在RTOS中,特別是有大量任務需要處理的時候,UART使用DMA發送就會帶來很大方便。使用裸機運行的相同,尤為突出。

三、實例代碼:DMA發送配置

ecb153ba-05bc-11ef-9118-92fbcf53809c.png本文使用STM32F4 MCU、標準外設庫為例給大家簡單講述一下配置。

01

USART配置

USART(COM)宏定義:

/* COMM通信 */#define COMM_COM USART2#define COMM_COM_CLK RCC_APB1Periph_USART2#define COMM_COM_TX_GPIO_CLK RCC_AHB1Periph_GPIOD //UART TX#define COMM_COM_TX_PIN GPIO_Pin_5#define COMM_COM_TX_GPIO_PORT GPIOD#define COMM_COM_TX_SOURCE GPIO_PinSource5#define COMM_COM_TX_AF GPIO_AF_USART2#define COMM_COM_RX_GPIO_CLK RCC_AHB1Periph_GPIOD //UART RX#define COMM_COM_RX_PIN GPIO_Pin_6#define COMM_COM_RX_GPIO_PORT GPIOD#define COMM_COM_RX_SOURCE GPIO_PinSource6#define COMM_COM_RX_AF GPIO_AF_USART2#define COMM_COM_IRQn USART2_IRQn#define COMM_COM_Priority 9 //優先級#define COMM_COM_BaudRate 115200 //波特率#define COMM_COM_IRQHandler USART2_IRQHandler //中斷函數接口(見stm32f4xx_it.c)

USART配置:

/************************************************函數名稱 :USART_COMM_Configuration功 能 :通信串口配置參 數 :無返 回 值 :無作 者 :strongerHuang*************************************************/void USART_COMM_Configuration(void){ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
/* 時鐘配置 */ RCC_AHB1PeriphClockCmd(COMM_COM_TX_GPIO_CLK | COMM_COM_RX_GPIO_CLK, ENABLE); if((USART1 == COMM_COM) || (USART6 == COMM_COM)) RCC_APB2PeriphClockCmd(COMM_COM_CLK, ENABLE); else RCC_APB1PeriphClockCmd(COMM_COM_CLK, ENABLE);
/* 復用配置 */ GPIO_PinAFConfig(COMM_COM_TX_GPIO_PORT, COMM_COM_TX_SOURCE, COMM_COM_TX_AF); GPIO_PinAFConfig(COMM_COM_RX_GPIO_PORT, COMM_COM_RX_SOURCE, COMM_COM_RX_AF);
/* 引腳配置 */ GPIO_InitStructure.GPIO_Pin = COMM_COM_TX_PIN; //USART Tx GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(COMM_COM_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = COMM_COM_RX_PIN; //USART Rx GPIO_Init(COMM_COM_RX_GPIO_PORT, &GPIO_InitStructure);
/* NVIC配置 */ NVIC_InitStructure.NVIC_IRQChannel = COMM_COM_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_COM_Priority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
/* USART配置 */ USART_InitStructure.USART_BaudRate = COMM_COM_BaudRate; //波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //傳輸位數 USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位 USART_InitStructure.USART_Parity = USART_Parity_No ; //校驗位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發功能 USART_Init(COMM_COM, &USART_InitStructure);
USART_ClearFlag(COMM_COM, USART_FLAG_RXNE | USART_FLAG_TC); USART_ITConfig(COMM_COM, USART_IT_RXNE, ENABLE); //接收中斷
USART_DMACmd(COMM_COM, USART_DMAReq_Tx, ENABLE); //使能DMA
USART_Cmd(COMM_COM, ENABLE); //使能USART}


02

DMA配置

DMA宏定義:

/* COMM_DMA */#define COMM_DR_ADDRESS ((uint32_t)USART2 + 0x04)#define COMM_DMA DMA1#define COMM_DMA_CLK RCC_AHB1Periph_DMA1#define COMM_TX_DMA_CHANNEL DMA_Channel_4#define COMM_TX_DMA_STREAM DMA1_Stream6#define COMM_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF6#define COMM_TX_DMA_IRQn DMA1_Stream6_IRQn#define COMM_TX_DMA_Priority 8 //優先級#define COMM_TX_DMA_IRQHandler DMA1_Stream6_IRQHandler //中斷函數接口(見stm32f4xx_it.c)#define COMM_TX_DMA_IT_TCIF DMA_IT_TCIF6

DMA配置:

/************************************************函數名稱 :USART_COMM_DMA_Configuration功 能 :通信串口的DMA配置參 數 :無返 回 值 :無作 者 :strongerHuang*************************************************/void USART_COMM_DMA_Configuration(void){ DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
/* 使能時鐘 */ RCC_AHB1PeriphClockCmd(COMM_DMA_CLK, ENABLE);
/* NVIC配置 */ NVIC_InitStructure.NVIC_IRQChannel = COMM_TX_DMA_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_TX_DMA_Priority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
/* DMA配置 */ DMA_DeInit(COMM_TX_DMA_STREAM); DMA_InitStructure.DMA_Channel = COMM_TX_DMA_CHANNEL; //DMA通道 DMA_InitStructure.DMA_PeripheralBaseAddr = COMM_DR_ADDRESS; //外設地址 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; //內存地址(待傳入參數) DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //傳輸方向 DMA_InitStructure.DMA_BufferSize = 0; //傳輸長度(待傳入參數) DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設遞增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存遞增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //數據寬度 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //循環模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //優先級 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(COMM_TX_DMA_STREAM, &DMA_InitStructure);
DMA_ClearFlag(COMM_TX_DMA_STREAM, COMM_TX_DMA_FLAG_TCIF); DMA_ITConfig(COMM_TX_DMA_STREAM, DMA_IT_TC, ENABLE); //使能DMA傳輸完成中斷
DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE); //初始化禁止}

03

DMA發送UART數據包

DMA發送函數:

/************************************************函數名稱 :COMM_SendBufByDMA功 能 :通信串口通過DMA發送數據參 數 :Buf ------ 數據(地址) Length --- 數據長度(字節)返 回 值 :無作 者 :strongerHuang*************************************************/void COMM_SendBufByDMA(uint8_t *Buf, uint16_t Length){ DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE); //關閉DMA //內存地址 DMA_MemoryTargetConfig(COMM_TX_DMA_STREAM, (uint32_t)Buf, DMA_Memory_0); DMA_SetCurrDataCounter(COMM_TX_DMA_STREAM, Length); //設置DMA傳輸長度 DMA_Cmd(COMM_TX_DMA_STREAM, ENABLE); //使能DMA}

細心的朋友會發現,這個發送函數其實很簡單,當然,這里是使用STM32F4芯片,其他芯片也差不多,原理類似。HAL庫同樣可以完成。
關于DMA發送完成中斷,可根據實際情況,如果使用RTOS,一般發送數據是一個任務,這個任務會OS等待(檢測)發送完成信號(即DMA發送完成中斷)。

本文轉載自公眾號|strongerHuang

如有侵權 |聯系刪除

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 串口
    +關注

    關注

    14

    文章

    1484

    瀏覽量

    74525
  • dma
    dma
    +關注

    關注

    3

    文章

    536

    瀏覽量

    99062
  • 數據包
    +關注

    關注

    0

    文章

    231

    瀏覽量

    24095
收藏 人收藏

    評論

    相關推薦

    stm32 adc1和串口2同時使用DMA出錯的原因?

    stm32f103r8t6adc1使用dma方式采集數據串口2使用dma方式收發串口發送沒有問題,串口接收只要adc1使用
    發表于 04-22 08:08

    用CUBE生成的freertos LWIP串口DMA程序不能正常運行怎么解決?

    frrertosconfig.h里面有個 #define configTOTAL_HEAP_SIZE((size_t)50000),如果這個值定義成47104就可以正常使用串口收發DMA,但是LWIP就PING不通了,這個值改大一點
    發表于 04-15 06:35

    dma串口直接發送的區別

    DMA(Direct Memory Access)和串口直接發送是兩種不同的數據傳輸方式,它們在實現上有著明顯的區別和優劣勢。本文將詳細介紹DMA串口直接發送的原理、優缺點以及適用場
    的頭像 發表于 01-07 17:43 ?1281次閱讀

    LPC5500_SDK例程:串口DMA發送+中斷接收

    LPC5500_SDK例程:串口DMA發送+中斷接收
    的頭像 發表于 10-30 16:59 ?527次閱讀
    LPC5500_SDK例程:<b class='flag-5'>串口</b><b class='flag-5'>DMA</b>發送+中斷接收

    STM32串口中斷及DMA接收常見的幾個問題

    STM32串口中斷及DMA接收常見的幾個問題
    的頭像 發表于 10-26 16:41 ?2551次閱讀
    STM32<b class='flag-5'>串口</b>中斷及<b class='flag-5'>DMA</b>接收常見的幾個問題

    一個嚴謹的STM32串口DMA發送&amp;接收(1.5Mbps波特率)機制

    一個嚴謹的STM32串口DMA發送&接收(1.5Mbps波特率)機制
    的頭像 發表于 09-18 10:58 ?1719次閱讀
    一個嚴謹的STM32<b class='flag-5'>串口</b><b class='flag-5'>DMA</b>發送&amp;接收(1.5Mbps波特率)機制

    DMA 串口傳輸原理解析

    從這個角度來說,DMA 并沒有加快串口本身的傳輸速度,只是解放了 CPU 資源而已。但是 CPU 被解放了, DMA 所使用的 緩存 資源可不能也隨之解放呀,只能等發送完畢后才能釋放。所以最簡單的方法是在 緩存 前面加一個 st
    發表于 09-16 10:04 ?1012次閱讀
    <b class='flag-5'>DMA</b> <b class='flag-5'>串口</b>傳輸原理解析

    搗鼓了兩晚上終于讓這塊鬼屏幕出字兒了時序這東西真是差一點兒都不給好臉色看。。。

    電源電壓電路原理
    學習電子知識
    發布于 :2023年08月15日 21:54:33

    STM32F103單片機學習筆記(5):DMA

    外部中斷觸發時,DMA串口發送一次數據。
    發表于 07-21 15:46 ?760次閱讀
    STM32F103單片機學習筆記(5):<b class='flag-5'>DMA</b>

    看完后,搞懂開關電源設計的這些指標一點都不難!

    中國一般是220V,由于電網電壓的不穩定,很多時候要求寬電壓輸入,所以會設計成90-270V都能正常工作。通常美國用電范圍為110-130V,日本用電范圍為100V。
    發表于 07-11 16:49 ?931次閱讀

    銜尾法解決當無法使用空閑中斷以及DMA中斷時配置DMA接收串口不定長數據

    [Ooonly新人貼]記錄工作中遇到的問題,話不多說先上干貨 問題:類似K線與藍牙接收模塊,要求由原來的接收串口中斷改為DMA接收。據說要用到空閑中斷與DMA中斷,但是經仿真發現DMA
    發表于 06-19 09:32

    STM32實例教程-DMA實驗

    在前面我們提到過 DMA,這一章我們就來學習 STM32F1 的DMA 使用。要實現的功能是:通過 K_UP 按鍵控制 DMA 串口 1 數據的傳送,在傳送過程中讓 D2 指示燈不斷閃
    發表于 05-24 09:20 ?774次閱讀
    STM32實例教程-<b class='flag-5'>DMA</b>實驗

    如何Reverse Engineer張40年前的原理圖...

    比如說下面這個圖... 只有張圖片,沒有原始的EDA文件: 唯的方法是重新繪制... 但通過合理的方法,可以讓這個過程輕松一點兒... 具體方式參見視頻...
    發表于 05-22 19:47

    STM32采用串口DMA方式向上位機連續發送數據

    完成1.3DMA庫函數配置過程二、串口DMA方式向上位機發送數據2.1新建工程2.2設置RCC?2.3打開USART1及DMA模式??三、代碼編寫3.1添加代碼?3.2編譯運行?四、
    發表于 05-11 09:32 ?2次下載
    STM32采用<b class='flag-5'>串口</b><b class='flag-5'>DMA</b>方式向上位機連續發送數據

    采用串口DMA方式向上位機連續發送數據的實例解析

    本文主要講解采用串口DMA方式,用115200bps或更高速率向上位機連續發送數據。采用STM32采用串口DMA方式,用115200bps或更高速率向上位機連續發送數據。 所需工具:
    發表于 05-09 10:44 ?0次下載
    采用<b class='flag-5'>串口</b><b class='flag-5'>DMA</b>方式向上位機連續發送數據的實例解析
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>