我有一个
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