请选择 进入手机版 | 继续访问电脑版
查看: 759|回复: 0

[分享] Kinetis KL8x 使用eDMA模块接收串口数据

[复制链接]
  • TA的每日心情
    开心
    2022-4-14 11:08
  • 签到天数: 47 天

    [LV.5]常住居民I

    23

    主题

    131

    帖子

    0

    高级会员

    Rank: 4

    积分
    724
    最后登录
    2024-1-20
    发表于 2020-7-7 22:27:05 | 显示全部楼层 |阅读模式
    Kinetis KL8x 使用eDMA模块接收串口数据

    飞思卡尔的芯片KL系列Cortex-M0+内核的,其他的应该可以通用,大体一致,之前在KL25上用过,这次是KL81,我对比两者使用类似,就是某些寄存器不同罢了

    正文开始:

    需要用LPUART接收上层接口的数据,比较大,而且大小不固定,之前用FIFO来接收,但是遇到收发错乱,很不稳定,故使用eDMA来接收
    1. #include "fsl_port_hal.h"
    2. #include "fsl_device_registers.h"

    3. #include "fsl_lpuart_edma_driver.h"
    4. #include "fsl_interrupt_manager.h"
    5. #include "board.h"
    6. #include <stdarg.h>
    7. #include <stdint.h>
    8. #include <stdio.h>
    9. #include <string.h>
    10. #include <stdlib.h>

    11. #if 1
    12. unsigned char eDMA_recv_buf[1024];
    13. int recv_flag;


    14. void Lpuart1Init(int channal)
    15. {
    16.   
    17.   //PINC3-RX,PINC4--TX
    18.   *(volatile unsigned int *)(0x4004B00C) |= 0x00000300;
    19.   *(volatile unsigned int *)(0x4004B010) |= 0x00000300;
    20.   
    21.   //uart Clock
    22.   *(volatile unsigned int *)(0x40048004) &= 0xF3FFFFFF;
    23.   *(volatile unsigned int *)(0x40048004) |= 0x08000000;
    24.   *(volatile unsigned int *)(0x40048038) |= 0x00200000;

    25.     LPUART1_BAUD = 0x0700000D;
    26.     LPUART1_STAT = 0xC01FC000;
    27.     LPUART1_CTRL = 0x00000000;
    28.     // Add this code to ensure that the TE bit has been cleared.
    29.     while(LPUART_BRD_CTRL_TE(LPUART1)){}
    30.     LPUART1_MATCH = 0x00000000;
    31. #if FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
    32.     LPUART1_MODIR = 0x00000000;
    33. #endif
    34. #if FSL_FEATURE_LPUART_HAS_FIFO
    35. //    LPUART1_FIFO = 0x0000400F;
    36. //    LPUART1_WATER = 0x000D0000;//water = 6
    37. #endif
    38.    
    39.   LPUART1_BAUD |= LPUART_BAUD_RDMAE_MASK;//RDMA Enable
    40.   LPUART1_CTRL = 0x003C0200;//RIE ILIE TE RE LPUART1_CTRL=010
    41.   
    42.   NVIC_EnableIRQ(LPUART1_IRQn);
    43. }
    44. void Lpuart1_eDMA0Init(int channal,unsigned int D_Addr,unsigned int Block_Size)
    45. {
    46.   
    47.   // Enable clock gate of eDMA module
    48.   SIM_SCGC6 |= SIM_SCGC6_DMACHMUX_MASK;
    49.   SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;
    50.   //DMAMUX Config
    51.   DMAMUX_CHCFG(channal) = 0x00;
    52.   // Enables the DMA channel and select the DMA Channel Source  
    53.   DMAMUX_CHCFG(channal) = DMAMUX_CHCFG_SOURCE(kDmaRequestMux0LPUART1Rx & 0xFF);//选择DMA触发源
    54.   DMAMUX_CHCFG(channal) |= DMAMUX_CHCFG_ENBL_MASK;//使能DMAMUX通道
    55.                           
    56.   
    57.   DMA_CR = 0;
    58.   DMA_SADDR(channal) = 0x4005500Cu;//Set Source Address is buff 设置源起始地址,这里直接固定为串口1的数据寄存器
    59.   DMA_DADDR(channal) = D_Addr;//Set Destination Address is UART_DATA_REG 设置目标起始地址
    60.   DMA_NBYTES_MLNO(channal) = 1;//Minor Byte Transfer Count is 1 设置 Minor_Byte 最小字节数,一般都是1个字节,这个根据传输的数据结构来定
    61.   DMA_ATTR(channal) = (0
    62.                  | DMA_ATTR_SMOD(0)                        // Source modulo feature disabled 设定源地址缓冲区边界
    63.                  | DMA_ATTR_SSIZE(0)                // Source size, 8bit 设定源地址位大小
    64.                  | DMA_ATTR_DMOD(0)                        // Destination modulo feature disabled 设定目的地址缓冲区边界
    65.                  | DMA_ATTR_DSIZE(0)                // Destination size, 8bit
    66.                   );
    67.   DMA_SOFF(channal)  = 0x0000;// Signed Source Address Offset is 0 byte 设定源地址每次传输的增量
    68.   DMA_DOFF(channal)  = 0x0001;// Signed Destination Address Offset is 1 byte 设定目的地址每次传输的增量
    69.   DMA_SLAST(channal) = 0x00;//Last Source Address Adjustment 完成一次输出之后即循环递减完后源地址的修正量
    70.   DMA_DLAST_SGA(channal) = 0x00;//Last Destination Address Adjustment/Scatter Gather Address
    71.   DMA_CITER_ELINKNO(channal) = DMA_CITER_ELINKNO_CITER(Block_Size);//设定一个循环的 Minor_Byte 量
    72.   DMA_BITER_ELINKNO(channal) = DMA_BITER_ELINKNO_BITER(Block_Size);//
    73.   
    74.   DMA_CSR(channal) = 0;//
    75.   DMA_INT |= (1 << channal);//Interrupt Request Register 写1清0 清除中断
    76.   DMA_CSR(channal) |= DMA_CSR_INTMAJOR_MASK;//The end-of-major loop interrupt is enabled 设置一次循环完成中断
    77.   
    78.   DMA_ERQ |= (1 << channal);//使能DMA请求
    79.   
    80.   NVIC_EnableIRQ(DMA0_DMA4_IRQn);//开启DMA中断处理

    81. }

    82. void eDMA_Start(int eDMA_CHn)
    83. {
    84.   DMA_ERQ |= (1 << eDMA_CHn);
    85. }
    86. void eDMA_Stop(int eDMA_CHn)
    87. {
    88.   DMA_ERQ &= ~(1 << eDMA_CHn);
    89. }

    90. void LPUART1_IRQHandler_ZNG(void)
    91. {
    92.   if((LPUART1_STAT & LPUART_STAT_IDLE_MASK) == LPUART_STAT_IDLE_MASK)//UART空闲中断,这里就是需要使用串口空闲中断来设定一次DMA数据传输完成
    93.   {
    94.     recv_flag = 1;
    95.     DMA_DADDR(0) = (unsigned int)eDMA_recv_buf;//填充DMA目的地址
    96.     LPUART1_STAT |= LPUART_STAT_IDLE_MASK;
    97.   }
    98.   
    99. }
    100. /*! @brief EDMA IRQ handler with the same name in the startup code*/
    101. void DMA0_DMA4_IRQHandler_ZNG(void)
    102. {
    103.     if((DMA_INT & DMA_INT_INT0_MASK) == DMA_INT_INT0_MASK)
    104.     {
    105.       DMA_INT |= DMA_INT_INT0_MASK;//清除中断
    106.       DMA_ERQ |= DMA_ERQ_ERQ0_MASK;//使能DMA请求
    107. //      DMA_DADDR(0) = (unsigned int)recv_buf;
    108.     }
    109. }


    110. #endif

    复制代码





    签到签到
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-3-29 03:41 , Processed in 0.109635 second(s), 18 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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