基于STM32设计的智能空调

news2024/11/17 17:46:04

一、项目背景

随着人们生活水平的不断提高,对居住环境的舒适度要求也越来越高。空调作为一种重要的家电设备,已经成为了现代家庭中必不可少的一部分。本文介绍了一种基于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);               //停止信号,传输结束
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单价20块蓝牙耳机卖爆越南市场,现象级爆款出现?

以儒道为文化底蕴的越南&#xff0c;是与中国最为相近的东南亚国家&#xff0c;"快速增长的劳动人口相对年轻的社会群体"是很多人对越南这个国家的基本认知。背靠庞大的Z世代用户群体&#xff0c;越南社会年轻化消费需求暴涨&#xff0c;手机与数码品类商品作为“年轻…

OpenCL编程指南-9.1命令、队列、事件

概述 命令队列是OpenCL的核心。平台定义了一个上下文&#xff0c;其中包含一个或多个计算设备。每个计算设备可以有一个或多个命令队列。提交到这些队列的命令将完成OpenCL程序的具体工作。 在一个简单的OpenCL程序中&#xff0c;提交到一个命令队列的命令会按顺序执行。一个…

ThinkPHP5使用phpqrcode生成二维码

生成指定跳转地址二维码图片&#xff1a; 首先将下载好的phpqrcode.php文件放到指定目录内&#xff08;我这里用的放在public/phpqrcode目录下&#xff09;&#xff0c;准备调用 之后控制器中调用 public function qrcode(){require_once "./phpqrcode/phpqrcode.php&quo…

浅谈能源管理系统在电子厂房中的应用

贾丽丽 安科瑞电气股份有限公司上海嘉定201801 摘要&#xff1a;以能耗管理系统在工业厂房的应用为例&#xff0c;介绍了系统架构及功能。重点分析能耗管理系统在工业厂房实施过程中遇到的难点&#xff0c;并对系统采集的数据进行分析&#xff0c;提出了相应的节能措施&#…

【百问百答】可靠性基础知识第七期

1.什么是振动频率范围? 振动频率范围表示振动试验由某个频率点到另一个频率点进行往复扫频。 例如&#xff1a;试验频率范围5~500Hz&#xff0c;表示5Hz到500Hz进行往复扫频 2.什么是振动量? 振动量&#xff1a;通常用加速度和位移来表示&#xff1b; 加速度&#xff1a;表…

轻松延长手机待机时长,2步设置让你告别电量焦虑

在现代社会中&#xff0c;手机成为了我们生活中不可或缺的伙伴。然而&#xff0c;随着手机功能的日益增多和使用频率的提高&#xff0c;电池续航时间成为了让许多人苦恼的问题。谁不曾遇到过电量不足的尴尬情况&#xff1f;当我们需要手机时&#xff0c;却发现它只剩下最后一丝…

2023年华数杯大学生数学建模【B题不透明制品最优配色方案设计】详细建模方案

目录 完整思路下载链接&#xff1a;这里获取2023华数杯全国大学生数学建模竞赛题目B 题不透明制品最优配色方案设计✅ 问题1问题1建模思路✅ 问题2问题2建模思路✅ 问题3问题3建模思路✅ 问题4问题4建模思路提供的数据和资料&#xff1a; 完整思路下载链接&#xff1a;这里获取…

高电压功率放大器原理是什么意思

高电压功率放大器是一种特殊类型的功率放大器&#xff0c;它可以将输入信号放大到高电压水平。这种设备通常用于测试和测量应用、电子学研究以及医疗成像等领域。它们的工作原理基于半导体器件&#xff08;如晶体管或MOSFET&#xff09;和放大器电路的组合使用&#xff0c;可以…

公司新来了个00后,一副毛头小子的样儿,哪想到是新一代卷王...

内卷&#xff0c;是现在热度非常高的一个词汇&#xff0c;随着热度不断攀升&#xff0c;隐隐到了“万物皆可卷”的程度。 在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不…

【文献分享】KITTI里程计排行榜上第五!CT-ICP:实时弹性激光雷达里程计与回环检测

论文题目&#xff1a;CT-ICP: Real-time Elastic LiDAR Odometry with Loop Closure 中文题目&#xff1a;CT-ICP:实时弹性激光雷达里程计与回环检测 作者&#xff1a;Pierre Dellenbach, Jean-Emmanuel Deschaud, Bastien Jacquet and Francois Goulette 作者机构&#xff…

逻辑代数运算

逻辑代数运算中的三种基本运算 与&#xff08;AND&#xff09;&#xff1a;只有满足全部条件&#xff0c;才会产生结果 或&#xff08;OR&#xff09; &#xff1a;只要满足一个条件&#xff0c;就会产生结果 非&#xff08;NOT&#xff09;&#xff1a;只要满足条件&#xff…

14-4_Qt 5.9 C++开发指南_QUdpSocket实现 UDP 通信_UDP组播

文章目录 1. UDP组播的特性2. UDP 组播实例程序的功能3. 组播功能的程序实现4. 源码4.1 可视化UI设计4.2 mainwindow.h4.3 mainwindow.cpp 1. UDP组播的特性 下图简单表示了组播的原理。UDP 组播是主机之间“一对一组”的通信模式&#xff0c;当多个客户端加入由一个组播地址定…

爆卖1.5万件!这款美牙神器成TikTok“现象级爆款!

在大多数美国人心中&#xff0c;健康洁白的牙齿是自信社交的底气&#xff0c;这使得他们对牙齿美白格外重视。 特看数据显示&#xff0c;TikTok Shop美国小店有一款“牙齿美白套件”近两个多月以 300 元的客单价爆卖 1.5 万件&#xff0c;截至7月 26日&#xff0c;产品近7 天共…

HTML基础铺垫

&#x1f60a;HTML基础铺垫 &#x1f47b;前言&#x1f4dc;HTML文档结构&#x1f3ad;头部head&#x1f94f;标题title标记&#x1f94f;元信息meta标记 &#x1f3ad;主体body&#x1f94f;body标记&#x1f94f;body标记属性 &#x1f3ad;HTML基本语法&#x1f94f;标记类型…

最新SecureCRT 中文注册版

SecureCRT是一款由VanDyke Software公司开发的终端仿真软件&#xff0c;它提供了类似于Telnet和SSH等协议的远程访问功能。SecureCRT专门为网络管理员、系统管理员和其他需要保密访问网络设备的用户设计。 软件下载&#xff1a;SecureCRT for ma注册版 远程访问&#xff1a;Sec…

海外市场品牌定位策略:打造独特品牌形象的关键步骤

在海外市场建立品牌&#xff0c;品牌定位是至关重要的一环。品牌定位是指企业在目标市场中通过一系列战略来塑造品牌形象和传达品牌价值&#xff0c;以区别于竞争对手并满足目标客户的需求和愿望。 在国际化的背景下&#xff0c;品牌定位需要更加细致入微和深思熟虑&#xff0…

《Linux从练气到飞升》No.07 Linux第一个小程序-进度条的实现

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

vue SKU已知sku.tree算出sku.list类目值和id

已知sku.tree算出sku.list类目值和id <van-skuref"sku"v-model"showBase":close-on-click-overlay"closeOnClickOverlay":goods"skuData.goods_info":goods-id"skuData.goods_id":hide-stock"skuData.sku.hide_stoc…

Android Ble蓝牙App(二)连接与发现服务

Ble蓝牙App&#xff08;二&#xff09;连接与发现服务 前言正文一、GATT回调二、连接和断连三、连接状态回调四、发现服务五、服务适配器六、显示服务七、源码 前言 在上一篇中我们进行扫描设备的处理&#xff0c;本文中进行连接和发现服务的数据处理&#xff0c;运行效果图如下…

CSGO游戏搬砖行业乱象

CSGO游戏搬砖行业乱象 CSGO游戏搬砖&#xff0c;这个项目&#xff0c;这个概念相信大家已不再陌生。CSGO这款全球竞技游戏&#xff0c;也早已不是当初的游戏&#xff0c;而是带着目的&#xff0c;带着经济系统向大家缓缓走来&#xff0c;一个虚拟的空间&#xff0c;一种虚拟的…