LPC5500的SDK中提供了非常豐富的串口例程(如下圖所示):
但是,偏偏沒(méi)有串口DMA發(fā)送+中斷接收這種組合。
實(shí)話(huà)說(shuō)小編覺(jué)得這種組合才是大部分MCU場(chǎng)景中最常用的。尤其是對(duì)一些RX數(shù)據(jù)量不大(比如只是解析一些命令)但是TX數(shù)據(jù)量大的應(yīng)用(比如定時(shí),高頻發(fā)送數(shù)據(jù))再合適不過(guò),該架構(gòu)模型簡(jiǎn)單,非常容易理解。
本篇文章就手把手教大家分分鐘擼一個(gè)DMA發(fā)送+中斷接收的例程:
我們復(fù)制一個(gè)dma_transfer例程作為模板,重命名為dma_tx_int_rx(名字無(wú)所謂,自己起即可)。打開(kāi),編譯下載運(yùn)行一下,確保原版demo在自己的板子上可以順利的運(yùn)行,咱們把前期工作都鋪墊好。
下面我們開(kāi)始改代碼:dma_transfer原版代碼是TX和RX都是dma傳輸,我們只需要將RX改為中斷接收數(shù)據(jù)即可。
首先將USART_TransferCreateHandleDMA函數(shù)修改下,將所有RX DMA有關(guān)的東西去掉,handler填NULL就可以。這樣usart_dmadriver就不會(huì)處理RX DMA有關(guān)的操作了:
USART_TransferCreateHandleDMA(DEMO_USART, &g_uartDmaHandle, USART_UserCallback, NULL,&g_uartTxDmaHandle, NULL);
2. 開(kāi)啟usart RX中斷,沒(méi)啥可說(shuō)的,常規(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:%c ", 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。這是仿照f(shuō)sl_usart_dma.c中的寫(xiě)法(fsl_usart_dma中開(kāi)啟了TXIDLE中斷,并使用TXIDLE中斷來(lái)調(diào)用dma handle用戶(hù)回調(diào)函數(shù),現(xiàn)在硬件串口中斷已經(jīng)被app層接管,所以我們同樣要實(shí)現(xiàn)這部分功能)。
4. 測(cè)試:改好代碼,下載運(yùn)行:當(dāng)串口敲入任意鍵時(shí)候,程序都會(huì)回顯接收到數(shù)據(jù),當(dāng)按鍵”s”時(shí),會(huì)調(diào)用USART_TransferSendDMA函數(shù)使用DMA發(fā)送一串?dāng)?shù)據(jù),并進(jìn)入DMA發(fā)送完成回調(diào)函數(shù)。
代碼清單
以下是完整代碼清單(可以直接復(fù)制到usart_dma_transfer.c里運(yùn)行):
/* * 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_DMA ";
#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%X ", 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:%c ", 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 INTERRUPT ");
PRINTF("press 's' for DMA TX tranmsit ");
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);
while(1);
}
原文標(biāo)題:LPC5500_SDK例程:串口DMA發(fā)送+中斷接收
文章出處:【微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
串口
+關(guān)注
關(guān)注
14文章
1554瀏覽量
76516 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4331瀏覽量
62618 -
dma
+關(guān)注
關(guān)注
3文章
561瀏覽量
100586 -
接收數(shù)據(jù)
+關(guān)注
關(guān)注
0文章
7瀏覽量
6086
原文標(biāo)題:LPC5500_SDK例程:串口DMA發(fā)送+中斷接收
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論