STM32H7使用Cubemx配置多通道+Cache+ADC3+BDMA+ADC1+ADC2+DMA,解决ADC不能实时更新问题。

时钟配置如上        

这里千万注意一个个配下去,参数多容易配错,而且要注意一下Rank这里,如果是像我一样多通道的话,channel一定要配置好,如果是默认的话可能会有重复配置一个通道的情况,我当时就踩了这个坑。

BMDA如上

MPU如下配置

在adc.c中加入如下代码。具体ADC转化逻辑为电压逻辑可以自己写也可以参考这。

/* USER CODE BEGIN 1 */
void adc_init(void)//在adc.c文件下插入写到/* USER CODE BEGIN 1 */下和/* USER CODE END 1 */中间
{
    MX_ADC1_Init();    //初始化调用放这里, 确保在MX_DMA_Init()初始化后面
    MX_ADC2_Init();    //初始化调用放这里, 确保在MX_DMA_Init()初始化后面
    MX_ADC3_Init();    //在MX_BDMA_Init()初始化后面
    
    //HAL_Delay(100);    //有地方说这里可以等等电压稳定后再校准
 
    if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
    {
        Error_Handler();
    }
    
    if (HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
    {
        Error_Handler();
    }
 
    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_dmabuff, adc1_buff_Size) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc2_dmabuff, adc2_buff_Size) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc3_dmabuff, adc3_buff_Size) != HAL_OK)
    {
        Error_Handler();
    }
}
 
 
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
  if(hadc->Instance == ADC1) {
//      flag0++;
      SCB_InvalidateDCache_by_Addr((uint32_t *) &adc1_dmabuff[0], adc1_buff_Size);
  }else if(hadc->Instance == ADC2) {
//      flag1++;
      SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2_dmabuff[0], adc2_buff_Size);
  }
  else if(hadc->Instance == ADC3) {
//      flag2++;
      SCB_InvalidateDCache_by_Addr((uint32_t *) &adc3_dmabuff[0], adc3_buff_Size);
  }
}
 
//ADC的DMA的完成中断回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    uint8_t j;
    j=1;
    ADC.flag_adc1=j;
    ADC.flag_adc2=j;
    ADC.flag_adc3=j;
    if(hadc->Instance == ADC1) {
        SCB_InvalidateDCache_by_Addr((uint32_t *) &adc1_dmabuff[adc1_buff_Size/2], adc1_buff_Size);
//        HAL_ADC_Stop_DMA(&hadc1);//add//sxq3.13
   }  else if(hadc->Instance == ADC2) {
       SCB_InvalidateDCache_by_Addr((uint32_t *) &adc2_dmabuff[adc2_buff_Size/2], adc2_buff_Size);
//        HAL_ADC_Stop_DMA(&hadc2);//add//sxq3.13
   }else if(hadc->Instance == ADC3) {
       SCB_InvalidateDCache_by_Addr((uint32_t *) &adc3_dmabuff[adc3_buff_Size/2], adc3_buff_Size);
//        HAL_ADC_Stop_DMA(&hadc3);//add//sxq3.13
   }
}
 
void Scan_ADC(void)
{
    uint32_t j;
    SCB_DisableDCache();
    if(ADC.flag_adc1==1){    //判断是不是ADC1进入的中断回调
        for(j=0;j<adc1_buff_Size;j++){ 
            ADC1_VALUE[j]=adc1_dmabuff[j];
            ADC.ADC1_V[j]=(float)(ADC1_VALUE[j]*3.3/65536.0);
        }
        ADC.flag_adc1=0;
    }
    if(ADC.flag_adc2==1)
    {
       for(j=0;j<adc2_buff_Size;j++){
            ADC2_VALUE[j]=adc2_dmabuff[j];
            ADC.ADC2_V[j]=(float)(ADC2_VALUE[j]*3.3/65536.0);
        } 
        ADC.flag_adc2=0;
    }
    if(ADC.flag_adc3==1)
    {
      for(j=0;j<adc3_buff_Size;j++){
            ADC3_VALUE[j]=adc3_dmabuff[j];
            ADC.ADC3_V[j]=(float)(ADC3_VALUE[j]*3.3/4096.0);
        } 
        ADC.flag_adc3=0;      
    } 
    SCB_EnableDCache();
}
/* USER CODE END 1 */

——在adc.c文件中需要注意的地方需要添加代码——在void MX_ADC3_Init(void)结尾的用户可以添加的代码区域添加上。

 /* USER CODE BEGIN ADC3_Init 2 */
      //ADD FOR adc3 the //ADC3只能使用BDMA ,数据访问的区域有限定,在0x38000000之后;    
    /** Initializes and configures the Region and the memory to be protected */
  MPU_Region_InitTypeDef MPU_InitStruct = {0};;
  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);    
 
  /* USER CODE END ADC3_Init 2 */ 

——还有一个值得注意的地方——在adc.h中需要添加代码——这一步是因为BDMA的特殊,在D3区域,看参考手册可以知道D3区域地址在0x38000000。需要改变一下它的地址

 
/* USER CODE BEGIN Includes */
typedef struct {//配置使用的ADC数据存储区域结构体
    
     volatile uint32_t flag_adc1; 
     volatile uint32_t flag_adc2;
     volatile uint32_t flag_adc3;
     float ADC1_V[adc1_buff_Size];
     float ADC2_V[adc2_buff_Size];
     float ADC3_V[adc3_buff_Size];
    
}ADC_VALUE;
ADC_VALUE ADC;
extern ADC_VALUE ADC;
 
volatile uint16_t ADC1_VALUE[adc1_buff_Size];
volatile uint16_t ADC2_VALUE[adc2_buff_Size];
volatile uint16_t ADC3_VALUE[adc3_buff_Size];
//32字节对齐(地址+大小)
//adc1_data指定到 AXI SRAM 的0x24000000
//adc3_data指定到 SRAM4 的0x38000000
ALIGN_32BYTES (uint16_t adc1_dmabuff[adc1_buff_Size]) __attribute__((section(".ARM.__at_0x24000080")));
ALIGN_32BYTES (uint16_t adc2_dmabuff[adc2_buff_Size]) __attribute__((section(".ARM.__at_0x24000060")));
ALIGN_32BYTES (uint16_t adc3_dmabuff[adc3_buff_Size]) __attribute__((section(".ARM.__at_0x38000000")));
/* USER CODE END Includes */
 
extern ADC_HandleTypeDef hadc1;
 
extern ADC_HandleTypeDef hadc2;
 
extern ADC_HandleTypeDef hadc3;
 
/* USER CODE BEGIN Private defines */
 
/* USER CODE END Private defines */
 
void MX_ADC1_Init(void);
void MX_ADC2_Init(void);
void MX_ADC3_Init(void);
 
/* USER CODE BEGIN Prototypes */
void adc_init(void);//头文件声明
void Scan_ADC(void);//头文件声明

最后在主函数那边加入adc_init()和大循环中加入Scan_ADC()即可。

具体参考文章为 

STM32+DMA多路+ADCHAL库函数+cubemax配置+部分解释_hal_adc_start_dma 多个通道-CSDN博客

  • 57
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
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 ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值