STM32智能风扇系统设计(温度报警+旋钮调速)

STM32智能风扇系统设计(温度报警+旋钮调速)

一、系统总体设计

STM32智能风扇系统以STM32F103C8T6为核心控制器,集成温度检测(DS18B20)、旋钮调速(旋转编码器)、温度报警(蜂鸣器+LED)及状态显示(OLED)四大功能模块,实现“自动温控+手动调速”双模式切换。系统架构如下面 的 图所示:

graph TD
    A[STM32F103C8T6] --> B[DS18B20温度传感器]
    A --> C[旋转编码器]
    A --> D[蜂鸣器+LED]
    A --> E[OLED显示屏]
    A --> F[风扇驱动电路]
    B -->|温度数据| A
    C -->|转速指令| A
    A -->|控制信号| F
    A -->|报警信号| D
    A -->|状态信息| E

二、硬件设计

2.1 核心控制器:STM32F103C8T6

2.2 温度检测模块:DS18B20

2.3 旋钮调速模块:旋转编码器

2.4 温度报警模块:蜂鸣器+LED

2.5 状态显示模块:OLED12864

2.6 风扇驱动模块:L9110

三、软件设计

3.1 开发环境

3.2 主程序流程

graph TD
    A[系统初始化] --> B[外设初始化]
    B --> C[读取温度]
    C --> D[模式判断]
    D -->|自动模式| E[温度→转速映射]
    D -->|手动模式| F[编码器→转速映射]
    E --> G[更新PWM占空比]
    F --> G
    G --> H[显示状态]
    H --> I[报警判断]
    I -->|是| J[触发蜂鸣器+LED]
    I -->|否| C

3.3 关键模块代码实现

(1)DS18B20温度采集

#include "ds18b20.h"

void DS18B20_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_0); // 初始高电平
}

uint8_t DS18B20_Reset(void) {
    uint8_t ack;
    GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 拉低DQ
    delay_us(480); // 保持480μs
    GPIO_SetBits(GPIOA, GPIO_Pin_0); // 释放DQ
    delay_us(60); // 等待60μs
    ack = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 读取应答
    delay_us(420); // 等待剩余时间
    return ack; // 0=存在,1=不存在
}

void DS18B20_WriteByte(uint8_t dat) {
    uint8_t i;
    for (i=0; i<8; i++) {
        GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 拉低DQ
        delay_us(2); // 保持2μs
        if (dat & 0x01) {
            GPIO_SetBits(GPIOA, GPIO_Pin_0); // 写1
        } else {
            GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 写0
        }
        delay_us(60); // 保持60μs
        GPIO_SetBits(GPIOA, GPIO_Pin_0); // 释放DQ
        dat >>= 1;
    }
}

uint8_t DS18B20_ReadByte(void) {
    uint8_t i, dat=0;
    for (i=0; i<8; i++) {
        GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 拉低DQ
        delay_us(2); // 保持2μs
        GPIO_SetBits(GPIOA, GPIO_Pin_0); // 释放DQ
        delay_us(10); // 等待10μs
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) {
            dat |= 0x01 << i; // 读1
        }
        delay_us(50); // 保持50μs
    }
    return dat;
}

float DS18B20_GetTemp(void) {
    uint8_t temp_l, temp_h;
    int16_t temp;
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0x44); // 启动温度转换
    delay_ms(750); // 等待转换完成
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0xBE); // 读取温度寄存器
    temp_l = DS18B20_ReadByte(); // 低8位
    temp_h = DS18B20_ReadByte(); // 高8位
    temp = (temp_h << 8) | temp_l;
    return temp * 0.0625; // 转换为℃
}

(2)旋转编码器处理

#include "encoder.h"

void Encoder_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    // A相(PA1)、B相(PA2)输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 按压开关(PA3)输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

int8_t Encoder_Read(void) {
    static uint8_t last_state = 0;
    uint8_t current_state;
    int8_t dir = 0;
    // 读取A、B相状态
    current_state = (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) << 1) | GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2);
    switch (last_state) {
        case 0:
            if (current_state == 1) dir = 1; // 顺时针
            else if (current_state == 2) dir = -1; // 逆时针
            break;
        case 1:
            if (current_state == 3) dir = 1;
            else if (current_state == 0) dir = -1;
            break;
        case 2:
            if (current_state == 0) dir = 1;
            else if (current_state == 3) dir = -1;
            break;
        case 3:
            if (current_state == 2) dir = 1;
            else if (current_state == 1) dir = -1;
            break;
    }
    last_state = current_state;
    return dir;
}

(3)PWM风扇控制

#include "pwm.h"

void PWM_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
    // PA8(TIM1_CH1)复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 定时器1配置(PWM频率20kHz)
    TIM_TimeBaseStructure.TIM_Period = 999; // 自动重载值(72MHz/(72 * 1000)=1kHz?不对,应该是72MHz/(71+1)=1MHz,1MHz/1000=1kHz,需要调整)
    // 修正:TIM_Prescaler=71(72MHz→1MHz),TIM_Period=49(1MHz→20kHz)
    TIM_TimeBaseStructure.TIM_Prescaler = 71;
    TIM_TimeBaseStructure.TIM_Period = 49;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    // PWM模式配置(TIM_OCMODE_PWM1)
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    // 使能预装载寄存器
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM1, ENABLE);
    // 使能定时器1
    TIM_Cmd(TIM1, ENABLE);
}

void Fan_SetSpeed(uint8_t duty_cycle) {
    uint16_t pulse;
    if (duty_cycle > 100) duty_cycle = 100;
    pulse = (duty_cycle * (TIM1->ARR + 1)) / 100; // 计算脉冲宽度
    TIM1->CCR1 = pulse; // 设置比较值
}

(4)温度报警逻辑

#include "alarm.h"

void Alarm_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    // 蜂鸣器(PB0)、LED(PB1)推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 初始关闭蜂鸣器
    GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 初始关闭LED
}

void Alarm_Check(float temp, float threshold) {
    if (temp > threshold) {
        GPIO_SetBits(GPIOB, GPIO_Pin_0); // 蜂鸣器响
        GPIO_SetBits(GPIOB, GPIO_Pin_1); // LED亮
    } else {
        GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 蜂鸣器关
        GPIO_ResetBits(GPIOB, GPIO_Pin_1); // LED关
    }
}

参考系统 stm32智能风扇(包括温度报警+旋钮调速) www.youwenfan.com/contenttee/183149.html

四、系统测试与优化

4.1 功能测试

4.2 性能优化

五、总结

本系统实现了STM32智能风扇的核心功能:温度检测、旋钮调速、温度报警及状态显示。硬件设计采用模块化思路,便于扩展(如添加蓝牙模块实现远程控制);软件设计采用结构化编程,可读性强、易维护。通过测试,系统性能稳定,满足日常使用需求,可作为智能家居的基础模块推广应用。

专注于matlab/simulink,电子电路,编程