0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

串口DMA发送+中断接收的例程

恩智浦MCU加油站 来源:恩智浦MCU加油站 作者:恩智浦MCU加油站 2022-07-21 09:14 次阅读

LPC5500的SDK中提供了非常丰富的串口例程(如下图所示):

264e7c58-088d-11ed-ba43-dac502259ad0.png

但是,偏偏没有串口DMA发送+中断接收这种组合。

实话说小编觉得这种组合才是大部分MCU场景中最常用的。尤其是对一些RX数据量不大(比如只是解析一些命令)但是TX数据量大的应用(比如定时,高频发送数据)再合适不过,该架构模型简单,非常容易理解。

本篇文章就手把手教大家分分钟撸一个DMA发送+中断接收的例程:

我们复制一个dma_transfer例程作为模板,重命名为dma_tx_int_rx(名字无所谓,自己起即可)。打开,编译下载运行一下,确保原版demo在自己的板子上可以顺利的运行,咱们把前期工作都铺垫好。

下面我们开始改代码:dma_transfer原版代码是TX和RX都是dma传输,我们只需要将RX改为中断接收数据即可。

  1. 首先将USART_TransferCreateHandleDMA函数修改下,将所有RX DMA有关的东西去掉,handler填NULL就可以。这样usart_dmadriver就不会处理RX DMA有关的操作了:


		

USART_TransferCreateHandleDMA(DEMO_USART, &g_uartDmaHandle, USART_UserCallback, NULL,&g_uartTxDmaHandle, NULL);

2. 开启usart RX中断,没啥可说的,常规操作:


		

/* Enable RX interrupt. */ USART_EnableInterrupts(DEMO_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable); EnableIRQ(DEMO_USART_IRQn);

3. 在app层定义(接管)串口硬件中断,并在中断中处理串口RX接收到的数据:

		

#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中断,并调用USART_TransferDMAHandleIRQ。这是仿照fsl_usart_dma.c中的写法(fsl_usart_dma中开启了TXIDLE中断,并使用TXIDLE中断来调用dma handle用户回调函数,现在硬件串口中断已经被app层接管,所以我们同样要实现这部分功能)。

4. 测试:改好代码,下载运行:当串口敲入任意键时候,程序都会回显接收到数据,当按键”s”时,会调用USART_TransferSendDMA函数使用DMA发送一串数据,并进入DMA发送完成回调函数。

2664fad2-088d-11ed-ba43-dac502259ad0.png

代码清单

以下是完整代码清单(可以直接复制到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_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);

}

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17141

    浏览量

    351101
  • 串口
    +关注

    关注

    14

    文章

    1551

    浏览量

    76483
  • dma
    dma
    +关注

    关注

    3

    文章

    561

    浏览量

    100563
收藏 人收藏

    评论

    相关推荐

    CH32V307有对应的串口+DMA传输中断接收,主动发送的例子吗?

    官方给的例程串口+DMA 好像只是一个简单的演示,请问有对应的 串口+DMA 传输 中断
    发表于 06-20 06:01

    stm32串口dma发送/接收程序

    串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何
    发表于 11-27 09:41 3w次阅读
    stm32<b class='flag-5'>串口</b><b class='flag-5'>dma</b><b class='flag-5'>发送</b>/<b class='flag-5'>接收</b>程序

    串口中断接收发送的C51程序免费下载

    这是一个单片机C51串口接收中断)和发送例程,可以用来测试51单片机的中断
    发表于 04-25 18:27 4次下载
    <b class='flag-5'>串口中断</b><b class='flag-5'>接收</b>和<b class='flag-5'>发送</b>的C51程序免费下载

    STM32串口中断 DMA接收的几点注意地方

    STM32串口中断DMA接收的几点注意地方
    的头像 发表于 03-04 13:57 2.1w次阅读

    如何解决PWM使用的DMA通道与串口接收DMA通道撞车问题

    项目做到一半,碰到个尴尬问题:PWM使用的DMA通道与串口接收DMA通道撞车了,咋办?考虑一下,决定放弃idle中断+
    的头像 发表于 02-16 11:35 2776次阅读
    如何解决PWM使用的<b class='flag-5'>DMA</b>通道与<b class='flag-5'>串口</b><b class='flag-5'>接收</b>的<b class='flag-5'>DMA</b>通道撞车问题

    PWM使用的DMA通道与串口接收DMA通道撞车了,咋办?

    项目做到一半,碰到个尴尬问题:PWM使用的DMA通道与串口接收DMA通道撞车了,咋办?考虑一下,决定放弃idle中断+
    发表于 04-27 06:00 12次下载
    PWM使用的<b class='flag-5'>DMA</b>通道与<b class='flag-5'>串口</b><b class='flag-5'>接收</b>的<b class='flag-5'>DMA</b>通道撞车了,咋办?

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)一、开发环境单片机型号:STM32H743IIT6工程配置环境:STM32CubeMX 6.3.0固件库:STM32Cube
    发表于 12-02 21:06 41次下载
    STM32 <b class='flag-5'>串口</b>使用IDLE<b class='flag-5'>中断</b>+<b class='flag-5'>DMA</b><b class='flag-5'>接收</b>(HAL库函数)

    STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA

    关于DMA原理部分讲解,及CubeMx配置部分,请参考该文章【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送
    发表于 12-20 19:39 31次下载
    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>

    STM32—无需中断来实现使用DMA接收串口数据

    本节目标:通过DMA,无需中断,接收不定时长的串口数据 描述:当在串口多数据传输下,CPU会产生多次
    发表于 12-24 19:01 8次下载
    STM32—无需<b class='flag-5'>中断</b>来实现使用<b class='flag-5'>DMA</b><b class='flag-5'>接收</b><b class='flag-5'>串口</b>数据

    STM32DMA+串口完成中断 接收发送

    最近在使用STM32F103单片机进行串口接收处理不定长数据测试时有两个需求。1、需要接收不定长的数据。2、提高串口响应速度。一直看过很多贴子关于
    发表于 12-24 19:03 5次下载
    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'>发送</b>

    stm32 发送完数据后 串口继续发送_STM32之串口DMA接收不定长数据

    引言在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢?同学A:数据来了就会进入串口中断,在
    发表于 12-24 19:17 8次下载
    stm32 <b class='flag-5'>发送</b>完数据后 <b class='flag-5'>串口</b>继续<b class='flag-5'>发送</b>_STM32之<b class='flag-5'>串口</b><b class='flag-5'>DMA</b><b class='flag-5'>接收</b>不定长数据

    STM32单片机串口空闲中断+DMA接收不定长数据

    在上一篇文章STM32单片机串口空闲中断接收不定长数据中介绍了利用串口空闲中断接收不定长数据,这
    发表于 12-27 19:24 18次下载
    STM32单片机<b class='flag-5'>串口</b>空闲<b class='flag-5'>中断</b>+<b class='flag-5'>DMA</b><b class='flag-5'>接收</b>不定长数据

    单片机接收不定长的数据,最优解是DMA+串口空闲中断

    如果单片机不支持串口空闲中断DMA,可以参考之前写的,串口只用接收中断,完成不定长的分包。这里
    发表于 12-28 19:26 25次下载
    单片机<b class='flag-5'>接收</b>不定长的数据,最优解是<b class='flag-5'>DMA</b>+<b class='flag-5'>串口</b>空闲<b class='flag-5'>中断</b>

    LPC5500_SDK例程:串口DMA发送+中断接收

    LPC5500_SDK例程:串口DMA发送+中断接收
    的头像 发表于 10-30 16:59 1109次阅读
    LPC5500_SDK<b class='flag-5'>例程</b>:<b class='flag-5'>串口</b><b class='flag-5'>DMA</b><b class='flag-5'>发送</b>+<b class='flag-5'>中断</b><b class='flag-5'>接收</b>

    STM32串口中断DMA接收常见的几个问题

    STM32串口中断DMA接收常见的几个问题
    的头像 发表于 10-26 16:41 3557次阅读
    STM32<b class='flag-5'>串口中断</b>及<b class='flag-5'>DMA</b><b class='flag-5'>接收</b>常见的几个问题