打印
[STM32H7]

STM32H7 ADC交替采样实现8M采样率(14bit) 与高速USB(VCP)传输

[复制链接]
317|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-10-25 17:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
1. 介绍
主控: STM32H743VIH6

软件:STM32CubeMX + STM32CubeIDE

由于此型号H7没有内置的HS USB PHY, 所以使用了外置芯片: USB3300

STM32H7的选型我是根据下帖进行选择的,需要注意的是 1. 不同封装对应的最高采样速率不同;

2. 不同通道所能达到的最高采样率也不同。

STM32H7中ADC功能被ST玩出花,现在分直接通道,快速通道和慢速通道,不同封装最高速不同, LQFP封装速度最低 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!

根据数据手册 和 参考手册:





可以看出 此型号H7的14bit最高采样率为单通道4M, 同时高速通道为每个ADC的 channel0 ~ 5;

本来我是打算通过3 个ADC交替达到12M的, 但是ADC3仅有的高速通道还都被 USB的ULPI接口占用了,所以退而使用 2个ADC交替, 刚好 ADC1 和 ADC2 可以使用H7自带的 interleaved mode。

所以,接下来的实现方案为使用 STM32H7 自带的 交替采样模式来实现。

2. CubeMX配置
首先是M7 内核的配置, 这个我也不是很懂, 在我的试验中,就是一定要打开DCache,  无论是USB 还是 ADC, 如果不打开DChache,就会出现各种各样的问题。



时钟配置, 主频480M, ADC 72M, USB 48M:






ADC配置:

ADC1 和 ADC2 选择同一引脚, 我这里选择了PA6, 同时对应ADC1和ADC2 的 通道3



ADC1 配置为:

主要配置为:



Mode: Dual interleaved mode only, 这个是配置为双重交替采样

DMA Access Mode 启动 ,因为使用了 DMA

Delay between 2 sampling phases 是两次交替之间的延时,这个的选用可以看一下这篇文章:STM32G474 CubeMX + CLion双重ADC交替采样实现2M+2M = 4M_delay between 2 sampling phases-CSDN博客

但是我按照此文思路应该配置为 72M /8M = 9 cycle, 实际测出来却是3.5cycle分隔最正常,我猜这个的选用可能是按照 采样时间 + 转换时间 +Delay between 2 = 9 cycle 来计算(以我这个来看);但是从手册看, 光是采样+转换就用了9个周期了。。。



然后是 Clock prescaler 时钟预分配,这个是最抽象的, 从手册来看 ADC时钟最高是36M,但是我配置的72M时钟,在2分频得到的最高采样率只有4M, 反而在1分频下达到了理论上的最高8M,这点我到现在都很懵逼

其他就是常规配置, 我这边用的是连续转换和DMA 循环, 因为其他方法都发生了奇怪的问题,这个放最后说。

DMA配置如下:只需要开启ADC1的就可以了, ADC2在interleaved mode 下作为 从ADC 是跟随ADC1的



ADC2: 与 ADC1 保持一致



顺便提一下USB的配置, USB的配置非常简单,一点都不需要改动,只需要打开USB_OTG_HS

选择为Device, 再打开USB_Device选择为虚拟串口即可。





3. 代码
因为整体没什么功能,代码很简单, 基本就是启用ADC 和 USB 即可

USB: 包含头文件 "usbd_cdc_if.h", 就可以在 文件中使用CDC_Transmit_HS() 发送数据了, 接受到的数据可以到" usbd_cdc_if.c "里的 CDC_Receive_HS() 函数处理。

代码可以看看stm32Cubemx USB虚拟串口_stm32f407 usb虚拟串口 cubemx-CSDN博客

整体非常简单, 一个函数搞定。

ADC的启用: 前两段 ADCEx_Calibration 函数用来 校准ADC, 启动的时候, 需要先启动从ADC,再通过HAL_ADCEx_MultiModeStart_DMA() 来启动 主ADC。

  HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_FACTOR_LINEARITY_REGOFFSET, ADC_SINGLE_ENDED);
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_FACTOR_LINEARITY_REGOFFSET, ADC_SINGLE_ENDED);

  HAL_ADC_Start(&hadc2);
  HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t* )dmabuffer, data_len);
由于之前DMA配置的size是 word(32位, 将ADC1和ADC2 的两个 14bit数据,存到1个word里了), 所以在传输完成后,还需要加一步,将ADC1与ADC2的数据分离开。 在处理数据之前,需要使用SCB_InvalidateDCache_by_Addr() 这个函数的作用是把DChache中的现有数据无效化,保证我们读到的是重新加载的新数据。 这个貌似是H7系列带有DChache而特需的步骤。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{


    SCB_InvalidateDCache_by_Addr((uint32_t *) dmabuffer, 2048);


    for( i=0, j=0;j<data_len && i<data_len*2;i++)
    {
        adc_data=(dmabuffer[j] & 0x0000FFFF) ;
        i++;
        adc_data=((dmabuffer[j] >>16)) ;

        j++;
    }
    CDC_Transmit_HS((uint8_t* )adc_data, 2048);

}

4. 试验结果
1.    ADC为72M, 1分频, delay between 2 为 3.5 cycle
测试波形: 400k 正弦波



测试波形1M 正弦波:



2.   ADC为72M, 1分频, delay between 2 为 9 cycle
测试波形 400K 正弦波



3.   ADC为72M, 2分频, delay between 2 为 3.5 cycle
测试波形:400K 正弦波



从上面的试验来看, 配置为 ADC时钟72M  1分频,  2次采样间隔为3.5 cycle,  可以跑出比较好看的波形, 问题就是ADC时钟远超于手册给的最大时钟36M, 这点难以理解, 希望有大佬可以解解惑。

5. 其他

此外,还有一种方式为定时器作为触发源来触发ADC,相关文章:STM32H743/H723 三ADC交替触发采样,理论速度可达14MSPS+ - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!

我最开始采用的就是这个方法,设置定时器两个触发源为4M,上升沿触发,示波器测出如下:



但是在最终测试时, 波形在好与不好之间切换,以500K 正弦波测试,结果如图:





我已尽可能的减少ADC1和ADC2 的dma冲突,采取的DMA配置为 Normal, 即DMA采集完后停止,直到我代码重新启动ADC_DMA, 即便这样仍然是这样的现象; 给我的感觉像是 ADC1和ADC2的先后顺序时不时在改变,一直没有解决,最后换成使用H7自带的交替采样模式勉强跑起来。

这篇在ADC部分有很多的bug和没搞懂的东西,希望有懂的大佬能指点指点/(ㄒoㄒ)/~~
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2404_88276917/article/details/143108040

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1845

主题

15436

帖子

11

粉丝