我正在尝试将
STM32H743ZI的 ADC 设置为 5 通道连续扫描。5 次扫描将用于
输入电压 - 通道 0
输入电流 - 通道 1
输出电压 - 通道 2
输出电流 - 通道 3
内部温度传感器 - 通道 18
本质上,我只是希望 ADC 连续扫描这 5 个通道,并让 DMA 将其传输到缓冲区中,以便软件可以读取它。我想读取缓冲区的方式是通过轮询,因为我正在使用 RTOS。
我遇到的问题是 ADC 的 EOS 标志和 DMA1 TC4 标志正在设置,但数据没有传输到 DMA 缓冲区。然而,我看到数据在 ADC3 的 DR 寄存器中移动。
我仔细检查了 DMA,内存地址在 DMA 可以查看的正确内存区域内。我不知道发生了什么,因为我以前从未真正使用过 ADC 进行顺序扫描。
如果有人能看到我是否设置错误或者我是否必须做某事,我很期待。例如,我没有使用中断,因为我提到我正在使用轮询,但是我正在使用 DMA。我还需要启用 DMA4 TC 中断吗?等等等等。我只想让 ADC 在 DMA 传输数据的同时永远扫描,我随时都可以轮询。
任何建议表示赞赏
设置 GPIO、DMA、ADC 的低电平寄存器
- void ADC_helper_function::enable(int * RxBuffer) {
- LL_DMA_InitTypeDef ADC_Config_DMA;
- LL_GPIO_InitTypeDef ADC_Config_GPIO;
- LL_ADC_InitTypeDef ADC_Config_init;
- LL_ADC_REG_InitTypeDef ADC_Config_REG;
- LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC);
- LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
- LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
- LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
- LL_ADC_StructInit(&ADC_Config_init);
- LL_ADC_REG_StructInit(&ADC_Config_REG);
- LL_GPIO_StructInit(&ADC_Config_GPIO);
- LL_DMA_StructInit(&ADC_Config_DMA);
- //Configure GPIOA
- ADC_Config_GPIO.Mode = LL_GPIO_MODE_ANALOG;
- ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- ADC_Config_GPIO.Pin = LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
- ADC_Config_GPIO.Pull = LL_GPIO_PULL_UP;
- ADC_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- LL_GPIO_Init(GPIOC, &ADC_Config_GPIO);
- //Configure GPIOC
- ADC_Config_GPIO.Mode = LL_GPIO_MODE_ANALOG;
- ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- ADC_Config_GPIO.Pin = LL_GPIO_PIN_9 | LL_GPIO_PIN_7;
- ADC_Config_GPIO.Pull = LL_GPIO_PULL_UP;
- ADC_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- LL_GPIO_Init(GPIOF, &ADC_Config_GPIO);
- ADC_Config_DMA.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
- ADC_Config_DMA.FIFOMode = LL_DMA_FIFOMODE_DISABLE;
- ADC_Config_DMA.MemBurst = LL_DMA_MBURST_SINGLE;
- ADC_Config_DMA.MemoryOrM2MDstAddress = (uint32_t)RxBuffer;
- ADC_Config_DMA.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
- ADC_Config_DMA.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
- ADC_Config_DMA.Mode = LL_DMA_MODE_CIRCULAR;
- ADC_Config_DMA.NbData = 5;
- ADC_Config_DMA.PeriphBurst = LL_DMA_PBURST_SINGLE;
- ADC_Config_DMA.PeriphOrM2MSrcAddress = (uint32_t)&ADC1->DR;
- ADC_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_WORD;
- ADC_Config_DMA.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
- ADC_Config_DMA.PeriphRequest = LL_DMAMUX1_REQ_ADC3;
- ADC_Config_DMA.Priority = LL_DMA_PRIORITY_LOW;
- //Interrupt: DMA
- LL_DMA_Init(DMA1, LL_DMA_STREAM_4, &ADC_Config_DMA);
- //Configure ADC
- ADC_Config_init.LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
- ADC_Config_init.LowPowerMode = LL_ADC_LP_MODE_NONE;
- ADC_Config_init.Resolution = LL_ADC_RESOLUTION_16B;
- LL_ADC_Init(ADC3, &ADC_Config_init);
- ADC_Config_REG.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
- ADC_Config_REG.DataTransferMode = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
- ADC_Config_REG.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
- ADC_Config_REG.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS;
- ADC_Config_REG.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
- LL_ADC_REG_Init(ADC3, &ADC_Config_REG);
- LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_0);
- LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_1);
- LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_2);
- LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_3);
- LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_TEMPSENSOR);
- LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_1 | LL_ADC_CHANNEL_2 | LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);
- LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_0 | LL_ADC_CHANNEL_1 | LL_ADC_CHANNEL_2 | LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_1CYCLE_5);
- LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_387CYCLES_5);
- LL_ADC_SetCommonPathInternalCh(ADC3_COMMON, LL_ADC_PATH_INTERNAL_TEMPSENSOR);
- LL_ADC_DisableDeepPowerDown(ADC3);
- LL_RCC_PLL2_SetM(4);
- LL_RCC_PLL2_SetN(9);
- LL_RCC_PLL2_SetP(4);
- LL_RCC_PLL2_SetFRACN(6144);
- LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
- LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
- LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL2P);
- LL_RCC_PLL2FRACN_Enable();
- LL_RCC_PLL2P_Enable();
- LL_RCC_PLL2_Enable();
- while ((LL_RCC_PLL2_IsReady == 0)) {
- }
- LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
- LL_ADC_EnableInternalRegulator(ADC3);
- LL_ADC_Enable(ADC3);
- LL_ADC_REG_StartConversion(ADC3);
- }
轮询 ADC 缓冲区的任务
- void ADC::ADC_Daemon(void * parameter) {
- int tempSensor = 0;
- while(1) {
- vTaskDelay(ADC_Checkin_Interval/portTICK_PERIOD_MS);
- if ((LL_ADC_IsActiveFlag_EOS(ADC3)) && (LL_DMA_IsActiveFlag_TC4(DMA1))) {
- tempSensor = dataStructure->getRxBuffer()[3];
- LL_ADC_ClearFlag_EOS(ADC3);
- LL_DMA_ClearFlag_TC4(DMA1);
- }
- }
- }