工作原理是输出模拟量电压值,只需要使用stm32adc读取电压再转换一下即可

本代码中,水位传感器连接在PA0,可通过宏定义快速设置电压区间和水位之间的关系
water_level.c
cpp
/**
******************************************************************************
* @file water_level.c
* @brief 水位传感器驱动实现
******************************************************************************
* @attention
*
* 水位传感器通过ADC读取PA0引脚电压值
* 水位范围:0-5cm
* 对应电压:0.65V-1.9V
*
******************************************************************************
*/
/* 包含头文件 */
#include "water_level.h"
/* 私有定义 */
#define WATER_LEVEL_PIN GPIO_PIN_0
#define WATER_LEVEL_PORT GPIOA
#define WATER_LEVEL_ADC_CHANNEL ADC_CHANNEL_0
/* 水位传感器参数 */
#define WATER_MIN_VOLTAGE 0.8f // 最小水位对应电压 (V)
#define WATER_MAX_VOLTAGE 1.6f // 最大水位对应电压 (V)
#define WATER_MIN_DEPTH 0.0f // 最小水位深度 (mm)
#define WATER_MAX_DEPTH 50.0f // 最大水位深度 (mm)
#define ADC_REFERENCE_VOLTAGE 3.3f // ADC参考电压 (V)
#define ADC_RESOLUTION 4096 // ADC分辨率 (12位)
/* 私有变量 */
static ADC_HandleTypeDef hadc1;
/**
* @brief 水位传感器初始化
* @param 无
* @retval HAL状态
*/
HAL_StatusTypeDef WaterLevel_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* 使能GPIO时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* 使能ADC1时钟 */
__HAL_RCC_ADC1_CLK_ENABLE();
/* 配置GPIO引脚 */
GPIO_InitStruct.Pin = WATER_LEVEL_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(WATER_LEVEL_PORT, &GPIO_InitStruct);
/* 配置ADC */
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
return HAL_ERROR;
}
/* 配置ADC通道 */
sConfig.Channel = WATER_LEVEL_ADC_CHANNEL;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
return HAL_ERROR;
}
/* ADC校准 */
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @brief 读取水位原始ADC值
* @param 无
* @retval ADC原始值 (0-4095)
*/
uint16_t WaterLevel_GetRawADC(void)
{
uint16_t adcValue = 0;
/* 启动ADC转换 */
HAL_ADC_Start(&hadc1);
/* 等待转换完成 */
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
/* 读取ADC转换结果 */
adcValue = HAL_ADC_GetValue(&hadc1);
}
/* 停止ADC转换 */
HAL_ADC_Stop(&hadc1);
return adcValue;
}
/**
* @brief 读取水位深度
* @param 无
* @retval 水位深度,单位:mm (0-50mm)
*/
float WaterLevel_GetDepth(void)
{
uint16_t adcValue = WaterLevel_GetRawADC();
float voltage = (float)adcValue * ADC_REFERENCE_VOLTAGE / ADC_RESOLUTION;
float depth;
/* 将电压值转换为水位深度 */
if (voltage <= WATER_MIN_VOLTAGE)
{
depth = WATER_MIN_DEPTH;
}
else if (voltage >= WATER_MAX_VOLTAGE)
{
depth = WATER_MAX_DEPTH;
}
else
{
/* 线性插值计算水位深度 */
depth = WATER_MIN_DEPTH + (voltage - WATER_MIN_VOLTAGE) *
(WATER_MAX_DEPTH - WATER_MIN_DEPTH) /
(WATER_MAX_VOLTAGE - WATER_MIN_VOLTAGE);
}
return depth;
}
water_level.h
cpp
/**
******************************************************************************
* @file water_level.h
* @brief 水位传感器驱动头文件
******************************************************************************
* @attention
*
* 水位传感器通过ADC读取PA0引脚电压值
* 水位范围:0-5cm
* 对应电压:0.65V-1.9V
*
******************************************************************************
*/
#ifndef __WATER_LEVEL_H
#define __WATER_LEVEL_H
#ifdef __cplusplus
extern "C" {
#endif
/* 包含头文件 */
#include "main.h"
#include "stm32f1xx_hal.h"
/* 函数声明 */
/**
* @brief 水位传感器初始化
* @param 无
* @retval HAL状态
*/
HAL_StatusTypeDef WaterLevel_Init(void);
/**
* @brief 读取水位深度
* @param 无
* @retval 水位深度,单位:mm (0-50mm)
*/
float WaterLevel_GetDepth(void);
/**
* @brief 读取水位原始ADC值
* @param 无
* @retval ADC原始值 (0-4095)
*/
uint16_t WaterLevel_GetRawADC(void);
#ifdef __cplusplus
}
#endif
#endif /* __WATER_LEVEL_H */