使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
简介 本示例的目标是连续读取 Kinetis KL25 的所有 ADC 输入,而无需使用 CPU 内核切换通道和引脚并读取单个值。 FRDM-KL25 板采用 Kinetis MKL25Z128VLK4 微控制器。该 MCU 包含一个具有 16 个输入的 16 位 AD 转换器。 在 Processor Expert 中,有可用的 ADC_LDD 组件,可用于测量这些引脚上的值。然而,存在一些限制,即某些输入引脚(例如ADC0_SE4a 和 ADC0_SE4b) 被复用到同一通道,并且 ADC_LDD 不允许在没有额外的复用切换代码的情况下同时测量这两个引脚。MCU 也不提供扫描 ADC 通道的选项,需要用户自行切换通道。为了实现连续测量所有输入的目标,可以使用外设初始化组件和 DMA(直接内存访问)外设。 项目描述 注意:本文附有示例项目的档案。 本例中的 DMA 用于控制所有通道切换、引脚多路复用器选择以及将一系列测量的结果读取到内存缓冲区中。 结果写入 FRDM 板提供的串行控制台(虚拟串行端口)。 直接内存访问 (DMA) 通道配置为按以下方式写入和读取 ADC 寄存器: DMA通道0读取转换结果(ADC0_RA寄存器) DMA 通道 1 使用来自内存阵列ChannelsCfg 的值更改 ADC 引脚组选择多路复用器(ADC0_CFG2 寄存器) DMA 通道 2 选择 ADC 通道并使用来自存储器阵列ChannelsCfg2的值开始转换(ADC0_SC1A 寄存器) DMA 通道 1 a 2 的数据在内存中准备好的ChannelsCfg和ChannelsCfg2数组中, DMA 按照以下周期运行: 首先,使用软件触发启动 DMA 通道 1 传输。这将选择引脚 (a/b)。 然后,由于启用了 DMA 通道链接,DMA 通道 2 立即执行。这将配置通道并开始转换。 转换完成后,结果由DMA通道0读取并存储到结果数组中。通道链接执行通道 1 传输并继续循环。 测量完所有需要的通道(DMA 字节计数器达到 0)后,将调用 DMA 中断,以便通知用户代码。 参见下图描述该过程: 组件配置 该应用程序使用以下 Processor Expert 组件生成的驱动程序模块: ConsoleIO 属性设置 该组件将 printf 命令输出重定向到连接到 UART0 引脚 PTA1/UART0_RX 和 PTA2/UART0_TX 的 FRDM USB 虚拟串行端口。 串行设备、速度和引脚在继承的 Serial_LDD 组件中配置。 Init_ADC属性设置 Init_ADC 提供 ADC 初始化代码,其中所有通道均已启用并设置为单端。 可以根据用户需要,根据任何有效值选择时钟。与 HW 平均设置相同。 本演示中不会使用比较功能。 引脚配置-板上所有可用的引脚均已启用: 中断、DMA 和触发- 中断被禁用, DMA 请求已启用。触发已被禁用,因为在此演示项目中未使用它,但是,可以扩展应用程序以使用它。 Init_DMA 属性设置 Init_DMA 提供 DMA 的初始化代码。 时钟门控和 DMA 多路复用器已启用: DMA通道0 16 位结果从 ADC0_RA 寄存器传输(参见属性数据源/地址)。 传输模式为循环窃取 (Cycle-steal),这意味着每个外部请求只进行一次交易。 目标地址初始值未在检查器中填写,因为在应用程序代码中该值被重复填写。 通道链接设置为在每次传输后触发通道 1 通道 0 的 DMA mux 设置已启用,并选择 ADC0_DMA_Request,这是转换结束时来自 ADC 的信号。 此通道的“DMA 传输完成”中断已启用。ADCint ISR 函数将被调用。 启用外部请求(来自 ADC 的请求)来启动传输。字节数也会在每个序列之前改变 属性值: DMA通道1 DMA 通道 1 使用来自存储器阵列ChannelsCfg 的值来更改 ADC 引脚组选择多路复用器(ADC0_CFG2 寄存器)。 请注意,源地址初始值未填充,将与字节计数值一起在应用程序代码中设置。 此通道没有 HW 触发器,它被设置为仅由 SW 触发(以及由将要使用的链接机制触发)。 该通道的链接设置为在传输后触发 CH2。 此通道未启用中断 DMA通道 2 DMA 通道 2 选择 ADC 通道并使用来自存储器阵列ChannelsCfg2 的值开始转换(ADC0_SC1A 寄存器)。 传输结束后没有链接任何频道 - 无链接。 未选择任何外部通道请求,此通道传输由来自 CH2 的链接触发。 TimerUnit_LDD 它在应用程序代码中用于提供延迟以减慢控制台输出速度。 TPM0 计数器的使用周期约为。350毫秒。 不使用中断。 自动初始化已启用。 代码 需要测量的通道/引脚在 ChannelsCfg 和 ChannelsCfg2 数组中指定。 这些数组包含要测量的引脚列表,可以根据用户需要更改顺序,甚至可以多次测量通道。 特殊值 0x1F 停止转换。 // 频道配置数组 - 频道编号。应该以 0x1F 结尾,停止转换 // 对应 于通道选择A/B引脚的 第二个 配置 数组 //例如:0+PIN_A对应引脚ADC0_SE0,5+PIN_5选择引脚ADC0_SE5b // 您可以根据需要使用这些数组来重新排序测量值 const uint8_t ChannelsCfg [ADC_CHANNELS_COUNT + 1] = { 0, 4, 3, 7, 4, 23, 8, 9, 11, 12, 13, 14, 15, 5, 6, 7, 0x1F }; const uint8_t ChannelsCfg2[ADC_CHANNELS_COUNT + 1] = {PIN_A, PIN_A, PIN_A, PIN_A, PIN_B, PIN_A, PIN_A, PIN_A, PIN_A, PIN_A, PIN_A, PIN_A, PIN_A, PIN_B, PIN_B, PIN_B, 0 }; 在主循环中,应用程序首先重新初始化 DMA 值并通过软件触发 DMA 通道 1 启动序列。 // loop 当(真){ // 清除标志 测量结果=错误; // 将 DMA0 目标指针重置为缓冲区的开头 DMA_DAR0 = ( uint32_t )&测量值; // 重置 DMA1 源指针(MUX 切换写入) DMA_SAR1 = (uint32_t) &ChannelsCfg2; // 重置 DMA2 源指针(通道切换和转换开始写入) DMA_SAR2 = (uint32_t) &ChannelsCfg; // 从 ADC 结果寄存器 A 传输的总字节数 DMA_DSR_BCR0 = ADC_通道数 * 2; // 设置要传输到 ADC0_CFG2 的总字节数 DMA_DSR_BCR1 = ADC_通道数 + 1; // 设置要传输到 ADC0_SC1A 的总字节数。 DMA_DSR_BCR2 = ADC_通道数 + 1; // 启动第一个 DMA1 传输(选择多路复用器,然后触发通道 2 来选择启动转换的通道) DMA_DCR1 |= DMA_DCR_START_MASK; // 等待所有测量完成 while (!Measured){} // 将所有测量值打印到控制台 for (i=0; i printf ( "%7u" , ( uint16_t ) MeasuredValues[i]); } printf ("\n"); // 重置计数器 TU1_ResetCounter(TU1_DeviceData); // 等待一段时间以减慢输出 当(TU1_GetCounterValue(TU1_DeviceData)<50000){} } 运行项目 该项目可以按常规方式运行。 将项目导入 CodeWarrior for MCUs V10.5。 构建项目 连接FRDM-KL25板 开始调试并运行代码 运行终端应用程序或使用 eclpise 中的终端视图。将其设置为使用为主板创建的虚拟串行端口。参数应设置为38400,无奇偶校验,8位,1个停止位。 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi, 看起来该链接不知何故停止工作了,可能是在社区迁移期间。 幸运的是,我找到了它并再次上传,现在可以在这里使用: KL25_MultiADC_DMA.zip 顺祝商祺! Petr Hradsky 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi NXP, 我无法下载您的示例代码,它已被删除。可以再上传一下吗? 此外,我可以在 MKL17 MCU 上按照这种方法测量 19ch ADC 吗? 谢谢! Leo 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
谢谢分享!这是我见过的用于 Kinetis KLZ25 的最轻的 ADC 驱动器。如果有人使用它,他们可能对速度感兴趣。PE(处理器专家)中的低层设备驱动程序(LLD)过于臃肿,无法达到最大速度。我也无法让他们的 DMA 选项正常工作,否则会出错。但是,你的方法有效! 使用您的代码,我将其修改为 3 个通道上的 8 位样本,时钟速度为 16mhz。所有速度功能均已启用。然而,当考虑重新加载 DMA 时,我只能有效获得~100ksps(所有 3 个通道约为 10us)。我使用完成中断来重新加载 DMA。理想情况下,我希望获得 200kbs+。知道我能做些什么来加快速度吗?从 16 位 12mhz 到 8 位 16mhz 时,我并没有看到性能有显著提升,这似乎很奇怪。最大处理器优化已打开,可以提供一些帮助。 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
查看此主题: https://community.freescale.com/message/462300?et= watches.email.thread#462300 我也尝试将 DMA 与 K70 一起使用,但 DMA+PDB+ADC 存在一些问题。 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
你好Petr_H 我一直在尝试构建一个带有一个 ADC 通道的录音系统。我必须执行模拟到数字的转换,然后将我的数据发送到计算机(例如使用串行通信)。首先,我使用了处理器专家中可用的 ADC 组件,该组件运行良好,但是当我使用串行通信(printf 和 scanf 函数)将这些数据发送到计算机时,我没有得到预期的数据。 我现在正在尝试使用 DMA 来改善 mcu(KL26Z)与计算机的通信。我尝试调整你的代码,但没有成功。您能给我一些提示吗? 提前谢谢! 回复:使用 DMA 测量 FRDM-KL25 上的所有 ADC 输入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
一个问题:这个系统可以达到的最大采样频率是多少?
View full article