[蓝桥杯嵌入式]hal库 stm32 ADC多通道指定通道采集解决办法,采用单通道,非扫描,非连续

文章讲述了在蓝桥杯嵌入式学习中,如何在非DMA情况下实现多通道ADC的可控扫描,通过HAL库调整通道配置,实现在单次转换非连续模式下读取不同通道的电压。作者借鉴了江协科技的方法,通过ADC初始化代码动态修改通道,简化了多通道操作并保持了代码移植性。
摘要由CSDN通过智能技术生成

问题:在蓝桥杯嵌入式学习过程中,在多通道采集PB5、PB11这里遇到了问题.

网上做法大部分都是

非DMA:单次转换+扫描模式+不连续转换+间断模式。然后在代码里面按分配的顺序依次扫描

DMA:单次转换+扫描模式+连续转换。然后在代码里面按分配的顺序依次扫描

需求

如果不DMA的话,在多个通道的情况下,你无法知道当前读取的是哪个通道,扫描过程比较不确定,一旦出现问题,那这次扫描就会出问题。

而DMA的配置又比较麻烦,而且不需要如此高效率,不方便移植和修改。

需要一个在同一个ADC外设的情况下,也能指定读取某个通道的办法。

解决

这里感谢江协科技的思路。

 【STM32入门教程-2023版 细致讲解 中文字幕】P22的41:44位置

我使用HAL库成功实现

非DMA:单次转换+非扫描模式

可控制的多通道扫描办法

思路:每次ADC转换将通道修改为对应的读取通道

查看源码,可知,单次扫描的初始化代码中,有配置通道的过程。

既然这样,每次我需要读取其它通道时,就改变需要读取的通道不就行了嘛

如下面ADC初始化源码:

其中红框部分就是ADC初始化的通道初始化,这里指定了通道11。

每次读取ADC值前,将红框部分的代码拿出来用于通道的选择就行了。

具体实现步骤

cubemx配置:

引脚选择

外设配置

外设参数配置

可以看出,这就是单次ADC单通道的的配置。无DMA,无NVIC。

生成工程,打开源码打开void MX_ADC1_Init(void)

应该是这样

红框部分就是我们要借用的代码。

代码实现

下面是最开始的单通道读取代码

//ADC单通道读取,单次转换,非连续,非扫描
double getADC(ADC_HandleTypeDef *pin)
{
    unsigned int value;
    HAL_ADC_Start(pin);
    HAL_ADC_PollForConversion(pin,0xffff);
    value = HAL_ADC_GetValue(pin);
    return value*3.3/4096;
}

下面是基于单通道优化后的多通道的读取代码:


//ADC多通道读取,单次转换,非连续,非扫描
double getADCByChannel(ADC_HandleTypeDef *pin,unsigned char channel)
{
  ADC_ChannelConfTypeDef sConfig = {0}; //建立结构体
  if(channel == 11)sConfig.Channel = ADC_CHANNEL_11;//将通道修改为通道11
  else if(channel == 5)sConfig.Channel = ADC_CHANNEL_5;//将通道修改为通道5
  sConfig.Rank = ADC_REGULAR_RANK_1;//ADC的第一个常规转换
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;//每次转换的采样时间为2.5个时钟周期
  sConfig.SingleDiff = ADC_SINGLE_ENDED;//了ADC的输入模式为单端
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//不使用偏移校准,下同
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(pin, &sConfig) != HAL_OK)//初始化通道和ADC
  {
    Error_Handler();
  }
    
    unsigned int value;
    HAL_ADC_Start(pin);//开始转换
    HAL_ADC_PollForConversion(pin,0xffff);//等待完成
    value = HAL_ADC_GetValue(pin);//读取转换置
    HAL_ADC_Stop(pin);//关闭转换
    return value*3.3/4096;//返回计算值
}

之后在主函数调用读取

 ADC11_value = getADCByChannel(&hadc1,11);//打开ASC1,通道11的电压读取
ADC5_value = getADCByChannel(&hadc1,5);//打开ASC1,通道5的电压读取

读取后通过串口打印还是屏幕显示都可

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
HAL库中,使用ADC连续多通道采集需要进行以下步骤: 1. 配置ADC时钟和DMA ```c hdma_adc.Init.Request = DMA_REQUEST_0; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_adc); __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); ``` 2. 配置ADC通道采样时间 ```c ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; HAL_ADC_ConfigChannel(&hadc1, &sConfig); ``` 3. 配置ADC连续模式和多通道模式 ```c hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.NbrOfDiscConversion = 0; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 2; hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; HAL_ADC_Init(&hadc1); ``` 4. 启动ADC和DMA ```c HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_data, 2); ``` 其中,`adc_data`是一个数组,存储采集到的多通道数据。这个数组的大小应该至少是 `2 * N`,其中 `N` 是采集周期的数量。 请注意,以上代码仅供参考,具体的实现可能因为硬件和软件环境的不同而有所不同。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值