[综合信息] N32H474 ADC4无DMA请求?数据手册解密

[复制链接]
小海师 发表于 2025-8-26 08:44 | 显示全部楼层 |阅读模式
     在某项目开发过程中,需要使用ADC检测电压引脚是73脚ADC34_IN8,使用了DMA获取数据,在调试过程中发现DMA无法获取数据?




        ADC3使用DMA获取数据正常,debug半天最终在数据手册中找到说明,只有ADC1、ADC3能够产生DMA请求,但是在17.8章节说明独立ADC模式时ADC4同样拥有独立的DMA功能。所以寄存器中的说明可能是多ADC模式下只有ADC1与ADC3才能产生DMA请求。







        DMA、ADC初始化配置如下:ADC3使用DMA1_CH5 、ADC2使用DMA1_CH6、ADC4使用DMA1_CH7,其他设置相同,在demo板上仿真时ADC4实际未工作?修改国民技术的demo程序ADC4可以正常运行。

static void DMA_ADC_Config(void)
{
    DMA_DeInit(DMA_ADC3_CH);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&ADC3->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)(&ADC_ConvertedValue[0].w_var);
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = 3;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.MemoryInc      = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_HALFWORD;
    DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_HALFWORD;
    DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(DMA_ADC3_CH, &DMA_InitStructure);


    DMA_DeInit(DMA_ADC2_CH);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&ADC2->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)(&ADC_ConvertedValue[3].w_var);
    DMA_InitStructure.BufSize        = 2;
    DMA_Init(DMA_ADC2_CH, &DMA_InitStructure);

    DMA_DeInit(DMA_ADC4_CH);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&ADC4->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)(&ADC_ConvertedValue[5].w_var);
    DMA_InitStructure.BufSize        = 5;
    DMA_Init(DMA_ADC4_CH, &DMA_InitStructure);


    DMA_RequestRemap(DMA_REMAP_ADC4,DMA_ADC4_CH,ENABLE);
    DMA_RequestRemap(DMA_REMAP_ADC3,DMA_ADC3_CH,ENABLE);
    DMA_RequestRemap(DMA_REMAP_ADC2,DMA_ADC2_CH,ENABLE);

    /* Enable DMA1 channel1 */
    DMA_EnableChannel(DMA_ADC4_CH, ENABLE);
    DMA_EnableChannel(DMA_ADC3_CH, ENABLE);
    DMA_EnableChannel(DMA_ADC2_CH, ENABLE);

}
/**
*\*\name    ADC_Initial.
*\*\fun     ADC_Initial program.
*\*\return  none
**/
void ADC_Initial(void)
{
    ADC_InitType ADC_InitStructure;
    /* ADC3 configuration ------------------------------------------------------*/
    ADC_InitStructure.WorkMode       = ADC_WORKMODE_INDEPENDENT;
    ADC_InitStructure.MultiChEn      = ENABLE;
    ADC_InitStructure.ContinueConvEn = ENABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = 3;
    ADC_InitStructure.Resolution     = ADC_DATA_RES_12BIT;
    ADC_Init(ADC3, &ADC_InitStructure);

    ADC_InitStructure.ChsNumber      = 2;
    ADC_Init(ADC2, &ADC_InitStructure);

    ADC_InitStructure.ChsNumber      = 5;
    ADC_Init(ADC4, &ADC_InitStructure);

    /* ADC3 regular channel12 configuration */
    ADC_ConfigRegularChannel(ADC3, ADC3_Channel_13_PF5, 1, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC3, ADC3_Channel_02_PE9, 2, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC3, ADC3_Channel_06_PE8, 3, ADC_SAMP_TIME_CYCLES_13_5);

    /* ADC2 regular channel12 configuration */
    ADC_ConfigRegularChannel(ADC2, ADC2_Channel_11_PC5, 1, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC2, ADC2_Channel_12_PB2, 2, ADC_SAMP_TIME_CYCLES_13_5);

    /* ADC4 regular channel12 configuration */
    ADC_ConfigRegularChannel(ADC4, ADC4_Channel_00_PF10, 1, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC4, ADC4_Channel_08_PD11, 2, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC4, ADC4_Channel_09_PD12, 3, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC4, ADC4_Channel_10_PD13, 4, ADC_SAMP_TIME_CYCLES_13_5);
    ADC_ConfigRegularChannel(ADC4, ADC4_Channel_11_PD14, 5, ADC_SAMP_TIME_CYCLES_13_5);

    /* Enable ADC4 */
    ADC_Enable(ADC4, ENABLE);
    /* Enable ADC3 */
    ADC_Enable(ADC3, ENABLE);
    /* Enable ADC2 */
    ADC_Enable(ADC2, ENABLE);


    /*Check ADC Ready*/
    while(ADC_GetFlagStatus(ADC3,ADC_FLAG_RDY) == RESET)
        ;
    /* Start ADC3 calibration */
    ADC_CalibrationOperation(ADC3,ADC_CALIBRATION_SINGLE_MODE);

    /* Check the end of ADC3 calibration */
    while (ADC_GetCalibrationStatus(ADC3,ADC_CALIBRATION_SINGLE_MODE))
        ;
    /* Enable ADC3 DMA */
    ADC_SetDMATransferMode(ADC3, ADC_MULTI_REG_DMA_EACH_ADC);

    /*Check ADC Ready*/
    while(ADC_GetFlagStatus(ADC4,ADC_FLAG_RDY) == RESET)
        ;
    /* Start ADC4 calibration */
    ADC_CalibrationOperation(ADC4,ADC_CALIBRATION_SINGLE_MODE);

    /* Check the end of ADC1 calibration */
    while (ADC_GetCalibrationStatus(ADC4,ADC_CALIBRATION_SINGLE_MODE))
        ;
    /* Enable ADC4 DMA */
    ADC_SetDMATransferMode(ADC4, ADC_MULTI_REG_DMA_EACH_ADC);

    /*Check ADC Ready*/
    while(ADC_GetFlagStatus(ADC2,ADC_FLAG_RDY) == RESET)
        ;
    /* Start ADC2 calibration */
    ADC_CalibrationOperation(ADC2,ADC_CALIBRATION_SINGLE_MODE);

    /* Check the end of ADC2 calibration */
    while (ADC_GetCalibrationStatus(ADC2,ADC_CALIBRATION_SINGLE_MODE))
    ;
    /* Enable ADC2 DMA */
    ADC_SetDMATransferMode(ADC2, ADC_MULTI_REG_DMA_EACH_ADC);

}



        对比发现需要调用函数ADC_EnableSoftwareStartConv(ADC4, ENABLE);ADC4才能正常工作。

#define ADC_REG_SWSTART_MASK                      (ADC_CTRL2_SWSTRRCH)/**  Start conversion of regular channels  **/


/**
*\*\name    ADC_EnableSoftwareStartConv.
*\*\fun     Enables or disables the selected ADC software start conversion ..
*\*\param   ADCx :
*\*\          - ADC1
*\*\          - ADC2
*\*\          - ADC3
*\*\          - ADC4
*\*\param   Cmd :
*\*\          - ENABLE   
*\*\          - DISABLE  
*\*\return  none
**/
void ADC_EnableSoftwareStartConv(ADC_Module* ADCx, FunctionalState Cmd)
{
    if (Cmd != DISABLE)
    {
        /* Enable the selected ADC conversion on external event and start the selected
           ADC conversion */
        ADCx->CTRL2 |= ADC_REG_SWSTART_MASK;
    }
    else
    {
        /* Disable the selected ADC conversion on external event and stop the selected
           ADC conversion */
        ADCx->CTRL2 &= (~ADC_REG_SWSTART_MASK);
    }
}



函数的作用是开启转换规则通道。




疑问:为什么ADC4需要软件开启转换而ADC2、ADC3不需要?
————————————————
版权声明:本文为CSDN博主「吗喽不休息」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_58123084/article/details/149367578

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

本版积分规则

67

主题

210

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部