chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

UART需要使用DMA發(fā)送嗎 ?

黃工的嵌入式技術(shù)圈 ? 來源:黃工的嵌入式技術(shù)圈 ? 2020-03-07 16:57 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

DMA一種在嵌入式實時任務(wù)處理中常用的功能。

UART發(fā)送數(shù)據(jù)包,使用DMA方式能大量減輕CPU處理的時間,使其CPU資源不被大量浪費(fèi),尤其在UART收發(fā)大量數(shù)據(jù)包(如高頻率收發(fā)指令)時具有明顯優(yōu)勢。

Ⅰ簡述DMA

DMA:Direct Memory Access,直接內(nèi)存存取/訪問。簡單來說就是內(nèi)存RAM直接和其他設(shè)備(外設(shè))進(jìn)行數(shù)據(jù)交互,而不需要CPU參與的一種控制器。

DMA它允許不同速度的硬件裝置來溝通,而不需要依賴于 CPU 的大量中斷負(fù)載。否則,CPU 需要從來源把每一片段的數(shù)據(jù)復(fù)制到暫存器,然后把它們再次寫回到新的地方。在這個時間中,CPU 對于其他的工作來說就無法使用。

ⅡDMA優(yōu)點

DMA在系統(tǒng)中的角色好比一個公司的員工,CPU好比是公司的老板。

老板想要寄送一個快遞到北京,只需要一個口令安排員工即可,具體填寫快遞單號、物流、派送等一系列工作老板不用關(guān)心。最后快遞被對方收到,通知一聲老板即可。

回到UART發(fā)送數(shù)據(jù),同樣的道理,CPU只需要簡單的操作(類似上面的“安排”),就可把一串?dāng)?shù)據(jù)包丟給DMA直接發(fā)送,最后發(fā)送完成,收到一個發(fā)送完成中斷,通知CPU發(fā)送完成即可。

說到這里相信大部分人都明白了,老板可以親自開車或者坐飛機(jī)送快遞,完成這件事情,但會耽擱老板很多時間。

同樣,如果我們使用UART自己發(fā)送,CPU就會不停仲裁發(fā)送結(jié)果,占據(jù)CPU大量資源。

RTOS中,特別是有大量任務(wù)需要處理的時候,UART使用DMA發(fā)送就會帶來很大方便。使用裸機(jī)運(yùn)行的相同,尤為突出。

ⅢUART使用DMA發(fā)送配置

本文使用STM32F4 MCU、標(biāo)準(zhǔn)外設(shè)庫為例給大家簡單講述一下配置。


1.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 //優(yōu)先級 #define COMM_COM_BaudRate 115200 //波特率 #define COMM_COM_IRQHandler USART2_IRQHandler //中斷函數(shù)接口(見stm32f4xx_it.c)

USART配置:

/************************************************函數(shù)名稱 : USART_COMM_Configuration功 能 : 通信串口配置參 數(shù) : 無返 回 值 : 無作 者 : 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); /* 復(fù)用配置 */ 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; //復(fù)用模式 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; //傳輸位數(shù) 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; //收發(fā)功能 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 }

2.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 //優(yōu)先級 #define COMM_TX_DMA_IRQHandler DMA1_Stream6_IRQHandler //中斷函數(shù)接口(見stm32f4xx_it.c) #define COMM_TX_DMA_IT_TCIF DMA_IT_TCIF6

DMA配置:

/************************************************函數(shù)名稱 : USART_COMM_DMA_Configuration功 能 : 通信串口的DMA配置參 數(shù) : 無返 回 值 : 無作 者 : 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; //外設(shè)地址 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; //內(nèi)存地址(待傳入?yún)?shù)) DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //傳輸方向 DMA_InitStructure.DMA_BufferSize = 0; //傳輸長度(待傳入?yún)?shù)) DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設(shè)遞增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內(nèi)存遞增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //數(shù)據(jù)寬度 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //循環(huán)模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //優(yōu)先級 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); //初始化禁止 } ⅣDMA發(fā)送UART數(shù)據(jù)包

DMA發(fā)送函數(shù):

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

細(xì)心的朋友會發(fā)現(xiàn),這個發(fā)送函數(shù)其實很簡單,當(dāng)然,這里是使用STM32F4芯片,其他芯片也差不多,原理類似。 HAL庫同樣可以完成。

關(guān)于DMA發(fā)送完成中斷,可根據(jù)實際情況,如果使用RTOS,一般發(fā)送數(shù)據(jù)是一個任務(wù),這個任務(wù)會OS等待(檢測)發(fā)送完成信號(即DMA發(fā)送完成中斷)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11218

    瀏覽量

    222972
  • uart
    +關(guān)注

    關(guān)注

    22

    文章

    1304

    瀏覽量

    106123
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    577

    瀏覽量

    105363
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    CW32F030的DMA問題求解

    應(yīng)用很簡單,通過DMAUART接收到的數(shù)據(jù)放到指定的內(nèi)存緩沖區(qū)rx_buffer[]. 每次接收8個字節(jié)數(shù)據(jù),下一次數(shù)據(jù)覆蓋上一次. 這個過程本來可以無需CPU參與自動完成.無論串口發(fā)送的快慢都
    發(fā)表于 12-08 08:07

    UART無法收發(fā)/亂碼的排查

    了嗎?共地了嗎? 3、引腳復(fù)用: 確認(rèn)使用的 UART 引腳配置正確,且復(fù)用功能已開啟。 4、中斷/DMA: 如果使用中斷或 DMA,相關(guān)配置和使能是否正確? 5、電平轉(zhuǎn)換: 如果需要
    發(fā)表于 11-18 07:05

    哪些場景適合使用DMA?

    。 串行通信(UART,SPI,I2C等): UART:在大量數(shù)據(jù)收發(fā)時,例如通過串口接收一幀數(shù)據(jù)或發(fā)送一幀數(shù)據(jù),可以使用DMA來搬運(yùn)數(shù)據(jù)。比如,使用
    發(fā)表于 11-12 07:13

    RVMCU課堂「18」: 手把手教你玩轉(zhuǎn)RVSTAR—DMA數(shù)據(jù)傳輸篇

    _init()和uart_send()實現(xiàn)的完整代碼工程,請參考文末附帶鏈接)。 代碼編寫完成后,需要編譯并上傳到開發(fā)板,然后需要使用一個類似下圖所示的TTL-USB串口轉(zhuǎn)換器,將RV-STAR的
    發(fā)表于 10-30 08:29

    UART指令控制RGB燈實驗

    保證開發(fā)板相關(guān)硬件連接正確,用Type-C USB線連接開發(fā)板“USB TO UART”接口跟電腦。本次實驗需要使用到串口調(diào)試助手,配置好串口參數(shù)并打開串口后,在調(diào)試助手的發(fā)送區(qū)域輸入任意字符并點擊
    的頭像 發(fā)表于 10-27 11:26 ?1929次閱讀
    <b class='flag-5'>UART</b>指令控制RGB燈實驗

    串口DMA發(fā)送有緩存嗎?

    串口DMA發(fā)送有緩存嗎, 我是從ringbuffer取出來,放到申請的緩存里,啟動串口DMA發(fā)送,然后就釋放了。暫時沒發(fā)現(xiàn)什么問題。 用的drv_usart.c是這個版本
    發(fā)表于 10-10 06:14

    串口DMA發(fā)送數(shù)據(jù)一直發(fā)不出來是怎么回事?

    , buf, size) == HAL_OK) { return size; } else { return 0; } } return 0; } 仿真只有發(fā)送第一次的時候調(diào)用了HAL_UART_Transmit_DMA()函數(shù),而且返回HAL_OK,但是就是沒數(shù)
    發(fā)表于 10-09 07:01

    finsh 控制臺dma發(fā)送如何操作?

    今天因為在高優(yōu)先級線程中頻繁調(diào)用rt_kprintf導(dǎo)致低優(yōu)先級運(yùn)行阻塞,所以突發(fā)奇想想試試控制臺能不能dma發(fā)送,在保證對應(yīng)uart tx dma的驅(qū)動打開后,rt_device_o
    發(fā)表于 09-11 07:48

    STM32H743 UART DMA接收不到數(shù)據(jù)是為什么?

    ;find %s failed!n\", \"uart3\"); return RT_ERROR; } /* 以 DMA 接收及輪詢發(fā)送方式打開串口設(shè)備
    發(fā)表于 09-11 07:14

    SPI主機(jī)/從機(jī)接收發(fā)送都開啟DMA通信

    發(fā)送;SPI 作為從機(jī)時,接收和發(fā)送同時開啟 DMA 進(jìn)行數(shù)據(jù)接收和發(fā)送。 注:本應(yīng)用筆記對應(yīng)的代碼是基于雅特力提供的V2.x.x 板級支持包(BSP)而開發(fā),對于其他版本BSP,
    發(fā)表于 09-10 16:56

    串口DMA發(fā)送失敗的原因?怎么解決?

    我想使用DMA發(fā)送,但是出現(xiàn)了發(fā)送不出去,但是發(fā)送完成回調(diào)函數(shù)它是能進(jìn)去的,打印出里面的內(nèi)容,接收數(shù)據(jù)是沒問題,這是為什么呢?有大佬指點一下嗎 #include #include
    發(fā)表于 08-15 06:21

    XMC7100 F100K4160AA Uart2 dma實例程序無法運(yùn)行,使用hal驅(qū)動發(fā)送丟字符并且無法接收怎么解決?

    問題1:修改SCB UART DMA Echo實例程序引腳和dma通道配置正常運(yùn)行后,無法按照實例設(shè)計功能接收和顯示。 問題2:使用hal驅(qū)動方式,能正常發(fā)送數(shù)據(jù),但經(jīng)常丟字符,添加
    發(fā)表于 08-13 06:23

    為什么無法使用Lpuart_Uart_Ip_ 發(fā)送任何數(shù)據(jù)回調(diào)中的AsyncSend?

    我已經(jīng)實現(xiàn)了基于 LPUART 的 DMA ,我可以發(fā)送使用 Lpuart_Uart_Ip_ 接收的數(shù)據(jù)同步發(fā)送 in lpuart_6_callback , 但是,我無法
    發(fā)表于 04-11 07:51

    DMA發(fā)送函數(shù)只能被調(diào)用一次是怎么回事?

    逐步debug DMA發(fā)送函數(shù),HAL_UART Transmit DMA,發(fā)現(xiàn)函數(shù)會對串口句柄的一個狀態(tài)位,gState 進(jìn)行判斷,只有在 huart->gState==HAL
    發(fā)表于 03-12 07:37

    STM32H743 UART DMA接收不到數(shù)據(jù),為什么?

    failed!\\n\", \"uart3\"); return RT_ERROR; } /* 以 DMA 接收及輪詢發(fā)送方式打開串口設(shè)備
    發(fā)表于 02-19 06:14