STM32F103C8T6 · HAL库 · OLED显示

雨滴传感器

Raindrops Module — 电阻式雨滴检测模块演示

3.3-5V
工作电压
12-bit
ADC分辨率
AO+DO
双路输出
500ms
采样周期

1传感器原理与功能

1.1 工作原理

雨滴传感器(Raindrops Module)是一种基于电阻式检测原理的环境传感器。其核心传感元件是一块覆有叉指状(interdigitated)铜走线的PCB检测板,走线之间留有窄间隙,形成类似梳齿的交错结构。

当检测板表面干燥时,铜走线之间的空气充当绝缘体,电阻趋于无穷大;当雨滴落在检测板上时,水作为导体桥接了相邻走线之间的间隙,使电阻显著降低。水覆盖面积越大,并联导电路径越多,电阻下降越明显。模块内部的LM393电压比较器将这一电阻变化转换为可读取的电压信号输出。

干燥状态(高阻) 电阻 ≈ 无穷大(断路) AO ≈ VCC,DO = HIGH 雨水落下 湿润状态(低阻) 电阻显著降低 AO下降,DO = LOW

图:雨滴传感器干湿状态对比 — 水桥接走线间隙使电阻降低

1.2 功能特性

📡

双路信号输出

同时提供模拟输出(AO)和数字输出(DO)。AO输出连续变化的电压,反映雨量大小;DO输出高低电平,表示是否超过设定阈值。

🔧

灵敏度可调

板载蓝色电位器(10K),旋转调节比较器参考电压,从而改变DO输出的触发阈值,适应不同应用场景。

⚡

LM393比较器

采用LM393双路电压比较器芯片,将传感器模拟信号与参考电压比较,输出干净的数字开关信号,具备一定抗干扰能力。

💡

状态指示灯

配备电源指示灯(常亮)和输出指示灯(触发时亮灭),方便调试时直观判断模块工作状态。

🔌

宽电压兼容

工作电压3.3V-5V,兼容STM32(3.3V)和Arduino(5V)等主流单片机平台,可直接连接GPIO和ADC引脚。

🌧️

大面积检测

叉指状铜走线覆盖约50mm×40mm的检测面积,多条平行走线交错排列,有效提升检测灵敏度和响应速度。

1.3 模块引脚定义

VCC
电源正极
3.3V-5V
GND
电源地
DO
数字输出
接 PA1
AO
模拟输出
接 PA0(ADC)
引脚名称功能说明STM32连接
1VCC电源正极输入,3.3V-5V DC3.3V / 5V
2GND电源地,共地参考GND
3DO数字输出,雨量超过阈值时电平翻转PA1(GPIO输入)
4AO模拟输出,0-VCC电压随雨量变化PA0(ADC1_IN0)

2模块外观展示

以下为雨滴传感器模块的实物外观图片,包含传感器检测板、比较器控制板及连接线缆。

3原理图与PCB封装

4程序分析

本演示程序基于 STM32F103C8T6 微控制器,使用 HAL 库开发。通过 ADC1 通道0(PA0)读取雨滴传感器的模拟输出,通过 GPIO PA1 读取数字输出,最终在 OLED 屏幕上显示雨量值和触发状态。

4.1 系统时钟配置

系统时钟采用外部高速晶振(HSE),通过PLL倍频至 72MHz 主频。ADC时钟由PCLK2(72MHz)8分频得到9MHz,满足ADC最高14MHz的限制。

SystemClock_Config() — main.c
// HSE外部晶振 → PLL倍频9 → SYSCLK = 72MHz
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.PLL.PLLState    = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLMUL      = RCC_PLL_MUL9;

// AHB=72MHz, APB1=36MHz, APB2=72MHz
RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

// ADC时钟 = PCLK2/8 = 9MHz
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;

4.2 ADC配置(adc.c)

ADC1配置为单通道、单次转换、软件触发模式。使用通道0(PA0),数据右对齐,采样时间设置为239.5个时钟周期以获得更精确的转换结果。12位分辨率,ADC值范围0-4095。

MX_ADC1_Init() — adc.c
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;    // 数据右对齐
hadc1.Init.NbrOfConversion      = 1;                      // 单通道

// 配置通道0,对应PA0引脚
sConfig.Channel       = ADC_CHANNEL_0;
sConfig.Rank           = ADC_REGULAR_RANK_1;
sConfig.SamplingTime   = ADC_SAMPLETIME_239CYCLES_5; // 长采样时间

// PA0 配置为模拟输入模式
GPIO_InitStruct.Pin  = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

4.3 GPIO配置(gpio.c)

PA1配置为浮空输入模式,用于读取雨滴传感器的数字输出(DO)。当雨量超过比较器阈值时,DO输出低电平(0),反之输出高电平(1)。

MX_GPIO_Init() — gpio.c
// 使能GPIOA时钟
__HAL_RCC_GPIOA_CLK_ENABLE();

// 配置PA1为输入模式(读取DO数字输出)
GPIO_InitStruct.Pin  = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;          // 浮空输入
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

4.4 主程序逻辑(main.c)

主程序在 while(1) 主循环中,每 500ms 执行一次采样与显示更新。核心逻辑如下:

1. 通过 HAL_GetTick() 判断是否到达500ms间隔;

2. 启动ADC转换,读取PA0模拟值并换算为0-100的雨量百分比;

3. 读取PA1数字电平,判断是否触发雨水检测;

4. 在OLED屏幕上居中显示"雨水:是/否"和"Rain:XX"数值。

main() 主循环 — main.c
uint32_t Time_Now;  // 上次更新时间戳
uint8_t Rain;        // 雨量值 0-100

int main(void)
{
    HAL_Init();                  // HAL库初始化
    SystemClock_Config();        // 系统时钟配置 72MHz
    MX_GPIO_Init();              // GPIO初始化(PA1输入)
    MX_ADC1_Init();              // ADC初始化(PA0通道0)
    OLED_Init();                 // OLED显示屏初始化

    while (1)
    {
        if(HAL_GetTick() - Time_Now >= 500)       // 500ms更新一次
        {
            // ===== 单通道ADC数据获取 =====
            HAL_ADC_Start(&hadc1);                             // 启动ADC转换
            if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)
            {
                // ADC值(0-4095) → 雨量百分比(0-100)
                // 注意取反:干燥时ADC值大(接近4095),雨量大时ADC值小
                Rain = 100 - HAL_ADC_GetValue(&hadc1) / 4095.0 * 100;
            }
            HAL_ADC_Stop(&hadc1);                              // 停止ADC

            OLED_Clear();                                       // 清屏

            // ===== 读取数字输出,判断是否触发 =====
            if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == 0)
                OLED_CenterPrintf(16, "雨水:是");          // DO=0,触发
            else
                OLED_CenterPrintf(16, "雨水:否");          // DO=1,未触发

            OLED_CenterPrintf(40, "Rain:%d", Rain);         // 显示雨量值

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

4.5 雨量计算公式解析

Rain = 100 − (ADC_Value / 4095.0 × 100)

取反逻辑:传感器干燥时,AO输出电压接近VCC,ADC读数接近4095(满量程),此时Rain约为0(无雨)。当雨水覆盖检测板时,AO电压下降,ADC读数减小,Rain值增大。ADC值越小,Rain值越大,表示雨量越大。

状态AO电压ADC原始值Rain计算值DO电平
完全干燥约 3.3V约 40950HIGH (1)
少量水滴约 2.0V约 248239HIGH (1)
中等雨量约 1.0V约 124170LOW (0)
大雨/浸水约 0.3V约 37291LOW (0)

4.6 OLED显示接口

OLED屏通过I2C协议(软件模拟)连接至 PB14(SDA) 和 PB15(SCL)。程序中使用 OLED_CenterPrintf() 函数实现文字居中显示,OLED_Update() 将显存数据刷新到屏幕。

5程序流程图

以下为 main.c 程序的完整流程图,展示初始化过程与 while(1) 主循环逻辑。

开始 系统初始化 HAL_Init() — HAL库初始化 SystemClock_Config() — 时钟72MHz MX_GPIO_Init() — PA1输入 MX_ADC1_Init() — PA0/ADC1_IN0 while (1) 主循环 HAL_GetTick() - Time_Now ≥ 500? 否 是 启动ADC转换 HAL_ADC_Start(&hadc1) 转换成功? PollForConversion 是 读取ADC值并计算雨量 Rain = 100 - ADC值/4095*100 否 停止ADC HAL_ADC_Stop(&hadc1) OLED清屏 OLED_Clear() PA1 == 0? ReadPin(GPIOA, PIN_1) 是 显示 "雨水:是" OLED_CenterPrintf(16) 否 显示 "雨水:否" OLED_CenterPrintf(16) 显示Rain值 OLED_CenterPrintf(40, "Rain:%d", Rain) OLED更新显示 OLED_Update() 更新时间戳 Time_Now = HAL_GetTick()

流程图说明

初始化阶段:依次完成HAL库初始化、系统时钟配置(72MHz)、GPIO初始化(PA1浮空输入)、ADC初始化(PA0模拟输入通道0)和OLED初始化。

主循环 while(1):使用 HAL_GetTick() 实现500ms定时。到达时间后启动ADC单次转换,读取模拟值计算雨量百分比,同时读取PA1数字电平判断是否触发阈值,最后在OLED上刷新显示。完成后更新时间戳,循环回到500ms判断处继续等待。

6交互式动画演示

点击"开始下雨"模拟雨滴落在传感器上,观察ADC值、雨量百分比和OLED显示屏的实时变化。

当前状态:干燥
雨滴传感器检测板(叉指状裸露铜线)
湿润度: 0%
雨水:否
Rain:0
ADC 原始值 4095
雨量百分比 Rain 0
DO 数字输出 (PA1) HIGH (1)

动画说明

传感器检测板:模拟雨滴传感器实物检测板,黑色PCB上布满22条平行的裸露铜走线,呈叉指状交错排列(奇数行从左侧延伸,偶数行从右侧延伸)。干燥时走线呈铜色,下雨时水滴落在走线上使其变为蓝色(导通状态),同时在板面上出现水滴。

ADC值:干燥时ADC读数接近4095(满量程),随雨水增多ADC值下降。雨量百分比 Rain = 100 - ADC/4095×100。

DO数字输出:当雨量超过阈值(模拟50%)时,DO从HIGH变为LOW,OLED显示"雨水:是"。

OLED显示:模拟STM32驱动的OLED屏幕,每500ms更新一次显示内容,与实际程序行为一致。