在某项目开发过程中,需要使用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
|