Kinetis KL8x 使用eDMA模块接收串口数据

来源:互联网 发布:java base64解码图片 编辑:程序博客网 时间:2024/05/29 15:58

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

正文开始:

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

#include "fsl_port_hal.h"#include "fsl_device_registers.h"#include "fsl_lpuart_edma_driver.h"#include "fsl_interrupt_manager.h"#include "board.h"#include <stdarg.h>#include <stdint.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#if 1unsigned char eDMA_recv_buf[1024];int recv_flag;void Lpuart1Init(int channal){    //PINC3-RX,PINC4--TX  *(volatile unsigned int *)(0x4004B00C) |= 0x00000300;  *(volatile unsigned int *)(0x4004B010) |= 0x00000300;    //uart Clock  *(volatile unsigned int *)(0x40048004) &= 0xF3FFFFFF;  *(volatile unsigned int *)(0x40048004) |= 0x08000000;  *(volatile unsigned int *)(0x40048038) |= 0x00200000;     LPUART1_BAUD = 0x0700000D;    LPUART1_STAT = 0xC01FC000;    LPUART1_CTRL = 0x00000000;    // Add this code to ensure that the TE bit has been cleared.    while(LPUART_BRD_CTRL_TE(LPUART1)){}    LPUART1_MATCH = 0x00000000;#if FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT    LPUART1_MODIR = 0x00000000;#endif#if FSL_FEATURE_LPUART_HAS_FIFO//    LPUART1_FIFO = 0x0000400F;//    LPUART1_WATER = 0x000D0000;//water = 6#endif      LPUART1_BAUD |= LPUART_BAUD_RDMAE_MASK;//RDMA Enable  LPUART1_CTRL = 0x003C0200;//RIE ILIE TE RE LPUART1_CTRL=010    NVIC_EnableIRQ(LPUART1_IRQn);}void Lpuart1_eDMA0Init(int channal,unsigned int D_Addr,unsigned int Block_Size){    // Enable clock gate of eDMA module  SIM_SCGC6 |= SIM_SCGC6_DMACHMUX_MASK;  SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;  //DMAMUX Config  DMAMUX_CHCFG(channal) = 0x00;  // Enables the DMA channel and select the DMA Channel Source    DMAMUX_CHCFG(channal) = DMAMUX_CHCFG_SOURCE(kDmaRequestMux0LPUART1Rx & 0xFF);//选择DMA触发源  DMAMUX_CHCFG(channal) |= DMAMUX_CHCFG_ENBL_MASK;//使能DMAMUX通道                              DMA_CR = 0;  DMA_SADDR(channal) = 0x4005500Cu;//Set Source Address is buff 设置源起始地址,这里直接固定为串口1的数据寄存器  DMA_DADDR(channal) = D_Addr;//Set Destination Address is UART_DATA_REG 设置目标起始地址  DMA_NBYTES_MLNO(channal) = 1;//Minor Byte Transfer Count is 1 设置 Minor_Byte 最小字节数,一般都是1个字节,这个根据传输的数据结构来定  DMA_ATTR(channal) = (0                  | DMA_ATTR_SMOD(0)// Source modulo feature disabled 设定源地址缓冲区边界                 | DMA_ATTR_SSIZE(0)// Source size, 8bit 设定源地址位大小                 | DMA_ATTR_DMOD(0)// Destination modulo feature disabled 设定目的地址缓冲区边界                 | DMA_ATTR_DSIZE(0)// Destination size, 8bit                   );  DMA_SOFF(channal)  = 0x0000;// Signed Source Address Offset is 0 byte 设定源地址每次传输的增量  DMA_DOFF(channal)  = 0x0001;// Signed Destination Address Offset is 1 byte 设定目的地址每次传输的增量  DMA_SLAST(channal) = 0x00;//Last Source Address Adjustment 完成一次输出之后即循环递减完后源地址的修正量  DMA_DLAST_SGA(channal) = 0x00;//Last Destination Address Adjustment/Scatter Gather Address   DMA_CITER_ELINKNO(channal) = DMA_CITER_ELINKNO_CITER(Block_Size);//设定一个循环的 Minor_Byte 量  DMA_BITER_ELINKNO(channal) = DMA_BITER_ELINKNO_BITER(Block_Size);//    DMA_CSR(channal) = 0;//  DMA_INT |= (1 << channal);//Interrupt Request Register 写1清0 清除中断  DMA_CSR(channal) |= DMA_CSR_INTMAJOR_MASK;//The end-of-major loop interrupt is enabled 设置一次循环完成中断    DMA_ERQ |= (1 << channal);//使能DMA请求    NVIC_EnableIRQ(DMA0_DMA4_IRQn);//开启DMA中断处理}void eDMA_Start(int eDMA_CHn){  DMA_ERQ |= (1 << eDMA_CHn);}void eDMA_Stop(int eDMA_CHn){  DMA_ERQ &= ~(1 << eDMA_CHn);}void LPUART1_IRQHandler_ZNG(void){  if((LPUART1_STAT & LPUART_STAT_IDLE_MASK) == LPUART_STAT_IDLE_MASK)//UART空闲中断,这里就是需要使用串口空闲中断来设定一次DMA数据传输完成  {    recv_flag = 1;    DMA_DADDR(0) = (unsigned int)eDMA_recv_buf;//填充DMA目的地址    LPUART1_STAT |= LPUART_STAT_IDLE_MASK;  }  }/*! @brief EDMA IRQ handler with the same name in the startup code*/void DMA0_DMA4_IRQHandler_ZNG(void){    if((DMA_INT & DMA_INT_INT0_MASK) == DMA_INT_INT0_MASK)    {      DMA_INT |= DMA_INT_INT0_MASK;//清除中断      DMA_ERQ |= DMA_ERQ_ERQ0_MASK;//使能DMA请求//      DMA_DADDR(0) = (unsigned int)recv_buf;    }}#endif

在main中就只要轮询recv_flag是否置位然后打印buff



0 0
原创粉丝点击