硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4712|回复: 21
收起左侧

[ADC] STM32H743adc采样率上不去的问题

  [复制链接]

1

主题

11

回帖

14

积分

新手上路

积分
14
发表于 2020-9-16 20:32:23 | 显示全部楼层 |阅读模式
这是ADC.c的源码,看看有没有配置错误,定时器3触发ADC采样,我想用3MHz采样率采集信号,可是上不去。

#include "adc.h"
#include "dma.h"


ALIGN_32BYTES (__attribute__ ((at(0x24000000))) __IO uint16_t ADC_ConvertedValue = 0);
extern float ADC_vol;

ADC_HandleTypeDef ADC1_Handle;
ADC_HandleTypeDef ADC2_Handle;
DMA_HandleTypeDef hdma_adc;
ADC_MultiModeTypeDef ADC_multimode;

static void ADC_GPIO_Mode_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    __GPIOB_CLK_ENABLE();
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    /* 配置为模拟输入,不需要上拉电阻 */
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
   
}
static void ADC_Mode_Config(void)
{
    ADC_ChannelConfTypeDef ADC_Config;
  
//    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;  
//    /*            配置ADC3时钟源             */
//    /*    HSE Frequency(Hz)    = 25000000   */                                             
//    /*         PLL_M                = 5     */
//    /*         PLL_N                = 160   */
//    /*         PLL_P                = 25    */
//    /*         PLL_Q                = 2     */
//    /*         PLL_R                = 2     */
//    /*     ADC_ker_clk         = 32000000   */
//    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
//    RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
//    RCC_PeriphClkInit.PLL2.PLL2M = 5;
//    RCC_PeriphClkInit.PLL2.PLL2N = 180;
//    RCC_PeriphClkInit.PLL2.PLL2P = 8;
//    RCC_PeriphClkInit.PLL2.PLL2Q = 2;
//    RCC_PeriphClkInit.PLL2.PLL2R = 2;
//    RCC_PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
//    RCC_PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
//    RCC_PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
//    HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);  
//        
        __HAL_RCC_ADC12_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();

         //选择DMA1的Stream1
    hdma_adc.Instance = DMA1_Stream0;
    //ADC1的DMA请求
    hdma_adc.Init.Request = DMA_REQUEST_ADC1;
    //传输方向:外设-》内存
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
    //外设地址不自增
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
    //内存地址不自增
    hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
    //外设数据宽度:半字
    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    //内存数据宽度:半字
    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    //DMA循环传输
    hdma_adc.Init.Mode = DMA_CIRCULAR;
    //DMA的软件优先级:低
    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;
    //FIFO模式关闭
    hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    //DMA初始化
    HAL_DMA_Init(&hdma_adc);
    //hdma_adc和ADC_Handle.DMA_Handle链接
    __HAL_LINKDMA(&ADC1_Handle,DMA_Handle,hdma_adc);


    ADC1_Handle.Instance = ADC1;
    //使能Boost模式
    ADC1_Handle.Init.BoostMode = ENABLE;
    //ADC时钟1分频
//    ADC1_Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
    ADC1_Handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    //使能连续转换模式
    ADC1_Handle.Init.ContinuousConvMode = DISABLE;
    //数据存放在数据寄存器中
    ADC1_Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
    //关闭不连续转换模式
    ADC1_Handle.Init.DiscontinuousConvMode = DISABLE;
    ADC1_Handle.Init.NbrOfConversion       = 1;                             /* 使用了1个转换通道 */
    //单次转换
    ADC1_Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;   
    ADC1_Handle.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_TRGO;
    ADC1_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
//        ADC1_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
//    ADC1_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    //关闭低功耗自动等待
    ADC1_Handle.Init.LowPowerAutoWait = DISABLE;
    //数据溢出时,覆盖写入
    ADC1_Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    //不使能过采样模式
    ADC1_Handle.Init.OversamplingMode = DISABLE;
    //分辨率为:12bit
    ADC1_Handle.Init.Resolution = ADC_RESOLUTION_12B;
    //不使能多通道扫描
    ADC1_Handle.Init.ScanConvMode = DISABLE;
    //初始化 ADC_MASTER
    HAL_ADC_Init(&ADC1_Handle);
    /* 校准ADC,采用偏移校准 */
    HAL_ADCEx_Calibration_Start(&ADC1_Handle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);

    ADC_Config.Channel = ADC_CHANNEL_5;
    //转换顺序为1
    ADC_Config.Rank = ADC_REGULAR_RANK_1;
    ADC_Config.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    //不使用差分输入的功能
    ADC_Config.SingleDiff = ADC_SINGLE_ENDED ;
    ADC_Config.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */
    ADC_Config.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
    HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC_Config);
    //使能ADC1
    ADC_Enable(&ADC1_Handle);
    //使能DMA,此函数会开启DMA中断,需要用户自行配置DMA中断优先级
   HAL_ADC_Start_DMA(&ADC1_Handle, (uint32_t*)&ADC_ConvertedValue, 1);
        
}

void Rheostat_DMA_NVIC_Config(void)
{
    __HAL_RCC_DMA1_CLK_ENABLE();
    HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
void ADC_Init(void)
{   
    ADC_GPIO_Mode_Config();
    ADC_Mode_Config();
    Rheostat_DMA_NVIC_Config();
    HAL_ADC_Start(&ADC1_Handle);
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2020-9-16 21:39:42 | 显示全部楼层
你开着DMA中断,还配置的每采集一个ADC值就一次DMA中断。

你的处理器处理的过来么。。。。

HAL_ADC_Start_DMA(&ADC1_Handle, (uint32_t*)&ADC_ConvertedValue, 1);
回复

使用道具 举报

1

主题

11

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2020-9-16 21:48:03 | 显示全部楼层
eric2013 发表于 2020-9-16 21:39
你开着DMA中断,还配置的每采集一个ADC值就一次DMA中断。

你的处理器处理的过来么。。。。

那我改改试试,看看效果
回复

使用道具 举报

1

主题

11

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2020-9-16 22:33:02 | 显示全部楼层
eric2013 发表于 2020-9-16 21:39
你开着DMA中断,还配置的每采集一个ADC值就一次DMA中断。

你的处理器处理的过来么。。。。

这个HAL_ADC_Start_DMA函数,最后那个变量代表的是个数是吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2020-9-17 09:55:57 | 显示全部楼层
bao292387701 发表于 2020-9-16 22:33
这个HAL_ADC_Start_DMA函数,最后那个变量代表的是个数是吗?

是的。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2021-12-23 22:48:52 | 显示全部楼层

不是说最后一位设置必须为32的倍数的吗
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2021-12-24 01:05:39 | 显示全部楼层
梦幻的帅帅 发表于 2021-12-23 22:48
不是说最后一位设置必须为32的倍数的吗

对齐是指的Cache处理函数。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2021-12-24 09:26:28 | 显示全部楼层
uint16_t ADCxValues[4];       
if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 4) != HAL_OK)  { Error_Handler(__FILE__, __LINE__); }
    /*
       使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍
    */
    SCB_InvalidateDCache_by_Addr((uint32_t *)ADCxValues,  sizeof(ADCxValues));
我看例程是这样的,ADC一共采集了四次,赋值到ADCxValues数组, sizeof(ADCxValues)这个值就是4*32嘛?
还有就是我看到例程就每个通道只采集了一次,这边有必要采集多次求平均值嘛,数值会不会更精确点。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2021-12-24 09:35:15 | 显示全部楼层
本帖最后由 梦幻的帅帅 于 2021-12-24 09:43 编辑

这个4是代表的一共采样四次吧,四个通道每个通道一次吧
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2021-12-24 09:58:00 | 显示全部楼层
再请教一个问题,我是8通道采集,ADC1  6通道,ADC2  2通道,要求每个通道的采集频率都是1KHz,  ADC1的6个通道是不是依次循环采集的,是不是就意味着ADC1的采集频率要大于6KHz,ADC2和ADC1可以同时采集的吧
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2021-12-25 09:36:00 | 显示全部楼层
梦幻的帅帅 发表于 2021-12-24 09:26
uint16_t ADCxValues[4];        
if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 4) != HAL_OK)  { ...

1、要做32字节整数倍,大家用最好是整数倍。
2、这个例子有个对比的例子,ADC硬件过采样。不需要用户去做多通道求平均。
QQ截图20211225093623.png


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2021-12-25 09:37:39 | 显示全部楼层
梦幻的帅帅 发表于 2021-12-24 09:35
这个4是代表的一共采样四次吧,四个通道每个通道一次吧

对的。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2021-12-25 09:41:53 | 显示全部楼层
梦幻的帅帅 发表于 2021-12-24 09:58
再请教一个问题,我是8通道采集,ADC1  6通道,ADC2  2通道,要求每个通道的采集频率都是1KHz,  ADC1的6个 ...

1、理解有误,ADC1的6个通道是依次循环采集的。 比如你定时器触发1KHz处理一次,每1ms触发一次,触发一次后是6个通道依次转换完毕了,不是触发一次转换1个通道。

2、可以定时器控制同时触发。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2022-7-6 15:04:26 | 显示全部楼层
image.png 硬汉兄,这边我一直有个疑问,32字节对齐 ADCxValues[4]数组 ,然后 sizeof(ADCxValues)这个值需要是32字节的整数倍,但是实际应该是一个元素四个字节,一个数组4个元素,一共才16个字节,也不是32字节的整数倍呀,新人求指教!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2022-7-7 03:00:39 | 显示全部楼层
梦幻的帅帅 发表于 2022-7-6 15:04
硬汉兄,这边我一直有个疑问,32字节对齐 ADCxValues[4]数组 ,然后 sizeof(ADCxValues)这个值需要是32字 ...

我这里的不够专业,实际应用务必满足这个要求。可以将数组补0(多定义几个数组变量)来满足32字节整数倍。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2022-7-7 09:03:07 | 显示全部楼层
eric2013 发表于 2022-7-7 03:00
我这里的不够专业,实际应用务必满足这个要求。可以将数组补0(多定义几个数组变量)来满足32字节整数倍 ...

1:意思是我可以定义为ADCxValues[8],实际只有前四个有,后四个为0,是这样嘛
2:这第二个参数什么意义呢,和第一个参数有什么必要的联系嘛,
3:比如像现在定义了ADCxValues[4] ,sizeof(ADCxValues) =16,我可以设置第二个参数的值为sizeof(ADCxValues)*2嘛,强行设为32的倍数,这样可行不
4:我看ADC双缓冲的程序,定义了ADCxValues[128] ,sizeof(ADCxValue)=4*128,满足32字节的倍数,但是我看到程序里第二个参数直接设置的是128,我已经混乱了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2022-7-7 12:54:28 | 显示全部楼层
梦幻的帅帅 发表于 2022-7-7 09:03
1:意思是我可以定义为ADCxValues[8],实际只有前四个有,后四个为0,是这样嘛
2:这第二个参数什么意义 ...

1、直接定义为ADCxValues[8]的话,就已经是4*8 = 32字节了。
2、同上。
3.  不好,这个会影响你没有定义的其它地址数据。
4.  专业设计,一定要配套。严格按照这个来。
回复

使用道具 举报

0

主题

19

回帖

19

积分

新手上路

积分
19
发表于 2022-7-7 14:36:02 | 显示全部楼层
eric2013 发表于 2022-7-7 12:54
1、直接定义为ADCxValues[8]的话,就已经是4*8 = 32字节了。
2、同上。
3.  不好,这个会影响你没有定 ...


这个ADC双缓冲的例程,定义的是 uint16_t ADCxValues[128]; SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADCxValues[64]), 128);第二个参数为嘛是128呢,怎么不是siezof(ADCxValues)=4*64=256呢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2022-7-8 11:31:15 | 显示全部楼层
梦幻的帅帅 发表于 2022-7-7 14:36
这个ADC双缓冲的例程,定义的是 uint16_t ADCxValues[128]; SCB_InvalidateDCache_by_Addr((uint32_t * ...

双缓冲。仅用了一半。
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2023-11-18 20:52:33 | 显示全部楼层
请问,你这个问题解决了吗,我使用STM32H750VBT6,双ADC同步采样想达到16bit 2M的采样率,ADC时钟36MHz,使用定时器触发,但是ADC采样率只有1M,把ADC超频到72MHz才能达到2MHz,这是为啥呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106678
QQ
发表于 2023-11-20 00:18:56 | 显示全部楼层
xhj 发表于 2023-11-18 20:52
请问,你这个问题解决了吗,我使用STM32H750VBT6,双ADC同步采样想达到16bit 2M的采样率,ADC时钟36MHz,使 ...


看看注意这个问题没有。

STM32H743/H750的Y版和V版芯片ADC的主频区别
https://www.armbbs.cn/forum.php? ... d=118747&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2023-11-20 10:13:35 | 显示全部楼层
eric2013 发表于 2023-11-20 00:18
xhj 发表于 2023-11-18 20:52
请问,你这个问题解决了吗,我使用STM32H750VBT6,双ADC同步采样想达到16bit ...

是这个原因导致的,没注意到芯片的版本,找了好久的原因,谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 09:12 , Processed in 0.291477 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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