77|0

138

帖子

2

TA的资源

一粒金砂(高级)

楼主
 

【MCXA156开发板测评】-7-EDMA3与LPADC1协作搬运 [复制链接]

本帖最后由 慕容雪花 于 2025-1-13 14:13 编辑

前面测评:

【MCXA156开发板测评】-1-开发环境搭建与串口回显 https://bbs.eeworld.com.cn/thread-1303370-1-1.html

【MCXA156开发板测评】-2-ADC https://bbs.eeworld.com.cn/thread-1303898-1-1.html

【MCXA156开发板测评】-3-LPTMR体验 https://bbs.eeworld.com.cn/thread-1304161-1-1.html

【MCXA156开发板测评】-4-LPI2C驱动OLED屏幕 https://bbs.eeworld.com.cn/thread-1304186-1-1.html

【MCXA156开发板测评】-5-LPADC中断模式快速配置 https://bbs.eeworld.com.cn/thread-1304340-1-1.html

【MCXA156开发板测评】-6-EDMA3例程代码分析 https://bbs.eeworld.com.cn/thread-1304375-1-1.html

 

MCX-A156的例程库提供了lpi2c, lpspi,lpuart等模块与edma3模块协作搬运数据的例程,但是没有看到adc与dma的例程。

所以本次实验来尝试在恩智浦mcuconfigtool里面配置edma3模块,并尝试去搬运adc获取到数据。

 

一、配置adc发送dma请求

在前面的测评文章中,提到了FIFO watermark可以用来作为一个阈值来发起中断请求或者DMA触发。

 

二、使能并配置dma3

本次实验使用dma0:

 

配置eDMA通道0的request source等参数:

 

 

 

 

三、适当修改代码

在生成的ADC1初始化代码中,看到已经使能了DMA请求:

static void ADC1_init(void) {
  /* Initialize LPADC converter */
  LPADC_Init(ADC1_PERIPHERAL, &ADC1_config);
  /* Perform auto calibration */
  LPADC_DoAutoCalibration(ADC1_PERIPHERAL);
  /* Enable DMA request on FIFO watermark event */
  LPADC_EnableFIFOWatermarkDMA(ADC1_PERIPHERAL, true);
  /* Configure conversion command 1. */
  LPADC_SetConvCommandConfig(ADC1_PERIPHERAL, 1, &ADC1_commandsConfig[0]);
  /* Configure trigger 0. */
  LPADC_SetConvTriggerConfig(ADC1_PERIPHERAL, 0, &ADC1_triggersConfig[0]);
  /* Interrupt vector ADC1_IRQn priority settings in the NVIC. */
  NVIC_SetPriority(ADC1_IRQN, ADC1_IRQ_PRIORITY);
  /* Enable interrupts from LPADC */
  LPADC_EnableInterrupts(ADC1_PERIPHERAL, (kLPADC_FIFO0WatermarkInterruptEnable));
  /* Enable interrupt ADC1_IRQN request in the NVIC */
  EnableIRQ(ADC1_IRQN);
}

查看dma0的初始化代码:

edma_config_t DMA0_config = {
  .enableMasterIdReplication = false,
  .enableGlobalChannelLink = true,
  .enableHaltOnError = true,
  .enableDebugMode = false,
  .enableRoundRobinArbitration = false
};
/* Tansactional transfer configurations */
edma_transfer_config_t DMA0_CH0_Transfers_config[1];
edma_handle_t DMA0_CH0_Handle;
/* TCD pool initialization */
EDMA_ALLOCATE_TCD(DMA0_CH0_TCD_pool, DMA0_CH0_TCD_SIZE);

static void DMA0_init(void) {
  status_t status;
  (void)status;

  /* Channel CH0 initialization */
  /* Set the kDma0RequestMuxAdc1FifoRequest request */
  EDMA_SetChannelMux(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL, DMA0_CH0_DMA_REQUEST);
  /* Create the eDMA DMA0_CH0_Handle handle */
  EDMA_CreateHandle(&DMA0_CH0_Handle, DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);
  /* DMA0 channel 0 reset */
  EDMA_ResetChannel(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);
  /* DMA0 channel 0 peripheral request */
  EDMA_EnableAsyncRequest(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL, true);
  /* Allocate TCD memory pool for scatter-gather mode */
  EDMA_InstallTCDMemory(&DMA0_CH0_Handle, DMA0_CH0_TCD_pool, DMA0_CH0_TCD_SIZE);
  /* DMA callback initialization */
  EDMA_SetCallback(&DMA0_CH0_Handle, DMA_Callback, NULL);
  /* DMA0 transfer CH0_TRANSFER0 configuration */
  EDMA_PrepareTransferConfig(&DMA0_CH0_TRANSFER0_CONFIG, (void *) (uint32_t)(&(ADC1->RESFIFO))    , 1 << kEDMA_TransferSize4Bytes, 0, (void *) &destAddr[0], 1 << kEDMA_TransferSize4Bytes, sizeof(destAddr[0]), 4U, 80U); 
  DMA0_CH0_TRANSFER0_CONFIG.dstMajorLoopOffset = 4;
  /* DMA0 loop transfer submit */
  status = EDMA_SubmitLoopTransfer(&DMA0_CH0_Handle, DMA0_CH0_Transfers_config, 1U);
  assert(status == kStatus_Success);
  /* DMA0 hardware channel 0 request auto stop */
  EDMA_EnableAutoStopRequest(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL, true);
  /* DMA0 channel 0 peripheral request */
  EDMA_EnableChannelRequest(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);
}

定义相关的目标数组:

extern edma_handle_t DMA0_CH0_Handle;
volatile bool g_transferDone = false;

uint32_t destAddr[20];
/* DMA0 TCD CH0_TRANSFER0 destination address */
AT_NONCACHEABLE_SECTION_ALIGN_INIT(uint32_t destAddr[], 4);

/* DMA channel DMA0_CH0 callback function */
void DMA_Callback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) {
	/* Place your code here */
    if (transferDone)
    {
        g_transferDone = true;
    }
    PRINTF("\r\n DMA_Callback Done");
}

启动DMA:

EDMA_StartTransfer(&DMA0_CH0_Handle);

之后等待DMA传输完成标志位在DMA CALLBAKC函数中置位:

    /* Wait for EDMA transfer finish */
    while (!g_transferDone)
    {
    	LPADC_DoSoftwareTrigger(ADC1_PERIPHERAL, 1U);
    }
    /* Print destination buffer */
    PRINTF("\r\n\r\nEDMA transfer ADC1 finish.\r\n\r\n");
    PRINTF("Destination Buffer:\r\n");
    for (uint8_t i = 0; i < 20; i++)
    {
        PRINTF("%d\t", (uint16_t)(destAddr[i]& ADC_RESFIFO_D_MASK));
    }
	PRINTF("\r\n END TEST");
    while(1){

    }

 

四、运行

ADC的输入信号是连接到3.3V电源上,这样简便些。

 

 

采集一下声音传感器数据:

 

五、总结

eDMA是恩智浦在MCXA156产品上提供的增强型DMA控制器,可以在不占用CPU资源来进行数据搬运。这种工作模式可以大大减轻CPU的负担。

借助恩智浦的MCU CONFIGTOOL,可以方便的配置eDMA模块和各种外设模式,自动生成驱动代码。用户只需要添加数行业务代码即可轻松使用eDMA模块。

 

 

参考:

Using Configtools to set up ADC and DMA from scratch - Sample Project LPC55S69 https://community.nxp.com/t5/MCUXpresso-Config-Tools/Using-Configtools-to-set-up-ADC-and-DMA-from-scratch-Sample/m-p/1183770

此帖出自NXP MCU论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表