LPC5500
串口DMA
LPC5500的SDK中提供了非常豐富的串口例程(如下圖所示):
但是,偏偏沒有串口DMA發(fā)送+中斷接收這種組合。
實話說小編覺得這種組合才是大部分MCU場景中最常用的。尤其是對一些RX數(shù)據(jù)量不大(比如只是解析一些命令)但是TX數(shù)據(jù)量大的應(yīng)用(比如定時,高頻發(fā)送數(shù)據(jù))再合適不過,該架構(gòu)模型簡單,非常容易理解。
本篇文章就手把手教大家分分鐘擼一個DMA發(fā)送+中斷接收的例程:
我們復(fù)制一個dma_transfer例程作為模板,重命名為dma_tx_int_rx(名字無所謂,自己起即可)。打開,編譯下載運行一下,確保原版demo在自己的板子上可以順利的運行,咱們把前期工作都鋪墊好。
下面我們開始改代碼:dma_transfer原版代碼是TX和RX都是dma傳輸,我們只需要將RX改為中斷接收數(shù)據(jù)即可。
首先將USART_TransferCreateHandleDMA函數(shù)修改下,將所有RX DMA有關(guān)的東西去掉,handler填NULL就可以。這樣usart_dma driver就不會處理RX DMA有關(guān)的操作了:
USART_TransferCreateHandleDMA(DEMO_USART, g_uartDmaHandle, USART_UserCallback, NULL, g_uartTxDmaHandle, NULL);
2. 開啟usart RX中斷,沒啥可說的,常規(guī)操作:
/* Enable RX interrupt. */ USART_EnableInterrupts(DEMO_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable); EnableIRQ(DEMO_USART_IRQn);
3. 在app層定義(接管)串口硬件中斷,并在中斷中處理串口RX接收到的數(shù)據(jù):
#define DEMO_USART_IRQHandler FLEXCOMM0_IRQHandler #define DEMO_USART_IRQn FLEXCOMM0_IRQn void DEMO_USART_IRQHandler(void) { uint8_t data; /* If new data arrived. */ if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError | kUSART_RxFifoFullFlag) USART_GetStatusFlags(DEMO_USART)) { data = USART_ReadByte(DEMO_USART); PRINTF("usart rx interrupt:%crn", data); if(data == 's') { /* Send g_tipString out. */ xfer.data = g_tipString; xfer.dataSize = sizeof(g_tipString) - 1; g_uartDmaHandle.txState = kUSART_TxIdle; USART_TransferSendDMA(DEMO_USART, g_uartDmaHandle, xfer); } } if ((0U != (DEMO_USART->INTENSET USART_INTENSET_TXIDLEEN_MASK)) (0U != (DEMO_USART->INTSTAT USART_INTSTAT_TXIDLE_MASK))) { USART_TransferDMAHandleIRQ(DEMO_USART, g_uartDmaHandle); } }
注意,這里需要在硬件串口中斷里判斷TXIDLE中斷,并調(diào)用USART_TransferDMAHandleIRQ。這是仿照fsl_usart_dma.c中的寫法(fsl_usart_dma中開啟了TXIDLE中斷,并使用TXIDLE中斷來調(diào)用dma handle用戶回調(diào)函數(shù),現(xiàn)在硬件串口中斷已經(jīng)被app層接管,所以我們同樣要實現(xiàn)這部分功能)。
4. 測試:改好代碼,下載運行:當(dāng)串口敲入任意鍵時候,程序都會回顯接收到數(shù)據(jù),當(dāng)按鍵”s”時,會調(diào)用USART_TransferSendDMA函數(shù)使用DMA發(fā)送一串?dāng)?shù)據(jù),并進入DMA發(fā)送完成回調(diào)函數(shù)。
代碼清單
以下是完整代碼清單(可以直接復(fù)制到usart_dma_transfer.c里運行):
/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "pin_mux.h" #include "board.h" #include "fsl_usart.h" #include "fsl_usart_dma.h" #include "fsl_dma.h" #include "fsl_debug_console.h" #include #include "fsl_power.h" #define DEMO_USART USART0 #define DEMO_USART_CLK_SRC kCLOCK_Flexcomm0 #define DEMO_USART_CLK_FREQ CLOCK_GetFlexCommClkFreq(0U) #define USART_RX_DMA_CHANNEL 4 #define USART_TX_DMA_CHANNEL 5 #define EXAMPLE_UART_DMA_BASEADDR DMA0 #define DEMO_USART_IRQHandler FLEXCOMM0_IRQHandler #define DEMO_USART_IRQn FLEXCOMM0_IRQn #define ECHO_BUFFER_LENGTH 8 usart_transfer_t xfer; usart_dma_handle_t g_uartDmaHandle; dma_handle_t g_uartTxDmaHandle; uint8_t g_tipString[] = "This string is send from UART_DMArn"; #define kUSART_TxIdle 0 void USART_UserCallback(USART_Type *base, usart_dma_handle_t *handle, status_t status, void *userData) { userData = userData; if (kStatus_USART_TxIdle == status) { PRINTF("USART_UserCallback, status:0x%Xrn", status); } } void DEMO_USART_IRQHandler(void) { uint8_t data; /* If new data arrived. */ if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError | kUSART_RxFifoFullFlag) USART_GetStatusFlags(DEMO_USART)) { data = USART_ReadByte(DEMO_USART); PRINTF("usart rx interrupt:%crn", data); if(data == 's') { /* Send g_tipString out. */ xfer.data = g_tipString; xfer.dataSize = sizeof(g_tipString) - 1; g_uartDmaHandle.txState = kUSART_TxIdle; USART_TransferSendDMA(DEMO_USART, g_uartDmaHandle, xfer); } } if ((0U != (DEMO_USART->INTENSET USART_INTENSET_TXIDLEEN_MASK)) (0U != (DEMO_USART->INTSTAT USART_INTSTAT_TXIDLE_MASK))) { USART_TransferDMAHandleIRQ(DEMO_USART, g_uartDmaHandle); } } int main(void) { usart_config_t config; /* set BOD VBAT level to 1.65V */ POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false); /* attach 12 MHz clock to FLEXCOMM0 (debug console) */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0); BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); PRINTF("USART: TX DMA, RX INTERRUPTrn"); PRINTF("press 's' for DMA TX tranmsitrn"); USART_GetDefaultConfig( config); config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE; config.enableTx = true; config.enableRx = true; USART_Init(DEMO_USART, config, DEMO_USART_CLK_FREQ); /* Configure DMA. */ DMA_Init(EXAMPLE_UART_DMA_BASEADDR); DMA_EnableChannel(EXAMPLE_UART_DMA_BASEADDR, USART_TX_DMA_CHANNEL); DMA_EnableChannel(EXAMPLE_UART_DMA_BASEADDR, USART_RX_DMA_CHANNEL); DMA_CreateHandle( g_uartTxDmaHandle, EXAMPLE_UART_DMA_BASEADDR, USART_TX_DMA_CHANNEL); USART_TransferCreateHandleDMA(DEMO_USART, g_uartDmaHandle, USART_UserCallback, NULL, g_uartTxDmaHandle, NULL); /* Send g_tipString out. */ xfer.data = g_tipString; xfer.dataSize = sizeof(g_tipString) - 1; USART_TransferSendDMA(DEMO_USART, g_uartDmaHandle, xfer); /* Enable RX interrupt. */ USART_EnableInterrupts(DEMO_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable); EnableIRQ(DEMO_USART_IRQn);
來源:恩智浦MCU加油站
審核編輯:湯梓紅
-
中斷
+關(guān)注
關(guān)注
5文章
898瀏覽量
41495 -
串口
+關(guān)注
關(guān)注
14文章
1554瀏覽量
76512 -
dma
+關(guān)注
關(guān)注
3文章
561瀏覽量
100584 -
SDK
+關(guān)注
關(guān)注
3文章
1036瀏覽量
45936
發(fā)布評論請先 登錄
相關(guān)推薦
如何使用DMA的方式進行串口的發(fā)送與接收
stm32串口dma發(fā)送/接收程序
![stm32<b class='flag-5'>串口</b><b class='flag-5'>dma</b><b class='flag-5'>發(fā)送</b>/<b class='flag-5'>接收</b>程序](https://file1.elecfans.com//web2/M00/A6/F7/wKgZomUMQYeAH3sCAAAw8JSLS0c710.png)
PWM使用的DMA通道與串口接收的DMA通道撞車了,咋辦?
![PWM使用的<b class='flag-5'>DMA</b>通道與<b class='flag-5'>串口</b><b class='flag-5'>接收</b>的<b class='flag-5'>DMA</b>通道撞車了,咋辦?](http://mcu.eetrend.com/files/2020-11/博客/100059078-113575-x1.png)
STM32 串口使用IDLE中斷+DMA接收(HAL庫函數(shù))
![STM32 <b class='flag-5'>串口</b>使用IDLE<b class='flag-5'>中斷</b>+<b class='flag-5'>DMA</b><b class='flag-5'>接收</b>(HAL庫函數(shù))](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32 HAL CubeMX 串口IDLE接收空閑中斷+DMA
![STM32 HAL CubeMX <b class='flag-5'>串口</b>IDLE<b class='flag-5'>接收</b>空閑<b class='flag-5'>中斷</b>+<b class='flag-5'>DMA</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32—無需中斷來實現(xiàn)使用DMA接收串口數(shù)據(jù)
![STM32—無需<b class='flag-5'>中斷</b>來實現(xiàn)使用<b class='flag-5'>DMA</b><b class='flag-5'>接收</b><b class='flag-5'>串口</b>數(shù)據(jù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32DMA+串口完成中斷 接收和發(fā)送
![STM32<b class='flag-5'>DMA</b>+<b class='flag-5'>串口</b>完成<b class='flag-5'>中斷</b> <b class='flag-5'>接收</b>和<b class='flag-5'>發(fā)送</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
stm32 發(fā)送完數(shù)據(jù)后 串口繼續(xù)發(fā)送_STM32之串口DMA接收不定長數(shù)據(jù)
![stm32 <b class='flag-5'>發(fā)送</b>完數(shù)據(jù)后 <b class='flag-5'>串口</b>繼續(xù)<b class='flag-5'>發(fā)送</b>_STM32之<b class='flag-5'>串口</b><b class='flag-5'>DMA</b><b class='flag-5'>接收</b>不定長數(shù)據(jù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32單片機串口空閑中斷+DMA接收不定長數(shù)據(jù)
![STM32單片機<b class='flag-5'>串口</b>空閑<b class='flag-5'>中斷</b>+<b class='flag-5'>DMA</b><b class='flag-5'>接收</b>不定長數(shù)據(jù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
單片機接收不定長的數(shù)據(jù),最優(yōu)解是DMA+串口空閑中斷
![單片機<b class='flag-5'>接收</b>不定長的數(shù)據(jù),最優(yōu)解是<b class='flag-5'>DMA</b>+<b class='flag-5'>串口</b>空閑<b class='flag-5'>中斷</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論