STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出

STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出


STM32 HAL库 CubeMX系列教程 目录

ADC简介

STM32f103 系列有 3 个 ADC,精度为 12 位,每个 ADC 最多有 18 个通道,包括 16 个外部通道和 2 个内部信号源。

ADC 的输入电压范围为: 0~3.3V

输入通道:
在这里插入图片描述
外部的 16 个通道在转换的时候又分为规则通道和注入通道,我们一般使用规则通道即可。

ADC 转换可以由ADC 控制寄存器 2: ADC_CR2 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候停止转换。还可以通过内部定时器触发和外部 IO 触发等触发源来触发AD转换。

ADC 输入时钟 ADC_CLK 由 PCLK2 经过分频产生,可以是 2/4/6/8 分频 ,分频后最大是 14M。一般我们设置 PCLK2=HCLK=72M ,那么6分频后最大就是12M

ADC时钟周期就是 1/ADC_CLK。 采样周期最小是 1.5 个 时钟周期,也就是采样一次的最短时间。

ADC转换时间 = 采样时间 +12.5 个周期,即最短转换时间为14个周期。ADC时钟为12M的话最短的转换时间为 1.17us。

CubeMX配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ADC初始化代码分析

  1. ADC_HandleTypeDef
    ADC_HandleTypeDef是一个ADC的句柄结构体,stm32每一个外设都有一个这样的句柄,我们通过对给结构体的参数赋初值,就完成了外设的初始化了。
typedef struct
{
	ADC_TypeDef                   *Instance; //寄存器基地址
	ADC_InitTypeDef               Init; //ADC初始化
	DMA_HandleTypeDef             *DMA_Handle; //DMA指针
	HAL_LockTypeDef               Lock; //互斥锁
	__IO uint32_t                 State; //状态变量
	__IO uint32_t                 ErrorCode; //保存错误代码的变量
}ADC_HandleTypeDef;

我们主要对ADC_InitTypeDef Init进行初始化,这也是一个结构体。

  1. ADC_InitTypeDef
typedef struct
{
	  uint32_t DataAlign; //数据对齐方式
	  uint32_t ScanConvMode; //是否使用扫描模式
	  uint32_t ContinuousConvMode; //单一/连续模式 
	  uint32_t NbrOfConversion; //AD 转换通道数目 
	  uint32_t DiscontinuousConvMode; //是否使用间断模式 
	  uint32_t NbrOfDiscConversion; //间断模式中一个组的转换通道的数目 
	  uint32_t ExternalTrigConv; //外部触发选择 
}ADC_InitTypeDef;
  1. ADC_ChannelConfTypeDef
    ADC通道配置结构体
typedef struct { 
	uint32_t Channel; //通道选择
	uint32_t Rank; //转换顺序
	uint32_t SamplingTime; //采样周期
}ADC_ChannelConfTypeDef;
  1. adc.c
void MX_ADC1_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};//
    //ADC1初始化
    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;//单通道不使用扫描模式
    hadc1.Init.ContinuousConvMode = ENABLE;//连续模式
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件触发
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;//数据右对齐
    hadc1.Init.NbrOfConversion = 1; 
    //通道初始化
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
}

//ADC硬件初始化
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_ADC1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
  /**ADC1 GPIO Configuration    
    PA1     ------> ADC1_IN1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    /* ADC1 interrupt Init */
    HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
}

电压采集、串口打印

  1. 重定向printf
#define user_main_printf(format, ...) printf( format "\r\n", ##__VA_ARGS__)
int fputc(int ch, FILE *f){
	uint8_t temp[1] = {ch};
	HAL_UART_Transmit(&huart1, temp, 1, 0xffff);
return ch;
}
  1. 定义相关变量,使能AD转换完成中断
/* USER CODE BEGIN PV */
uint16_t ADC_value; //AD转换值
float Real_value; //实际电压值
/* USER CODE END PV */
HAL_ADC_Start_IT(&hadc1);
  1. 编写中断服务函数,读取AD转换值
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADC_value = HAL_ADC_GetValue(&hadc1);
}
  1. 主函数编写
while (1)
{  
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9);//指示AD转换正常完成
      Real_value=(float)(ADC_value)/4096*3.3;//计算实际电压值4096=2^12
      user_main_printf("The ADC_value is %d",ADC_value);
      user_main_printf("The Real_value is %f\n\n",Real_value); 
      user_main_printf(" ");
      HAL_Delay(500);
}

至此程序就完成了,连接好USB转串口模块。首先将ADC1转换通道1,即PA1与3.3V电压相连,然后拔掉3.3V供电,将PA0悬空,此时电压为1.6V左右
在这里插入图片描述

参考资料

  1. 【野火】《STM32+HAL+库开发实战指南—基于F103-MINI》.pdf
  2. 硬石YS-F1Pro开发板开发手册(HAL库版本20170104更新).pdf
### 回答1: STM32F103 HAL库提供了多种方式来实现ADC(模数转换器)的多通道采集,其中一种常见的方式是使用中断来进行采集。下面我将以简洁的方式介绍如何通过HAL库实现ADC中断方式的多通道采集。 首先,我们需要初始化ADC和对应的GPIO引脚。通过调用HAL_ADC_Init和HAL_ADC_MspInit函数来初始化ADC,以及调用HAL_GPIO_Init函数来初始化GPIO引脚。确保将GPIO引脚设置为ADC模式并使能对应的ADC时钟。 接下来,我们需要配置ADC。通过调用HAL_ADC_ConfigChannel函数来配置需要采集的通道,可以选择多个ADC通道。通过调用HAL_ADC_Start_IT函数来启动ADC的中断采集模式。 然后,我们需要重写HAL_ADC_ConvCpltCallback函数,该函数将在ADC转换完成时被调用。在该函数中,我们可以通过HAL_ADC_GetValue函数获取转换结果,并进行相应的处理。可以使用switch语句来根据转换结果的通道选择进行不同的处理操作。 最后,在主函数中,我们可以通过调用HAL_ADC_Start函数来启动ADC转换,并在合适的地方开启中断。同时,需要添加一个循环来保证程序能够一直运行,例如使用while(1)循环。 通过以上步骤,我们就可以使用STM32F103 HAL库的中断方式实现ADC的多通道采集。在中断回调函数中,我们可以根据需要对采集到的数据进行处理,例如发送到串口或者进行其他计算。这样可以方便地实现多通道的同时采集和处理。 ### 回答2: 在使用STM32F103 HAL库进行多通道ADC中断采集时,需要进行以下步骤: 1. 初始化ADC模块:首先,需要对ADC模块进行初始化,包括设置时钟、通道、转换时间、采样时间以及中断方式。 例子:`HAL_ADC_Init(&hadc1);` 2. 配置ADC通道:通过`HAL_ADC_ConfigChannel`函数配置ADC的多个通道,指定采集的顺序和采样时间。 例子:`sConfig.Channel = ADC_CHANNEL_1; // 设置第一个通道为ADC1` 3. 配置转换触发方式:可以选择软件触发或外部触发。如果选择软件触发,在启动转换之前需要调用`HAL_ADC_Start_IT`函数。 例子:`HAL_ADC_Start_IT(&hadc1);` 4. 实现ADC中断回调函数:在中断发生时,会调用预先定义的中断回调函数。在这个回调函数中,你可以读取ADC数据并作进一步的处理。 例子: ```c void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) // ADC1通道的中断 { uint32_t adc_value = HAL_ADC_GetValue(hadc); // 获取ADC转换值 // 进一步的处理操作 } } ``` 5. 启用ADC中断:通过调用`HAL_NVIC_EnableIRQ`函数启用ADC中断。 例子:`HAL_NVIC_EnableIRQ(ADC1_2_IRQ);` 6. 启动ADC转换:触发ADC转换,可以通过软件触发或外部触发。如果选择软件触发,则可以调用`HAL_ADC_Start_IT`函数。 例子:`HAL_ADC_Start_IT(&hadc1);` 以上是使用STM32F103 HAL库通过中断方式进行多通道ADC采集的基本步骤。请根据实际情况进行配置和编写代码。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值