光敏电阻传感器模块代码例程
1. STM32 HAL 库驱动
#ifndef __LDR_SENSOR_H
#define __LDR_SENSOR_H
#include "main.h"
#define LDR_DO_PORT GPIOB
#define LDR_DO_PIN GPIO_PIN_2 // 数字输出
#define LDR_DO_CLK_EN() __HAL_RCC_GPIOB_CLK_ENABLE()
#define LDR_AO_ADC hadc1 // 使用 ADC1
#define LDR_AO_CH ADC_CHANNEL_0 // PA0
void LDR_Init(void);
uint8_t LDR_IsDark(void); // 数字量:1=暗,0=亮
uint16_t LDR_ReadAO(void); // 模拟量:值越大光照越强
float LDR_GetLux(uint16_t adc_val); // 近似Lux(需标定)
#endif
#include "ldr_sensor.h"
static ADC_HandleTypeDef *adc_handle;
void LDR_Init(void) {
LDR_DO_CLK_EN();
GPIO_InitTypeDef gpio = {
.Pin = LDR_DO_PIN, .Mode = GPIO_MODE_INPUT,
.Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_LOW
};
HAL_GPIO_Init(LDR_DO_PORT, &gpio);
adc_handle = &LDR_AO_ADC;
}
uint8_t LDR_IsDark(void) {
return (HAL_GPIO_ReadPin(LDR_DO_PORT, LDR_DO_PIN) == GPIO_PIN_RESET) ? 1 : 0;
}
uint16_t LDR_ReadAO(void) {
HAL_ADC_Start(adc_handle);
HAL_ADC_PollForConversion(adc_handle, 10);
return HAL_ADC_GetValue(adc_handle);
}
float LDR_GetLux(uint16_t adc_val) {
float voltage = adc_val * 3.3f / 4095.0f;
float ratio = voltage / (3.3f - voltage);
return 100.0f * ratio; // 粗略值,仅供参考
}
2. STM32 自动夜灯示例
#include "ldr_sensor.h"
#include <stdio.h>
#define LED_PORT GPIOB
#define LED_PIN GPIO_PIN_10
int main(void) {
HAL_Init();
SystemClock_Config();
LDR_Init();
GPIO_InitTypeDef led = {
.Pin = LED_PIN, .Mode = GPIO_MODE_OUTPUT_PP,
.Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW
};
HAL_GPIO_Init(LED_PORT, &led);
char msg[64];
while (1) {
uint16_t ao = LDR_ReadAO();
if (LDR_IsDark()) {
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
sprintf(msg, "DARK! AO=%d → LED ON\r\n", ao);
} else {
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
sprintf(msg, "LIGHT AO=%d → LED OFF\r\n", ao);
}
printf("%s", msg);
HAL_Delay(200);
}
}
3. Arduino 例程
基础读取
#define DO_PIN 2 // 数字输出
#define AO_PIN A0 // 模拟输出
void setup() {
Serial.begin(9600);
pinMode(DO_PIN, INPUT_PULLUP);
}
void loop() {
int do_val = digitalRead(DO_PIN);
int ao_val = analogRead(AO_PIN); // 0-1023 (10bit ADC)
Serial.print("DO: ");
Serial.print(do_val == LOW ? "DARK" : "LIGHT");
Serial.print(" | AO: ");
Serial.println(ao_val);
delay(200);
}
自动夜灯(带滞回,防抖动)
#define DO_PIN 2
#define LED_PIN 13
#define HYST 50 // 滞回区间
int threshold = 512; // ADC 阈值(10bit: 0-1023)
bool light_on = false;
void setup() {
pinMode(DO_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
int ao = analogRead(A0);
if (!light_on && ao < threshold - HYST) {
light_on = true;
digitalWrite(LED_PIN, HIGH);
Serial.println("Light ON");
} else if (light_on && ao > threshold + HYST) {
light_on = false;
digitalWrite(LED_PIN, LOW);
Serial.println("Light OFF");
}
Serial.print("AO: "); Serial.println(ao);
delay(200);
}
4. 关键说明
| 要点 |
说明 |
| DO 逻辑 |
一般暗=低电平,但需实测确认(与比较器接法有关) |
| AO 非线性 |
模拟值与 Lux 非正比,精确应用需查表或拟合 |
| 滞回处理 |
DO 阈值附近可能抖动,建议软件加滞回区间 |
| ADC 参考电压 |
5V 供电模块接 3.3V MCU 的 ADC 时注意电平匹配 |
| 响应延迟 |
光敏电阻有惯性,状态变化后等待 50ms 再读取 |