ST意法半导体
直播中

王超

7年用户 1293经验值
私信 关注
[问答]

在STM32G070 ADC连续转换模式下DMA循环缓冲区停止工作咋办

我有一个 STM32g070 的代码,它将 adc 配置为连续转换模式,定序器设置为完全可配置,扫描转换模式,dma 连续请求,序列转换结束,过采样模式右移到 5 和比率 32x。
此外,我将 dma 配置为外围设备到内存方向的循环模式,使用 1200 半字大小的数组缓冲区 uint16_t,并启用半传输、完整传输和错误传输中断。
转换开始时,半传输上升,但缓冲区完全满,传输完成后,缓冲区被覆盖。
这里的代码:
  • void my_adc_start_scanning_channels_with_dma(void){
  •         __IO uint32_t backup_setting_adc_dma_transfer = 0U;
  •         __IO uint32_t wait_loop_index = 0UL;
  •         if(LL_ADC_IsInternalRegulatorEnabled(MY_ADC_HANDLER) != 0){
  •                 if(LL_ADC_IsEnabled(MY_ADC_HANDLER)){
  •                         LL_ADC_Disable(MY_ADC_HANDLER);
  •                         while(LL_ADC_IsDisableOngoing(MY_ADC_HANDLER) != 0);
  •                 }
  •                 LL_ADC_DisableInternalRegulator(MY_ADC_HANDLER);
  •         }
  •         if(LL_DMA_IsEnabledChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL) != 0){
  •                 LL_DMA_DisableChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
  •         }
  • //        LL_DMAMUX_SetRequestID(MY_ADC_DMA_HANDLER, LL_DMAMUX_CHANNEL_0, LL_DMAMUX_REQ_ADC1);
  •         LL_DMA_SetMode(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_DMA_MODE_CIRCULAR);
  •         LL_DMA_SetDataTransferDirection(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  •         LL_DMA_SetPeriphAddress(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_ADC_DMA_GetRegAddr(MY_ADC_HANDLER, LL_ADC_DMA_REG_REGULAR_DATA));
  •         LL_DMA_SetMemoryAddress(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, (uint32_t)my_adc_buffer);
  •         LL_DMA_SetDataLength(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, 1200);
  •         /* Enable DMA transfer interruption: transfer complete */
  •         LL_DMA_EnableIT_TC(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
  •         /* Enable DMA transfer interruption: half transfer */
  •         LL_DMA_EnableIT_HT(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
  •         /* Enable DMA transfer interruption: transfer error */
  •         LL_DMA_EnableIT_TE(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
  •         flag_my_adc_transfer_complete = 0;
  •         LL_DMA_EnableChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
  •         // enabling voltage regulator for adc
  •         LL_ADC_EnableInternalRegulator(MY_ADC_HANDLER);
  •         /* Delay for ADC stabilization time */
  •         /* Wait loop initialization and execution */
  •         /* Note: Variable divided by 2 to compensate partially              */
  •         /*       CPU processing cycles, scaling in us split to not          */
  •         /*       exceed 32 bits register capacity and handle low frequency. */
  •         wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
  •         while (wait_loop_index != 0UL){
  •           wait_loop_index--;
  •         };
  •         /* Disable ADC DMA transfer request during calibration */
  •         /* Note: Specificity of this STM32 series: Calibration factor is          */
  •         /*       available in data register and also transferred by DMA.          */
  •         /*       To not insert ADC calibration factor among ADC conversion data   */
  •         /*       in DMA destination address, DMA transfer must be disabled during */
  •         /*       calibration.                                                     */
  •         backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(MY_ADC_HANDLER);
  •         LL_ADC_REG_SetDMATransfer(MY_ADC_HANDLER, LL_ADC_REG_DMA_TRANSFER_NONE);
  •         // Run ADC self calibration
  •         LL_ADC_StartCalibration(MY_ADC_HANDLER);
  •         while(LL_ADC_IsCalibrationOnGoing(MY_ADC_HANDLER) != 0);
  •         /* Restore ADC DMA transfer request after calibration */
  •         LL_ADC_REG_SetDMATransfer(MY_ADC_HANDLER, backup_setting_adc_dma_transfer);
  •     /* Delay between ADC end of calibration and ADC enable.                   */
  •     /* Note: Variable divided by 2 to compensate partially                    */
  •     /*       CPU processing cycles (depends on compilation optimization).     */
  •     wait_loop_index = (ADC_DELAY_CALIB_ENABLE_CPU_CYCLES >> 1);
  •     while(wait_loop_index != 0){
  •       wait_loop_index--;
  •     }
  •     /* Enable ADC */
  •         LL_ADC_Enable(MY_ADC_HANDLER);
  •         while (LL_ADC_IsActiveFlag_ADRDY(MY_ADC_HANDLER) == 0);
  •         LL_ADC_REG_StartConversion(MY_ADC_HANDLER);
  • }12





回帖(1)

王竹

2022-12-19 15:29:07
当您在调试器中停止 mcu 时,ADC 和 DMA继续运行。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分