基于STM32H743的调试记录4——ADC1、2、3采样,DMA、BDMA 搬运处理

H7系列的单片机的ADC

相比于F1、F4系列的单片机,H7系列的单片机ADC功能全面的提升。ADC的采样精度由12位提高到16位,同时增加了差分电压采样功能。本文注重与应用,为了达到最大的端口利用率,使用如下配置,ADC1大部分通道,规则采样,DMA传输,ADC3全部通道,规则采样 BDNA传输。ADC2使用通道2,通道6进行查询采样。通道的分配使用STM32CubeMX进行分配,达到通道的利用最大化。

STM32CubeMX进行引脚分配

经过比较:按照如下分配 AC2 使用通道2、6;ADC1去除11号通道全开 ADC3全开单端信号采样模式通道数最多
在这里插入图片描述
在这里插入图片描述

ADC时钟设置30M;倍频系数如下

在这里插入图片描述

ADC1配置16通道规则循环采样,软件触发,DMA1通道7搬运数据

在这里插入图片描述

具体代码如下

ADC.H头文件定义接收数组

#ifndef _ADC_H
#define _ADC_H
#include "sys.h"

#define   BufferLenght   16*6    //16个通道每个采样6次取平均值 6次平均方便计算
#define   ADC3_BufferLenght   16*6
void ADC1_DMA_Init(void);
void ADC3_DMA_Init(void);
#endif

C文件
时钟设置

volatile u16  ADC_DualConvertedValueTab[BufferLenght];
u8 ADC1_DMA_FLAG=0;
volatile u16  ADC_DATA_GER[BufferLenght];
 GPIO_InitTypeDef GPIO_InitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
  ADC_HandleTypeDef ADC1_Handle;
  DMA_HandleTypeDef ADC1_DMA_Handle;
   ADC_HandleTypeDef ADC3_Handle;
  DMA_HandleTypeDef ADC3_DMA_Handle;

  ADC_MultiModeTypeDef ADC_MultiMode_Handle; 
  ADC_ChannelConfTypeDef ADC_CHan_conf_Handle; 
void ADC1_DMA_Init(void)
{

    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 2;
    PeriphClkInitStruct.PLL2.PLL2N = 12;
    PeriphClkInitStruct.PLL2.PLL2P = 5;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0.0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)  //调整ADC的输入时钟到 30M
    {
      Error_Handler();
    }
   __HAL_RCC_DMA1_CLK_ENABLE();             //DMA1时钟使能 
    __HAL_RCC_GPIOC_CLK_ENABLE();			//使能GPIOC时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();			//使能GPIOB时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();			//使能GPIOF时钟

    __HAL_RCC_ADC12_CLK_ENABLE(); //使能ADC1 时

引脚通道的映射

  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

   

    // GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    // GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    // GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    // GPIO_InitStruct.Pull = GPIO_NOPULL;
    // HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

DMA通道的配置

 /* ADC1 DMA Init */
    /* ADC1 Init */
    ADC1_DMA_Handle.Instance = DMA1_Stream7;
    ADC1_DMA_Handle.Init.Request = DMA_REQUEST_ADC1;                        //ADC1 发送DMA
    ADC1_DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;                  //存储器到外设
    ADC1_DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;                       //外设非增量模式
    ADC1_DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;                           //存储器增量模式
    ADC1_DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;      //外设数据长度:16位
    ADC1_DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;         //存储器数据长度:16位
    ADC1_DMA_Handle.Init.Mode = DMA_CIRCULAR;                                 //外设循环模式
    ADC1_DMA_Handle.Init.Priority = DMA_PRIORITY_LOW;                         //中等优先级  
    ADC1_DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    ADC1_DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    ADC1_DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
    ADC1_DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&ADC1_DMA_Handle) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(&ADC1_Handle,DMA_Handle,ADC1_DMA_Handle);  //将DMA与ADC1 联系起来接收 DMA

    HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 9, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);

ADC1的配置

 ADC1_Handle.Instance = ADC1;
  ADC1_Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6; //6分频,ADCCLK=PER_CK/4=30/6=5MHZ
  ADC1_Handle.Init.Resolution = ADC_RESOLUTION_16B;       	//16位模式
  ADC1_Handle.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式
  ADC1_Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;      //关闭EOC中断
  ADC1_Handle.Init.LowPowerAutoWait = DISABLE;                    //自动低功耗关闭			
  ADC1_Handle.Init.ContinuousConvMode = ENABLE;                   //连续转换

  ADC1_Handle.Init.NbrOfConversion = 4;                        //规则转换通道 数量        

  ADC1_Handle.Init.DiscontinuousConvMode = DISABLE;                   //禁止不连续采样模式
  ADC1_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;            //软件触发
  ADC1_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;   //使用软件触发
  ADC1_Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;  //规则通道的数据仅仅保存在DMA
 // ADC1_Handle.Init.BoostMode   = DISABLE; //
  ADC1_Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;      	/* ADC转换溢出的话,覆盖ADC的数据寄存器 */
  ADC1_Handle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  ADC1_Handle.Init.OversamplingMode = DISABLE;//过采样关闭
  if (HAL_ADC_Init(&ADC1_Handle) != HAL_OK)
  {
    Error_Handler();
  }

规则通道的配置



 /** Configure the ADC multi-mode
  */
  ADC_MultiMode_Handle.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&ADC1_Handle, &ADC_MultiMode_Handle) != HAL_OK)
  {
    Error_Handler();
  }

  ADC_CHan_conf_Handle.Channel = ADC_CHANNEL_3;
  ADC_CHan_conf_Handle.Rank = ADC_REGULAR_RANK_1;
  ADC_CHan_conf_Handle.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
  ADC_CHan_conf_Handle.SingleDiff = ADC_SINGLE_ENDED;
  ADC_CHan_conf_Handle.OffsetNumber = ADC_OFFSET_NONE;
  ADC_CHan_conf_Handle.Offset = 0;
  ADC_CHan_conf_Handle.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC_CHan_conf_Handle) != HAL_OK)
  {
    Error_Handler();
  }

只贴上一个通道的代码 其余通道配置相同,修改采样的序号和指定通道即可 同时好在ADC的配置里修改通道的数量
代码中使用的是4个通道

/* 校准ADC,采用偏移校准 */

if (HAL_ADCEx_Calibration_Start(&ADC1_Handle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_ADC_Start_DMA(&ADC1_Handle,(uint32_t *)ADC_DualConvertedValueTab,BufferLenght);
//开启ADC的采样
}

DMA的中断处理 因为有DNMA传输过半中断 个人认为传输偶数的数据量比较好减少出错,然后定义循环次数是6测取偶数


void DMA1_Stream7_IRQHandler(void)
{
	/* 传输完成中断 */
  if((DMA1->HISR&DMA_FLAG_TCIF3_7)!=RESET)
  {
		/*
		   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
		   2、进入传输完成中断,当前DMA正在使用缓冲区的前半部分,用户可以操作后半部分。
		*/
    SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADC_DualConvertedValueTab[BufferLenght/2]), BufferLenght);	
		ADC1_DMA_FLAG=1;
		/* 清除标志 */
		DMA1->HIFCR = DMA_FLAG_TCIF3_7;
  }
	/* 半传输完成中断 */    
	if((DMA1->HISR & DMA_FLAG_HTIF3_7) != RESET)
	{
		/*
		   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
		   2、进入半传输完成中断,当前DMA正在使用缓冲区的后半部分,用户可以操作前半部分。
		*/
		SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADC_DualConvertedValueTab[0]), BufferLenght);	       
		/* 清除标志 */
		DMA1->HIFCR = DMA_FLAG_HTIF3_7;
	}

 /* 传输错误中断 */
	if((DMA1->HISR & DMA_FLAG_TEIF3_7) != RESET)
	{
		/* 清除标志 */
		DMA1->HIFCR = DMA_FLAG_TEIF3_7;
	}

	/* 直接模式错误中断 */
	if((DMA1->HISR & DMA_FLAG_DMEIF3_7) != RESET)
	{
		/* 清除标志 */
		DMA1->HIFCR = DMA_FLAG_DMEIF3_7;
	}

 
}

然后数据的使用 判断DMA传输是否完场 转运 取平均值 即可

if(ADC1_DMA_FLAG==1)
		{
			ADC1_DMA_FLAG=0;
			for(ADC_TEMP=0;ADC_TEMP<BufferLenght;ADC_TEMP++)
			{
				ADC_DATA_GER[ADC_TEMP]=ADC_DualConvertedValueTab[ADC_TEMP];
			}
		}
		// if(ADC3_DMA_FLAG==1)
		// {
		// 	ADC3_DMA_FLAG=0;
		// 	for(ADC_TEMP=0;ADC_TEMP<ADC3_BufferLenght;ADC_TEMP++)
		// 	{
		// 		ADC3_DATA_GER[ADC_TEMP]=ADC3_DualConvertedValueTab[ADC_TEMP];
		// 	}
		// }
		TEMP_InitSrtes.Fuel_level=(ADC_DATA_GER[0]+ADC_DATA_GER[4]+ADC_DATA_GER[8]+ADC_DATA_GER[12]+ADC_DATA_GER[16]+ADC_DATA_GER[20])/6;

ADC3的代码大致相同有个别细微之处需要注意

详见代码

void ADC3_DMA_Init(void)
{

    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 2;
    PeriphClkInitStruct.PLL2.PLL2N = 12;
    PeriphClkInitStruct.PLL2.PLL2P = 5;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0.0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)  //调整ADC的输入时钟到 30M
    {
      Error_Handler();
    }
  __HAL_RCC_ADC3_CLK_ENABLE();
  __HAL_RCC_BDMA_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6
                        |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

  HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_OPEN);
  HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_OPEN);


    /* ADC3 DMA Init */
  /* ADC3 Init */
  ADC3_DMA_Handle.Instance = BDMA_Channel0;
  ADC3_DMA_Handle.Init.Request = BDMA_REQUEST_ADC3;                         //ADC3 发送  BDMA
  ADC3_DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;                    //存储器到外设
  ADC3_DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;                        //外设非增量模式
  ADC3_DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;                             //存储器增量模式
  ADC3_DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;         //外设数据长度:16位
  ADC3_DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;              //存储器数据长度:16位
  ADC3_DMA_Handle.Init.Mode = DMA_CIRCULAR;                                   //外设循环模式
  ADC3_DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH;                           //中等优先级  
  ADC3_DMA_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* BDMA不支持FIFO阀值设置 */ 
  ADC3_DMA_Handle.Init.MemBurst            = DMA_MBURST_SINGLE;       /* BDMA不支持存储器突发 */ 
  ADC3_DMA_Handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* BDMA不支持外设突发 */ 
  if (HAL_DMA_Init(&ADC3_DMA_Handle) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&ADC3_Handle,DMA_Handle,ADC3_DMA_Handle);

  HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 12, 0);
  HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);

  ADC3_Handle.Instance = ADC3;
  ADC3_Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6; //6分频,ADCCLK=PER_CK/4=30/6=5MHZ
  ADC3_Handle.Init.Resolution = ADC_RESOLUTION_16B;             //16位模式
  ADC3_Handle.Init.ScanConvMode = ADC_SCAN_ENABLE;              //扫描模式
  ADC3_Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;         //关闭EOC中断
  ADC3_Handle.Init.LowPowerAutoWait = DISABLE;                //自动低功耗关闭	
  ADC3_Handle.Init.ContinuousConvMode = ENABLE;                //连续转换

  ADC3_Handle.Init.NbrOfConversion = 4;                        //规则转换通道 数量     
  
  ADC3_Handle.Init.DiscontinuousConvMode = DISABLE;             //禁止不连续采样模式
  ADC3_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;        //软件触发
  ADC3_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;     //使用软件触发
  ADC3_Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;   //规则通道的数据仅仅保存在DMA
 // ADC3_Handle.Init.BoostMode             = DISABLE;                            /* ADC时钟低于20MHz的话,可以禁止boost */
  ADC3_Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;            /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
 // ADC3_Handle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  ADC3_Handle.Init.OversamplingMode = DISABLE;   //过采样关闭
  if (HAL_ADC_Init(&ADC3_Handle) != HAL_OK)
  {
    Error_Handler();
  }
  delay_ms(100);
  if (HAL_ADCEx_Calibration_Start(&ADC3_Handle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
  {
    Error_Handler();
  }
   /** Configure Regular Channel
  */
  ADC_CHan_conf_Handle.Channel = ADC_CHANNEL_15;
  ADC_CHan_conf_Handle.Rank = ADC_REGULAR_RANK_1;
  ADC_CHan_conf_Handle.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
  ADC_CHan_conf_Handle.SingleDiff = ADC_SINGLE_ENDED;
  ADC_CHan_conf_Handle.OffsetNumber = ADC_OFFSET_NONE;
  ADC_CHan_conf_Handle.Offset = 0;
  ADC_CHan_conf_Handle.OffsetRightShift       = DISABLE;           /* 禁止右移 */
  ADC_CHan_conf_Handle.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&ADC3_Handle, &ADC_CHan_conf_Handle) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  ADC_CHan_conf_Handle.Channel = ADC_CHANNEL_16;
  ADC_CHan_conf_Handle.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&ADC3_Handle, &ADC_CHan_conf_Handle) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  ADC_CHan_conf_Handle.Channel = ADC_CHANNEL_TEMPSENSOR;
  ADC_CHan_conf_Handle.Rank = ADC_REGULAR_RANK_3;
  ADC_CHan_conf_Handle.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  ADC_CHan_conf_Handle.SingleDiff = ADC_SINGLE_ENDED;
  ADC_CHan_conf_Handle.OffsetNumber = ADC_OFFSET_NONE;
  ADC_CHan_conf_Handle.Offset = 0;
  ADC_CHan_conf_Handle.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&ADC3_Handle, &ADC_CHan_conf_Handle) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  ADC_CHan_conf_Handle.Channel = ADC_CHANNEL_VREFINT;
  ADC_CHan_conf_Handle.Rank = ADC_REGULAR_RANK_4;
  ADC_CHan_conf_Handle.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  ADC_CHan_conf_Handle.SingleDiff = ADC_SINGLE_ENDED;
  ADC_CHan_conf_Handle.OffsetNumber = ADC_OFFSET_NONE;
  ADC_CHan_conf_Handle.Offset = 0;
  ADC_CHan_conf_Handle.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&ADC3_Handle, &ADC_CHan_conf_Handle) != HAL_OK)
  {
    Error_Handler();
  }


  HAL_ADC_Start_DMA(&ADC3_Handle,(uint32_t *)ADC3_DualConvertedValueTab,ADC3_BufferLenght);

}

注意事项

ADC3只能使用BDMA ,数据访问的区域有限定,在0x38000000之后;
所以要在MPU中设定存储空间 这个之前文章有介绍。

 /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;
  MPU_InitStruct.BaseAddress = 0x38000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
 
  HAL_MPU_ConfigRegion(&MPU_InitStruct);

接收数组的声明

u8 ADC3_DMA_FLAG=0;
volatile u16  ADC3_DATA_GER[ADC3_BufferLenght];
volatile u16  ADC3_DualConvertedValueTab[ADC3_BufferLenght] __attribute__((at(0x38000000))); //MDK中定义在RAM地址0x38000100 的ADC3采样数组


void BDMA_Channel0_IRQHandler(void)
{

  /* 传输完成中断 */
  if((BDMA->ISR&BDMA_FLAG_TC0)!=RESET)
  {
		/*
		   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
		   2、进入传输完成中断,当前DMA正在使用缓冲区的前半部分,用户可以操作后半部分。
		*/
    SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADC3_DualConvertedValueTab[ADC3_BufferLenght/2]), ADC3_BufferLenght);	
   // SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADC3_DualConvertedValueTab[0]), ADC3_BufferLenght);	
		ADC3_DMA_FLAG=1;
		/* 清除标志 */
		BDMA->IFCR = BDMA_FLAG_TC0;
  }
	/* 半传输完成中断 */    
	if((BDMA->ISR & BDMA_FLAG_HT0) != RESET)
	{
		/*
		   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
		   2、进入半传输完成中断,当前DMA正在使用缓冲区的后半部分,用户可以操作前半部分。
		*/
		SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADC3_DualConvertedValueTab[0]), ADC3_BufferLenght);	       
		/* 清除标志 */
		BDMA->IFCR = BDMA_FLAG_HT0;
	}

 /* 传输错误中断 */
	if((BDMA->ISR & BDMA_FLAG_TE0) != RESET)
	{
		/* 清除标志 */
		BDMA->IFCR = BDMA_FLAG_TE0;
	}

	/* 直接模式错误中断 */
	if((BDMA->ISR & BDMA_FLAG_GL0) != RESET)
	{
		/* 清除标志 */
		BDMA->IFCR = BDMA_FLAG_GL0;
	}

}
  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32H743的RCC(Reset and Clock Control)模块是用于控制系统的复位和时钟的模块。RCC模块可以配置和控制系统时钟源、时钟分频器以及各个外设的时钟使能。具体的RCC配置和使用方法可以参考STM32H743编程手册的相关章节。\[1\] 在RCC模块中,有一个RCC_D3AMR寄存器,该寄存器用于配置RCC的自动模式(Autonomous mode)。在Stop模式下,只有部分“L”字号的外设可以通过RCC的自动模式和BDMA来保持超低功耗和数据采集。而且,只有STM32L系列和STM32H系列的芯片才支持这种低功耗设置。\[3\] 如果你需要更具体的关于STM32H743的RCC模块的信息,可以参考STM32H743编程手册中的相关章节。\[1\] #### 引用[.reference_title] - *1* *3* [STM32H743 RCC时钟树的形象化理解](https://blog.csdn.net/NoDistanceY/article/details/103835987)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32H743串口同时收发问题总结](https://blog.csdn.net/m0_58644391/article/details/121777248)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值