Kinetis 使用eDMA完成串口接收功能

Jicheng 在http://blog.chinaaet.com/detail/27546 博客中给出了eDMA完成串口发送的例程,本博客结合一个实际客户需求,在其代码基础上实现使用DMA完成串口接收的功能。

功能:使用DMA将UART接收到的数据放在RAM区中(定义一个16字节的数组),数组接收满时,进入中断,在中断服务函数中将接收到的数据再打印出来。
下面只介绍需要改动的地方:
(1)将以下代码

/* 以下为使能UART的DMA功能 */  
    UART_C2_REG(uartch) |= UART_C2_TIE_MASK;      /* 使能UART发送中断或者DMA请求 */
    UART_C2_REG(uartch) &= ~UART_C2_TCIE_MASK;    /* 禁止发送中断,只使能DMA请求*/
    UART_C5_REG(uartch) |= UART_C5_TDMAS_MASK;    /* 打开UART发送的DMA请求 */

改为:

/* 以下为使能UART的DMA接收功能 */  
    UART_C2_REG(uartch) |= UART_C2_RIE_MASK;      /* 使能UART接收中断或者DMA请求 */
    UART_C5_REG(uartch) |= UART_C5_RDMAS_MASK;    /* 打开UART接收的DMA请求 */

在这里我另外将其单独写了一个函数:

void UART_ITDMAConfig(UART_MemMapPtr uartch)
{
    UART_C2_REG(uartch)|= UART_C2_RIE_MASK;
    UART_C5_REG(uartch)|= UART_C5_RDMAS_MASK;
}

(2) myDMA_Config()函数里将

 DMA_BASE_PTR->TCD[DMA_CHn].SOFF  = 0x0001;                  /* 每次操作完源地址,源地址增加1 */
  DMA_BASE_PTR->TCD[DMA_CHn].DOFF  = 0x0000;                  /* 每次操作完目标地址,目标地址不增加  */

改为:

 DMA_BASE_PTR->TCD[DMA_CHn].SOFF  = 0x0000;                  /* 每次操作完源地址,源地址不增加 */
  DMA_BASE_PTR->TCD[DMA_CHn].DOFF  = 0x0001;                  /* 每次操作完目标地址,目标地址增加1  */

(3) myDMA_Config()函数里将:

DMA_BASE_PTR->TCD[DMA_CHn].DLAST_SGA = 0x00;                /* DMA完成一次输出之后即major_loop衰减完之后不更改目标地址 */

改为:

DMA_BASE_PTR->TCD[DMA_CHn].DLAST_SGA = 0xFFFFFFF0;                /* DMA完成一次接收之后,更改目标地址,使其回到初始值,0xFFFFFFF0为16的补码*/

(4) myDMA_Config()函数里将:

DMA_BASE_PTR->TCD[DMA_CHn].CSR |= DMA_CSR_DREQ_MASK;        /* major_loop递减为0时自动关闭DMA,即只进行一次DMA传输 */

改为:

DMA_BASE_PTR->TCD[DMA_CHn].CSR &= ~DMA_CSR_DREQ_MASK;        /* major_loop递减为0时不关闭DMA,继续等待触发源触发 */

原来的例子只进行一次DMA传输,现在需要连续接收。

(5) myDMA_Config()函数里将:

 DMA_BASE_PTR->TCD[DMA_CHn].CSR &= ~DMA_CSR_INTMAJOR_MASK;   /*关闭DMA major_loop完成中断 */

改为:

 DMA_BASE_PTR->TCD[DMA_CHn].CSR |= DMA_CSR_INTMAJOR_MASK;   /*开启DMA major_loop完成中断 */

打开中断功能。

(6) 现在就可以写应用代码了,如下:

#define UART1_D_Addr 0x4006B007 // UART1_D 的地址
/* 接收缓冲区 */
static uint8_t UART_Buffer[16];
/* 中断服务函数 */
void DMA_ISR(void)
{
    uint32_t i; 
    DMA_BASE_PTR->CINT = DMA_CINT_CINT(1); /* 清中断标志*/
    for(i=0;i<sizeof(UART_RxBuffer);i++)
         printf("%c",UART_RxBuffer[i]);
     printf("\r\n"); 
}

void uartdma_task
    (
        uint32_t initial_data
    )
{
    (void)initial_data; /* disable 'unused variable' warning */
      rs232_init(); // 串口初始化
      UART_ITDMAConfig(UART1_BASE_PTR);/* 打开UART1 DMA接收功能 */
    myDMA_Config2(1,DMA_UART1_R,UART1_D_Addr,(uint32)UART_RxBuffer,sizeof(UART_RxBuffer)); 

    /*  以下四句话为MQX中中断配置 */
    _bsp_int_disable(INT_DMA1);
    _int_install_isr(INT_DMA1,DMA_ISR,NULL);
    _bsp_int_init(INT_DMA1, 5, 0, TRUE);
    _bsp_int_enable(INT_DMA1);

    myDMA_Start(1); // 启动DMA

    while(1)
    {

    }
}

注:我是在MQX中做的,在哪里实现无所谓,原理都是一样的。

最终的效果如下:
这里写图片描述
在串口调试中发送16字节数据,可以看到接收缓冲求就会收到相应的数据,同时在中断服务函数中会打印出数据。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值