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

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

  • ADC简介
  • CubeMX配置
  • ADC初始化代码分析
  • 电压采集、串口打印
  • 参考资料

STM32 HAL库 CubeMX系列教程 目录

ADC简介

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

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

输入通道:
STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第1张图片
外部的 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配置

STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第2张图片
STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第3张图片
STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第4张图片
STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第5张图片

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左右
STM32 HAL库 CubeMX教程(七)ADC电压采集串口输出_第6张图片

参考资料

  1. 【野火】《STM32+HAL+库开发实战指南—基于F103-MINI》.pdf
  2. 硬石YS-F1Pro开发板开发手册(HAL库版本20170104更新).pdf

你可能感兴趣的:(STM32)