PH传感器

STM32F103C8T6  |  HAL库开发  |  ADC模拟采集
工作电压
5V
通信方式
ADC
检测范围
PH 0 ~ 14
更新间隔
200ms

01传感器原理与功能

PH传感器基于玻璃电极法,通过测量溶液中氢离子浓度对应的电压信号,实现PH值的精确检测。

1.1 工作原理

玻璃电极法检测原理

PH传感器内部包含一个对氢离子(H⁺)敏感的玻璃电极和一个参比电极。当玻璃电极浸入待测溶液时,玻璃膜两侧会因氢离子浓度差产生一个电位差。该电位差遵循能斯特方程(Nernst Equation):E = E₀ - (2.303RT/nF) × pH。在25°C条件下,每变化1个PH单位,电极输出电压变化约59.16mV。传感器模块内置信号调理电路,将微弱的电极信号放大并转换为0~3.3V的模拟电压输出(AO),供STM32的ADC采集。

电压与PH值的映射关系

该模块输出的模拟电压与PH值呈线性反比关系:电压越高,PH值越低(偏酸性);电压越低,PH值越高(偏碱性)。本程序中通过标定得到的线性公式为:PH = -5.8887 × V + 21.677,其中V为ADC采集并换算后的实际电压值(单位:V)。

1.2 核心功能

🔬

PH值检测

通过玻璃电极实时测量溶液的氢离子浓度,输出对应的模拟电压信号,支持PH 0~14全量程检测。

📡

模拟电压输出

AO引脚输出0~3.3V线性模拟电压,直接连接STM32的ADC通道进行采集,无需复杂通信协议。

📊

实时监测

配合STM32定时采集(200ms周期),可在OLED屏幕上实时显示当前PH值,适用于水质连续监测场景。

⚙️

宽量程适配

采用5V供电,内置信号调理电路,适用于酸碱溶液、水质检测、实验室分析等多种应用场景。

1.3 引脚定义

引脚号 引脚名称 功能说明 STM32连接
1 VCC 电源正极(5V) 5V
2 GND 电源地 GND
3 AO 模拟电压输出(0~3.3V) PA0(ADC1_IN0)

02模块外观展示

PH传感器模块包含PH探头、信号转换板和连接线,下方为模块各角度实物展示。

外观1
模块正面外观
外观2
模块背面外观
尺寸图
模块尺寸图

03原理图与PCB封装

PH传感器模块的电路原理图与PCB封装设计。

原理图
PCB封装

04程序分析

基于STM32 HAL库开发,使用ADC1通道0采集PH传感器模拟电压,经线性换算得到PH值并在OLED上显示。

4.1 系统时钟配置

时钟树配置说明

系统使用外部高速晶振(HSE)8MHz作为时钟源,通过PLL倍频9倍得到72MHz系统时钟(SYSCLK)。AHB总线不分频(72MHz),APB1总线2分频(36MHz),APB2总线不分频(72MHz)。ADC时钟由APB2再8分频得到9MHz,满足ADC最高14MHz的限制。

main.c — SystemClock_Config()
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /* HSE 8MHz外部晶振, PLL倍频9倍 = 72MHz */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  /* SYSCLK=72MHz, AHB=72MHz, APB1=36MHz, APB2=72MHz */
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  /* ADC时钟 = APB2(72MHz) / 8 = 9MHz */
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
}

4.2 ADC初始化

ADC1通道0配置说明

使用ADC1通道0(PA0引脚)采集PH传感器AO输出的模拟电压。配置为12位分辨率(0~4095)、右对齐、软件触发、单次转换模式。采样时间设为239.5个ADC时钟周期(约26.6μs),确保高阻抗信号源的采样精度。PA0引脚配置为模拟模式(GPIO_MODE_ANALOG),避免数字电路干扰。

adc.c — MX_ADC1_Init()
ADC_HandleTypeDef hadc1;

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;          // 禁用扫描模式
  hadc1.Init.ContinuousConvMode = DISABLE;              // 单次转换
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;     // 软件触发
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         // 右对齐(12位)
  hadc1.Init.NbrOfConversion = 1;                     // 1个转换通道
  HAL_ADC_Init(&hadc1);

  sConfig.Channel = ADC_CHANNEL_0;                       // 通道0 (PA0)
  sConfig.Rank = ADC_REGULAR_RANK_1;                   // 规则组第1
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;       // 239.5周期采样
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

/* PA0 引脚配置为模拟模式 */
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance == ADC1)
  {
    __HAL_RCC_ADC1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /* PA0-WKUP -----> ADC1_IN0 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

4.3 GPIO初始化

GPIO时钟使能说明

在MX_GPIO_Init中使能GPIOD和GPIOA时钟。PA0的模拟模式配置在ADC的MspInit回调中完成。OLED使用的PB14(SDA)和PB15(SCL)引脚在OLED_Init函数内部通过软件I2C方式配置。

gpio.c — MX_GPIO_Init()
void MX_GPIO_Init(void)
{
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
}

4.4 OLED显示配置

OLED软件I2C配置说明

采用0.96寸OLED显示屏(128×64),通过软件模拟I2C通信。SCL连接PB15,SDA连接PB14。使用OLED_CenterPrintf函数在Y=24位置居中显示PH值,显示格式为"PH:%.1f"(保留1位小数)。每次更新前调用OLED_Clear清屏,更新后调用OLED_Update刷新显存到屏幕。

OLED.h — 引脚定义
#define SCL_Port   GPIOB
#define SCL_Pin    GPIO_PIN_15
#define SDA_Port   GPIOB
#define SDA_Pin    GPIO_PIN_14

/* OLED核心函数 */
void OLED_Init(void);                        // 初始化
void OLED_Clear(void);                       // 清屏
void OLED_CenterPrintf(int16_t Y, char *format, ...);  // 居中打印
void OLED_Update(void);                      // 更新显示

4.5 主循环逻辑

主循环数据处理流程

主函数首先完成HAL初始化、时钟配置、GPIO/ADC外设初始化,然后执行ADC自校准(HAL_ADCEx_Calibration_Start)和OLED初始化。进入while(1)主循环后,通过HAL_GetTick()实现200ms定时:启动ADC转换 → 等待转换完成 → 读取12位ADC原始值 → 换算为电压 → 线性公式计算PH值 → 限幅处理 → OLED显示。最后更新时间戳,等待下一个采集周期。

main.c — main() 主程序
uint32_t Time_Now;
float PH;

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ADC1_Init();

  HAL_ADCEx_Calibration_Start(&hadc1);     // ADC自校准
  OLED_Init();                              // OLED初始化

  while (1)
  {
    if(HAL_GetTick() - Time_Now >= 200)          // 200ms更新一次
    {
      // 单通道数据获取
      HAL_ADC_Start(&hadc1);
      if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)
        PH = (HAL_ADC_GetValue(&hadc1)/4095.0)*3.3;
      HAL_ADC_Stop(&hadc1);

      PH = -5.8887*PH+21.677;            // 计算PH值

      // 限幅
      if(PH > 14.0) PH = 14.0;
      if(PH < 0.0) PH = 0.0;

      OLED_Clear();                               // 清屏
      OLED_CenterPrintf(24, "PH:%.1f", PH);
      OLED_Update();                              // 更新显示

      Time_Now = HAL_GetTick();               // 更新时间戳
    }
  }
}

数据计算公式解析

电压 V = (ADC原始值 / 4095.0) × 3.3
ADC为12位分辨率,满量程4095对应3.3V参考电压
PH = -5.8887 × V + 21.677
线性标定公式:电压越高PH越低(酸性),电压越低PH越高(碱性)
PH = clamp(PH, 0.0, 14.0)
限幅处理:确保PH值在有效范围0~14之内

电压-PH值对照表

ADC原始值 电压 (V) PH值 溶液状态
40953.3002.24强酸性
30722.4757.10中性
20481.65011.95碱性
10240.82514.00 (限幅)强碱性
00.00014.00 (限幅)强碱性

05程序流程图

从系统初始化到主循环采集的完整程序执行流程,虚线框表示while(1)循环体。

开始 HAL_Init() 系统初始化 SystemClock_Config() 时钟配置 MX_GPIO_Init() / MX_ADC1_Init() ADC校准 + OLED_Init() while(1) HAL_GetTick() - Time_Now >= 200? 否 是 HAL_ADC_Start() PollForConversion == HAL_OK ? 是 PH = (ADC值/4095.0)*3.3 PH = -5.8887*PH + 21.677 限幅(0~14) → OLED显示 → 更新时间戳

06交互式动画演示

模拟PH传感器探头浸入不同酸碱性溶液,观察ADC采集、PH值计算与OLED显示的实时联动。

PH探头模拟

模拟说明

烧杯中的溶液颜色随PH值变化:红色(强酸)→ 橙色(弱酸)→ 绿色(中性)→ 蓝色(弱碱)→ 紫色(强碱)。PH探头浸入溶液中,AO引脚输出对应的模拟电压。

OLED显示与数据仪表

PH:--.-
ADC原始值 (12位) 0
模拟电压 (V) 0.000
PH值 7.0
溶液状态 中性
PH色阶条
024678101214