基于STM32设计的智能空调

一、项目背景

随着人们生活水平的不断提高,对居住环境的舒适度要求也越来越高。空调作为一种重要的家电设备,已经成为了现代家庭中必不可少的一部分。本文介绍了一种基于STM32的智能空调设计方案,可以自动地根据环境温度进行温度调节。

image-20230618181209765

image-20230618181649941

二、设计思路

2.1 整体构架

智能空调系统由温度检测传感器、微控制器、OLED显示屏、按键及直流电源等组件构成。传感器用于检测环境温度,通过微控制器进行处理后,将结果输出到OLED显示屏上展示。按键可根据需求调整预设阀值,切换模式等操作。

2.2 硬件设计

(1)温度检测传感器

选择DS18B20数字温度传感器作为本系统的温度检测器件。该传感器具有精度高,响应速度快等特点,可以满足该系统的检测需求。

(2)微控制器

使用STM32F103系列的微控制器,在该控制器活跃的生态环境下,以及其先进的处理能力,可以对信号进行快速采集、处理和控制。

(3)OLED显示屏

本系统使用的是一块128 * 64 OLED显示屏,显示屏具有高亮度、高对比度和低功耗等优点,易于与STM32微控制器进行通信。

2.3 软件设计

在软件设计方面,实现了温度检测传感器数据的采集,使用处理算法对数据进行处理,根据预设阀值自动调节温度,同时可以根据用户需求,切换制冷、制热和关闭等3种模式。最后,将结果通过OLED显示屏进行输出。

三、代码设计

3.1 DS18B20温度检测代码

#include "main.h"
#include "delay.h"

#define GPIO_PORT_TEMP     GPIOA        //温度数据引脚所在的端口
#define GPIO_PIN_TEMP      GPIO_Pin_0   //温度数据引脚所在的引脚编号

#define RCC_PORT_TEMPP     RCC_APB2Periph_GPIOA  // 温度引脚所在端口时钟号

void USART_SendByte( USART_TypeDef * pUSARTx, uint8_t ch );

void delay_us(uint32_t us){     // 延时us微秒函数
    uint8_t i;
    for(i=0;i<us;i++){
        asm("nop");  
    }
}

float get_temp(){   // 获取温度函数
    uint16_t temp;
    uint8_t buf[2];

    GPIO_InitTypeDef GPIO_InitStruct;
    TIM_TimeBaseInitTypeDef TIM_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_PORT_TEMPP,ENABLE);

    //DATA拉低480us复位
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_TEMP;        
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIO_PORT_TEMP , &GPIO_InitStruct);    
    GPIO_ResetBits(GPIO_PORT_TEMP , GPIO_PIN_TEMP ); 
    delay_us(500);                                  
    GPIO_SetBits(GPIO_PORT_TEMP , GPIO_PIN_TEMP );   
    delay_us(60);                                   

    //查询DS18B20是否存在
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;        
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_TEMP;         
    GPIO_Init(GPIO_PORT_TEMP , &GPIO_InitStruct);    
    while (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET);     

    //通信开始
    GPIO_ResetBits(GPIO_PORT_TEMP , GPIO_PIN_TEMP );  
    delay_us(480);                                  
    GPIO_SetBits(GPIO_PORT_TEMP , GPIO_PIN_TEMP );    
    delay_us(60);                                   

    //读取温度数据
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;        
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_TEMP ;        
    GPIO_Init(GPIO_PORT_TEMP , &GPIO_InitStruct);
    delay_us(10);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x01;
    }
    else{
        temp &=0xfe;
    } 
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x02;
    }
    else{
        temp &=0xfd;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x04;
    }
    else{
        temp &=0xfb;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x08;
    }
    else{
        temp &=0xf7;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x10;
    }
    else{
        temp &=0xef;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x20;
    }
    else{
        temp &=0xdf;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x40;
    }
    else{
        temp &=0xbf;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        temp |=0x80;
    }
    else{
        temp &=0x7f;
    }
    delay_us(50);

    //读取温度小数点数据
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x01;
    }
    else{
        buf[0] &=0xfe;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x02;
    }
    else{
        buf[0] &=0xfd;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x04;
    }
    else{
        buf[0] &=0xfb;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x08;
    }
    else{
        buf[0] &=0xf7;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x10;
    }
    else{
        buf[0] &=0xef;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x20;
    }
    else{
        buf[0] &=0xdf;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x40;
    }
    else{
        buf[0] &=0xbf;
    }
    delay_us(50);
    if (GPIO_ReadInputDataBit(GPIO_PORT_TEMP , GPIO_PIN_TEMP ) == RESET){
        buf[0] |=0x80;
    }
    else{
        buf[0] &=0x7f;
    }
    delay_us(50);

    return (float)temp+((float)buf[0]/16.0);   // 将温度整数位和小数位转换为十进制
}

int main(void){

    char temp_buf[20];  // 接收温度值的临时缓冲区

    USART_InitTypeDef USART_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);   

    USART_InitStruct.USART_BaudRate = 115200;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1,&USART_InitStruct);

    USART_Cmd(USART1,ENABLE);

    while(1){
        float temp_get=get_temp();  // 获取当前温度值
        sprintf(temp_buf,"temp:%0.1f\r\n",temp_get);  // 将温度值格式化为字符串输出
        for(int i=0;i<strlen(temp_buf);i++){  // 逐字符发送温度值至串口
            USART_SendByte(USART1,temp_buf[i]); 
        }
        delay_ms(1000);  // 延时1s后再次获取温度值
    }
}

void USART_SendByte( USART_TypeDef * pUSARTx, uint8_t ch ){
    while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);     
    USART_SendData(pUSARTx,ch);
}

3.2 OLED显示屏代码

#include "main.h"
#include "delay.h"
#include "oled.h"

void iic_init(void);
void GPIO_I2C_Delay(void);
void write_com(unsigned char com);
void write_data(unsigned char data);

int main(void){

    unsigned char x,y;
    iic_init();  // 初始化IIC接口
    OLED_Init();  // 初始化OLED显示屏

    while(1){
        OLED_ShowString(0,0,"1234");  // 在OLED显示屏上显示字符串“1234”
        delay_ms(500);  // 延时500ms
        OLED_Clear();  // 清空OLED显示屏
    }
}

void iic_init(void){
    GPIO_InitTypeDef GPIO_InitStruct; 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //GPIOB使能
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);  //I2C1使能

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;         //配置开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct); 

    I2C_InitTypeDef I2C_InitStruct; 
    I2C_DeInit(I2C1);

    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;                             // I2C 模式
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;                     // 数传比率 2
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;                              // 地址1, 设备地址
    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;                            // 开启I2C应答机制
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设备地址长度为 7 位
    I2C_InitStruct.I2C_ClockSpeed = 400000;                             // 时钟速度为400kHz
    I2C_Cmd(I2C1, ENABLE);

    I2C_Init(I2C1, &I2C_InitStruct);
}

void GPIO_I2C_Delay(void){
    uint32_t i = 1000;
    while(i--);
}

void write_com(unsigned char com){
    while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));  //等待I2C总线空闲
    I2C_GenerateSTART(I2C1,ENABLE);               //发送起始信号
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
    I2C_Send7bitAddress(I2C1,0x78,I2C_Direction_Transmitter);//选择写入模式,发送从机器OLED的地址0x78
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    I2C_SendData(I2C1,0x00);                      //发送控制字节0x00表示写入指令
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    I2C_SendData(I2C1,com);                       //写入要发送的指令
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    I2C_GenerateSTOP(I2C1,ENABLE);                //停止信号,传输结束
}

void write_data(unsigned char data){
    while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));  //等待I2C总线空闲
    I2C_GenerateSTART(I2C1,ENABLE);              //发送起始信号
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
    I2C_Send7bitAddress(I2C1,0x78,I2C_Direction_Transmitter); //选择写入模式,发送从机器OLED的地址0x78  
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    I2C_SendData(I2C1,0x40);                     //发送控制字节0x40表示写入数据
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    I2C_SendData(I2C1,data);                     //写入要发送的数据
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    I2C_GenerateSTOP(I2C1,ENABLE);               //停止信号,传输结束
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59041.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

文章目录 一、重映射简介二、图像扭曲 一、重映射简介 重映射&#xff0c;就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即&#xff1a; 在重映射过程中&#xff0c;图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系&#xff0c;因…

PHP从入门到精通—PHP开发入门-PHP概述、PHP开发环境搭建、PHP开发环境搭建、第一个PHP程序、PHP开发流程

每开始学习一门语言&#xff0c;都要了解这门语言和进行开发环境的搭建。同样&#xff0c;学生开始PHP学习之前&#xff0c;首先要了解这门语言的历史、语言优势等内容以及了解开发环境的搭建。 PHP概述 认识PHP PHP最初是由Rasmus Lerdorf于1994年为了维护个人网页而编写的一…

租赁类小程序定制开发|租赁管理系统源码|免押租赁系统开发

随着互联网的发展&#xff0c;小程序成为了一种重要的移动应用开发方式。租赁小程序作为其中的一种类型&#xff0c;可以为很多行业提供便利和创新。下面我们将介绍一些适合开发租赁小程序的行业。   房屋租赁行业&#xff1a;租房小程序可以帮助房东和租户快速找到合适的租赁…

对当下AI的一些观感思考

目前来看&#xff0c;AI技术地震的震中还是在美帝那旮瘩。尤其是M7&#xff0c;这几家市值加总快15万亿美元了&#xff0c;个个都是行业翘楚&#xff0c;个个都有拿得出手的东西。AI是个技术密集、人才密集、计算密集的产业。美帝拥有全球一流的顶尖人才&#xff0c;以及财力、…

IntelliJ IDEA 2023.2社区版插件汇总

参考插件帝&#xff1a;https://gitee.com/zhengqingya/java-developer-document 突发小技巧&#xff1a;使用插件时要注意插件的版本兼容性&#xff0c;并根据自己的实际需求选择合适的插件。同时&#xff0c;不要过度依赖插件&#xff0c;保持简洁和高效的开发环境才是最重要…

2023下半年软考初级程序员报名入口-报名流程-备考方法

软考初级程序员2023下半年考试时间&#xff1a; 2023年下半年软考初级程序员的考试时间为11月4日、5日。考试时间在全国各地一致&#xff0c;建议考生提前备考。共分两科&#xff0c;第一科基础知识考试具体时间为9:00到11:30&#xff1b;第二科应用技术考试具体时间为2:00到4…

STM32 低功耗-睡眠模式

STM32 睡眠模式 文章目录 STM32 睡眠模式第1章 低功耗模式简介第2章 睡眠模式简介2.1 进入睡眠模式2.1 退出睡眠模式 第3章 睡眠模式代码示例总结 第1章 低功耗模式简介 在 STM32 的正常工作中&#xff0c;具有四种工作模式&#xff1a;运行、睡眠、停止和待机模式。 在系统或…

小白到运维工程师自学之路 第六十四集 (dockerfile构建tomcat、mysql、lnmp、redis镜像)

一、tomcat&#xff08;更换jdk&#xff09; mkdir tomcat cd tomcat/ tar xf jdk-8u191-linux-x64.tar.gz tar xf apache-tomcat-8.5.40.tar.gzvim Dockerfile FROM centos:7 MAINTAINER Crushlinux <syh163.com> ADD jdk1.8.0_191 /usr/local/java ENV JAVA_HOME /us…

AcWing257. 关押罪犯(二分图+染色法)

输入样例&#xff1a; 4 6 1 4 2534 2 3 3512 1 2 28351 1 3 6618 2 4 1805 3 4 12884输出样例&#xff1a; 3512 解析&#xff1a; 二分&#xff0c;每次查看是否是二分图 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N2e45,M2e55…

《Spring Boot源码解读与原理分析》书籍推荐

Spring Boot 1.0.0 早在2014年就已经发布&#xff0c;只不过到了提倡“降本增效”的今天&#xff0c;Spring Boot才引起了越来越多企业的关注。Spring Boot是目前Java EE开发中颇受欢迎的框架之一。依托于底层Spring Framework的基础支撑&#xff0c;以及完善强大的特性设计&am…

使用 Go 语言实现二叉搜索树

原文链接&#xff1a; 使用 Go 语言实现二叉搜索树 二叉树是一种常见并且非常重要的数据结构&#xff0c;在很多项目中都能看到二叉树的身影。 它有很多变种&#xff0c;比如红黑树&#xff0c;常被用作 std::map 和 std::set 的底层实现&#xff1b;B 树和 B 树&#xff0c;…

前端实现打印1 - 使用 iframe 实现 并 分页打印

目录 打印代码对话框预览打印预览 打印代码 <!-- 打印 --> <template><el-dialogtitle"打印":visible.sync"dialogVisible"width"50%"top"7vh"append-to-bodyclose"handleClose"><div ref"print…

uni-app uView自定义底部导航栏

因项目需要自定义底部导航栏&#xff0c;我把它写在了组件里&#xff0c;基于uView2框架写的&#xff08;vue2&#xff09;&#xff1b; 一、代码 在components下创建tabbar.vue文件&#xff0c;代码如下&#xff1a; <template><view><u-tabbar :value"c…

推荐一款非常简单实用的数据库连接工具Navicat Premium

Navicat Premium是一款非常实用的数据库连接工具&#xff0c;别再用HeidiSQL和idea自带的数据库连接了&#xff0c;看完这篇文章&#xff0c;赶紧把Navicat Premium用起来吧。 首先&#xff0c;需要获取Navicat Premium的安装包&#xff0c;可以通过以下网盘链接下载&#xff0…

刷题笔记 day5

力扣 202 快乐数 首先来分析什么样的数是快乐数&#xff0c; 解题思路&#xff1a; 1&#xff09;定义快慢指针 &#xff1b; 2&#xff09;快指针走两步&#xff0c;慢指针走一步 &#xff1b;3&#xff09;两个指针相遇时判断相遇的数值是否为1。 怎样处理 取各分位数的平…

力扣初级算法(二分查找)

力扣初级算法(二分法)&#xff1a; 每日一算法&#xff1a;二分法查找 学习内容&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 2.二分查找流程&…

SystemVerilog scheduler

文章目录 简介调度器simulation regionPreponed regionActive regionInactive regionNBA(Non-blocking Assignment Events region)Observed regionReactive regionRe-Inactive Events regionRe-NBA RegionPostponed Region PLI region:Pre-active regionPre-NBA regionPost-NBA…

常见的设计模式(超详细)

文章目录 单例模式饿汉式单例模式懒汉式单例模式双重检索单例模式 工厂模式简单工厂模式工厂&#xff08;方法&#xff09;模式抽象工厂模式 原型模式代理模式 单例模式 确保一个类只有一个实例&#xff0c;并且自行实例化并向整个系统提供这个实例。 饿汉式单例模式 饿汉式单…

【React学习】—虚拟DOM两种创建方式(二)

【React学习】—虚拟DOM两种创建方式&#xff08;二&#xff09; 一、Hello React案例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, init…

spring-boot-maven-plugin使用

spring-boot-maven-plugin这个插件有7个目标&#xff1a; spring-boot:build-image 使用构建包将应用程序打包到OCI映像中。 spring-boot:build-info 根据当前MavenProject spring-boot:help 显示有关spring-boot-maven插件的帮助信息。 调用mvn-spring-boot:help-Ddetailtr…