#include <Wire.h>
#include <DHT.h>
//// 🔥 改用Arduino标准引脚标识(适配STM32L031K6的Arduino框架)
#define DHT_PIN A7 // DHT22 DATA → A7(直接用A7,无需PA7)
#define DHT_TYPE DHT22
#define PIR_PIN D13 // PIR → D13(直接用D13,无需PC13)
//// SSD1306 I2C 引脚(直接用D0/D1,无需PD0/PD1)
#define SSD1306_ADDR 0x3C
#define SSD1306_SDA D1 // OLED SDA → D1
#define SSD1306_SCL D0 // OLED SCL → D0
// 全局变量(精简内存)
DHT dht(DHT_PIN, DHT_TYPE);
char display_buf[32];
char pir_str[10];
// ==================== 极简 SSD1306 驱动 ====================
void I2C_Write(uint8_t reg, uint8_t data) {
Wire.beginTransmission(SSD1306_ADDR);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission();
}
void SSD1306_Init() {
Wire.setClock(100000); // 适配STM32L031K6的I2C速率
Wire.begin(SSD1306_SDA, SSD1306_SCL);
// 核心初始化命令
I2C_Write(0x00, 0xAE); // 关显示
I2C_Write(0x00, 0x20); // 页寻址模式
I2C_Write(0x00, 0x10);
I2C_Write(0x00, 0xB0); // 起始页
I2C_Write(0x00, 0xC8); // 行扫描方向
I2C_Write(0x00, 0x81); // 对比度
I2C_Write(0x00, 0xFF);
I2C_Write(0x00, 0xA1); // 段重映射
I2C_Write(0x00, 0xA6); // 正常显示
I2C_Write(0x00, 0xAF); // 开显示
}
void SSD1306_Clear() {
for(uint8_t page=0; page<8; page++) {
I2C_Write(0x00, 0xB0+page);
I2C_Write(0x00, 0x00);
I2C_Write(0x00, 0x10);
for(uint8_t col=0; col<128; col++) I2C_Write(0x40, 0x00);
}
}
// 极简字库(仅保留实验必需字符)
const uint8_t font8x8[] = {
0x3E,0x51,0x49,0x45,0x3E,0x00,0x00,0x00, // 0
0x00,0x42,0x7F,0x40,0x00,0x00,0x00,0x00, // 1
0x42,0x61,0x51,0x49,0x46,0x00,0x00,0x00, // 2
0x22,0x41,0x49,0x49,0x36,0x00,0x00,0x00, // 3
0x18,0x14,0x12,0x7F,0x10,0x00,0x00,0x00, // 4
0x27,0x45,0x45,0x45,0x39,0x00,0x00,0x00, // 5
0x3C,0x4A,0x49,0x49,0x30,0x00,0x00,0x00, // 6
0x01,0x71,0x09,0x05,0x03,0x00,0x00,0x00, // 7
0x36,0x49,0x49,0x49,0x36,0x00,0x00,0x00, // 8
0x06,0x49,0x49,0x29,0x1E,0x00,0x00,0x00, // 9
0x00,0x00,0x54,0x38,0x00,0x00,0x00,0x00, // %
0x00,0x00,0x60,0x90,0x00,0x00,0x00,0x00, // °
0x3E,0x41,0x41,0x41,0x3E,0x00,0x00,0x00, // C
0x7C,0x12,0x11,0x12,0x7C,0x00,0x00,0x00, // H
0x7C,0x0A,0x09,0x0A,0x7C,0x00,0x00,0x00, // T
0x70,0x18,0x14,0x12,0x7C,0x00,0x00,0x00, // P
0x7C,0x08,0x14,0x22,0x41,0x00,0x00,0x00, // I
0x3E,0x41,0x41,0x22,0x1C,0x00,0x00,0x00, // R
0x1C,0x22,0x41,0x00,0x00,0x00,0x00,0x00, // Y
0x7E,0x01,0x01,0x01,0x7E,0x00,0x00,0x00, // E
0x7F,0x41,0x41,0x41,0x7F,0x00,0x00,0x00, // S
0x7E,0x01,0x01,0x01,0x01,0x00,0x00,0x00, // N
0x3E,0x41,0x41,0x41,0x3E,0x00,0x00,0x00, // O
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // :/空格
};
void SSD1306_Print(uint8_t x, uint8_t y, char* str) {
uint8_t page = y/8, col = x;
I2C_Write(0x00, 0xB0+page);
I2C_Write(0x00, col&0x0F);
I2C_Write(0x00, 0x10|(col>>4));
while(*str) {
uint8_t idx = 24; // 默认空格/:
if(*str>='0'&&*str<='9') idx=*str-'0';
else if(*str=='%') idx=10;
else if(*str=='°') idx=11;
else if(*str=='C') idx=12;
else if(*str=='H') idx=13;
else if(*str=='T') idx=14;
else if(*str=='P') idx=15;
else if(*str=='I') idx=16;
else if(*str=='R') idx=17;
else if(*str=='Y') idx=18;
else if(*str=='E') idx=19;
else if(*str=='S') idx=20;
else if(*str=='N') idx=21;
else if(*str=='O') idx=22;
for(uint8_t i=0; i<8; i++) I2C_Write(0x40, font8x8[idx*8+i]);
col +=8; str++;
}
}
// ==================== 主程序(无HAL库依赖) ====================
void setup() {
// 初始化引脚(Arduino标准函数,适配L031K6)
pinMode(PIR_PIN, INPUT);
pinMode(DHT_PIN, INPUT);
// 初始化传感器和屏幕
dht.begin();
SSD1306_Init();
SSD1306_Clear();
// 初始显示
SSD1306_Print(0,0,"STM32L031 Ready");
delay(1000);
}
void loop() {
// 定时读取传感器(避免阻塞)
static uint32_t last_read = 0;
if(millis() - last_read >= 1000) {
last_read = millis();
// 读取数据(转整数,减少运算)
int temp = (int)dht.readTemperature();
int humi = (int)dht.readHumidity();
int pir = digitalRead(PIR_PIN);
// 处理PIR状态
sprintf(pir_str, "PIR:%s", pir?"YES":"NO");
// 屏幕显示
SSD1306_Clear();
sprintf(display_buf, "T:%d°C", temp);
SSD1306_Print(0,0, display_buf);
sprintf(display_buf, "H:%d%%", humi);
SSD1306_Print(0,16, display_buf);
SSD1306_Print(0,32, pir_str);
}
}