Erwinchn 发表于 2019-3-19 16:07:28

STM32F030 ADC多通道DMA方式采集配置问题

我用的是STM32F030使用多通道DMA采集,发现F0芯片使用cubemx配置跟F1一样的,但是就是读值全都不对,原来F1没有遇到过这种问题,有用过的大神看下配置上有什么需要改的吗?之前有个帖子说自己添加通道,我也添加过了读值还是不对,只配置一个通道设置跟多通道一模一样读值就正确的,应该就是多通道添加有问题。

void MX_ADC_Init(void)

{

ADC_ChannelConfTypeDef sConfig = {0};



/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc.Instance = ADC1;

hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;

hadc.Init.Resolution = ADC_RESOLUTION_12B;

hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;

hadc.Init.LowPowerAutoWait = DISABLE;

hadc.Init.LowPowerAutoPowerOff = DISABLE;

hadc.Init.ContinuousConvMode = ENABLE;

hadc.Init.DiscontinuousConvMode = DISABLE;

hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc.Init.DMAContinuousRequests = ENABLE;

hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;

if (HAL_ADC_Init(&hadc) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_1;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_2;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_3;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_4;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}

/** Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_5;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

    Error_Handler();

}



}



这个是添加通道设置

void init_ADCRank(void)

{

ADC_ChannelConfTypeDef sConfig;

sConfig.Channel = ADC_CHANNEL_1;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

HAL_ADC_ConfigChannel(&hadc, &sConfig);





sConfig.Channel = ADC_CHANNEL_2;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

HAL_ADC_ConfigChannel(&hadc, &sConfig);





sConfig.Channel = ADC_CHANNEL_3;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

HAL_ADC_ConfigChannel(&hadc, &sConfig);





sConfig.Channel = ADC_CHANNEL_4;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

HAL_ADC_ConfigChannel(&hadc, &sConfig);



sConfig.Channel = ADC_CHANNEL_5;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

HAL_ADC_ConfigChannel(&hadc, &sConfig);



}


:)

xmshao 发表于 2019-3-19 17:20:38

你也检查下DMA的配置有没有问题,比方源端、目的端数据宽带是否一致;
源端、目的端是否都是DMA可以访问到的

Erwinchn 发表于 2019-3-19 17:27:03

xmshao 发表于 2019-3-19 17:20
你也检查下DMA的配置有没有问题,比方源端、目的端数据宽带是否一致;
源端、目的端是否都是DMA可以访问到 ...

uint32_t AD_Value; //用来存放ADC转换结果,也是DMA的目标地址,每通道采N次,M为通道数
HAL_ADC_Start_DMA(&hadc, *AD_Value, N);
带宽大小都一样的啊

wenyangzeng 发表于 2019-3-19 21:04:52

本帖最后由 wenyangzeng 于 2019-3-19 21:17 编辑

用CubeMX生成的ADC初始化代码是:
void MX_ADC_Init(void)
{

ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
    */
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = ENABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_2;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_3;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_4;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

    /**Configure for the selected ADC regular channel to be converted.
    */
sConfig.Channel = ADC_CHANNEL_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}



}无需再来一个 Int_ADCRank()函数。因为:
如果所有通道转换速率相同,

sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
于是下面紧跟的其他通道都默认上面的设置。

然后需要:
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_Value, ADC_Number*ADC_Channel);
才能启动ADC读数据。每次DMA传输的数据是转换次数×ADC通道数,保存在ADC_Value[]数组中。





Erwinchn 发表于 2019-3-20 08:58:01

wenyangzeng 发表于 2019-3-19 21:04
用CubeMX生成的ADC初始化代码是:
无需再来一个 Int_ADCRank()函数。因为:
如果所有通道转换速率相同,


谢谢大神,原来是转换次数×ADC通道数那个地方没设置对,太感谢了

Kevin201707 发表于 2019-3-20 10:00:31

HAL_ADC_Start_DMA(&hadc, *AD_Value, N);是这里有问题吧?

Erwinchn 发表于 2019-3-21 14:25:47

Kevin201707 发表于 2019-3-20 10:00
HAL_ADC_Start_DMA(&hadc, *AD_Value, N);是这里有问题吧?

是的就是这里的问题,应该是单通道采集次数*通道数

speciallyyj 发表于 2019-4-23 15:37:17

我也是这里的问题。读出来的值都不对,但是我不是用的二维数组去存放ADC的值,我是用一维数组,通过DMA连续读取,不断覆盖之前的数据,求教~!!!
页: [1]
查看完整版本: STM32F030 ADC多通道DMA方式采集配置问题