查看: 1922|回复: 2

[分享] LPC5500_SDK例程:串口DMA发送+中断接收

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32030
    最后登录
    2024-4-26
    发表于 2022-7-25 15:34:01 | 显示全部楼层 |阅读模式
    LPC5500_SDK例程:串口DMA发送+中断接收


    LPC5500的SDK中提供了非常丰富的串口例程(如下图所示):
    11.png
    但是,偏偏没有串口DMA发送+中断接收这种组合。


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


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


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


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


    首先将USART_TransferCreateHandleDMA函数修改下,将所有RX DMA有关的东西去掉,handler填NULL就可以。这样usart_dma driver就不会处理RX DMA有关的操作了:
    1. USART_TransferCreateHandleDMA(DEMO_USART,  &g_uartDmaHandle, USART_UserCallback, NULL,&g_uartTxDmaHandle, NULL);
    复制代码
    2. 开启usart RX中断,没啥可说的,常规操作:
    1. /* Enable RX interrupt. */
    2. USART_EnableInterrupts(DEMO_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable);
    3. EnableIRQ(DEMO_USART_IRQn);
    复制代码
    3. 在app层定义(接管)串口硬件中断,并在中断中处理串口RX接收到的数据:
    1. #define DEMO_USART_IRQHandler FLEXCOMM0_IRQHandler
    2. #define DEMO_USART_IRQn     FLEXCOMM0_IRQn
    复制代码
    1. void DEMO_USART_IRQHandler(void)
    2. {
    3.    uint8_t data;
    4.    /* If new data arrived. */
    5.    if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError | kUSART_RxFifoFullFlag) & USART_GetStatusFlags(DEMO_USART))
    6.    {
    7.        data = USART_ReadByte(DEMO_USART);
    8.        PRINTF("usart rx interrupt:%c\r\n", data);

    9.        if(data == 's')

    10.        {

    11.           /* Send g_tipString out. */

    12.           xfer.data     = g_tipString;

    13.           xfer.dataSize = sizeof(g_tipString) - 1;


    14.           g_uartDmaHandle.txState = kUSART_TxIdle;

    15.           USART_TransferSendDMA(DEMO_USART, &g_uartDmaHandle, &xfer);

    16.       }

    17.    }

    18.    if ((0U != (DEMO_USART->INTENSET &  USART_INTENSET_TXIDLEEN_MASK)) && (0U != (DEMO_USART->INTSTAT & USART_INTSTAT_TXIDLE_MASK)))

    19.    {

    20.       USART_TransferDMAHandleIRQ(DEMO_USART, &g_uartDmaHandle);

    21.    }

    22. }
    复制代码
    注意,这里需要在硬件串口中断里判断TXIDLE中断,并调用USART_TransferDMAHandleIRQ。这是仿照fsl_usart_dma.c中的写法(fsl_usart_dma中开启了TXIDLE中断,并使用TXIDLE中断来调用dma handle用户回调函数,现在硬件串口中断已经被app层接管,所以我们同样要实现这部分功能)。
    4. 测试:改好代码,下载运行:当串口敲入任意键时候,程序都会回显接收到数据,当按键”s”时,会调用USART_TransferSendDMA函数使用DMA发送一串数据,并进入DMA发送完成回调函数。
    12.png
    代码清单
    以下是完整代码清单(可以直接复制到usart_dma_transfer.c里运行):
    1. /*
    2. * Copyright (c) 2016, Freescale Semiconductor, Inc.

    3. * Copyright 2016-2017 NXP

    4. * All rights reserved.

    5. *

    6. * SPDX-License-Identifier:  BSD-3-Clause

    7. */

    8. #include "pin_mux.h"

    9. #include "board.h"

    10. #include "fsl_usart.h"

    11. #include "fsl_usart_dma.h"

    12. #include "fsl_dma.h"

    13. #include "fsl_debug_console.h"


    14. #include <stdbool.h>

    15. #include "fsl_power.h"


    16. #define DEMO_USART                USART0

    17. #define DEMO_USART_CLK_SRC        kCLOCK_Flexcomm0

    18. #define DEMO_USART_CLK_FREQ       CLOCK_GetFlexCommClkFreq(0U)

    19. #define USART_RX_DMA_CHANNEL      4

    20. #define USART_TX_DMA_CHANNEL      5

    21. #define EXAMPLE_UART_DMA_BASEADDR DMA0

    22. #define DEMO_USART_IRQHandler FLEXCOMM0_IRQHandler

    23. #define DEMO_USART_IRQn       FLEXCOMM0_IRQn

    24. #define ECHO_BUFFER_LENGTH 8


    25. usart_transfer_t xfer;

    26. usart_dma_handle_t g_uartDmaHandle;

    27. dma_handle_t g_uartTxDmaHandle;

    28. uint8_t g_tipString[]                  = "This string is send from UART_DMA\r\n";

    29. #define kUSART_TxIdle 0

    30. void USART_UserCallback(USART_Type *base, usart_dma_handle_t *handle, status_t status, void *userData)

    31. {

    32.    userData = userData;

    33.    if (kStatus_USART_TxIdle == status)

    34.    {

    35.        PRINTF("USART_UserCallback, status:0x%X\r\n", status);

    36.    }

    37. }

    38. void DEMO_USART_IRQHandler(void)
    39. {
    40.    uint8_t data;
    41.    /* If new data arrived. */
    42.    if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError | kUSART_RxFifoFullFlag) & USART_GetStatusFlags(DEMO_USART))
    43.    {
    44.        data = USART_ReadByte(DEMO_USART);
    45.        PRINTF("usart rx interrupt:%c\r\n", data);

    46.        if(data == 's')

    47.        {

    48.           /* Send g_tipString out. */

    49.           xfer.data     = g_tipString;

    50.           xfer.dataSize = sizeof(g_tipString) - 1;


    51.           g_uartDmaHandle.txState = kUSART_TxIdle;

    52.           USART_TransferSendDMA(DEMO_USART, &g_uartDmaHandle, &xfer);

    53.       }

    54.    }

    55.    if ((0U != (DEMO_USART->INTENSET &  USART_INTENSET_TXIDLEEN_MASK)) && (0U != (DEMO_USART->INTSTAT & USART_INTSTAT_TXIDLE_MASK)))

    56.    {

    57.       USART_TransferDMAHandleIRQ(DEMO_USART, &g_uartDmaHandle);

    58.    }

    59. }
    复制代码
    1. int main(void)

    2. {

    3.    usart_config_t    config;

    4.   

    5.    /* set BOD VBAT level to 1.65V */

    6.    POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false);

    7.    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */

    8.    CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);

    9.   

    10.    BOARD_InitBootPins();

    11.    BOARD_InitBootClocks();

    12.    BOARD_InitDebugConsole();

    13.   

    14.    PRINTF("USART: TX DMA, RX INTERRUPT\r\n");

    15.    PRINTF("press 's' for DMA TX tranmsit\r\n");

    16.   

    17.    USART_GetDefaultConfig(&config);

    18.    config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;

    19.    config.enableTx     = true;

    20.    config.enableRx     = true;

    21.   

    22.    USART_Init(DEMO_USART, &config, DEMO_USART_CLK_FREQ);

    23.   

    24.    /* Configure DMA. */

    25.    DMA_Init(EXAMPLE_UART_DMA_BASEADDR);

    26.    DMA_EnableChannel(EXAMPLE_UART_DMA_BASEADDR, USART_TX_DMA_CHANNEL);

    27.    DMA_EnableChannel(EXAMPLE_UART_DMA_BASEADDR, USART_RX_DMA_CHANNEL);

    28.    DMA_CreateHandle(&g_uartTxDmaHandle, EXAMPLE_UART_DMA_BASEADDR, USART_TX_DMA_CHANNEL);

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



    30.    /* Send g_tipString out. */

    31.    xfer.data     = g_tipString;

    32.    xfer.dataSize = sizeof(g_tipString) - 1;

    33.    USART_TransferSendDMA(DEMO_USART, &g_uartDmaHandle, &xfer);

    34.   

    35.    /* Enable RX interrupt. */

    36.    USART_EnableInterrupts(DEMO_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable);

    37.    EnableIRQ(DEMO_USART_IRQn);

    38.    while (1);

    39. }
    复制代码




    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-10 22:38
  • 签到天数: 1335 天

    [LV.10]以坛为家III

    88

    主题

    4292

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9049
    最后登录
    2024-4-13
    发表于 2022-7-25 21:56:14 | 显示全部楼层
    我就是觉得官方的示例代码有些冗余。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-1-4 14:25
  • 签到天数: 1 天

    [LV.1]初来乍到

    0

    主题

    172

    帖子

    0

    高级会员

    Rank: 4

    积分
    571
    最后登录
    2024-4-26
    发表于 2022-8-9 23:41:04 | 显示全部楼层
    学习了,谢谢!!
    每天登陆学习一下
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 18:37 , Processed in 0.130705 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表