基于STM32的“智能家居系统”课程设计

此设计是基于STM32F407单片机的智能家居系统,具体完成要求如下:

基于蓝牙的智能家居系统设计

设计一个基于蓝牙/Wifi的智能家居控制系统,实现手机端蓝牙发射和接收控制,并能实现控制各种家用电器设备,设计并完成特定的控制对象。
1、遥控距离大于6米,
2、采用单片机与HC05蓝牙模块实现信号接收与控制端输出。
3、能实现多种负载控制,如灯光、窗帘控制、门铃等智能家居设备的控制
4、画出的系统原理图并焊接调试。
5、单片机可选用stm32系列,手机端app控制家居的开关与灯光亮暗。
6、自行设计其他功能如语音控制等。

一、设计主体思路

设计流程如下图:

值得注意的是我们选择的蓝牙模块是必须要3.3V供电的,否则发送/接收的信号会乱码!!!
(如果选择Wifi模块的话,我选择的是正点原子的Esp8266模块,相关资料比较完善)

二、硬件电路设计

01# MCU主控电路


通过查阅STM32F4的数据手册,查找到对应复用功能的引脚,进行引脚的选择(按键和拨码开关本来是想做一些复杂一点的用户界面以及状态机进行切换,但是时间原因以及课程设计本来没有要求,个人也比较懒,就没有用到这些外设。。。)

02# PCB-3D展示


硬件方面最后插一句嘴,就是舵机的可控电压范围是4.5~8V,基于成本的考虑,设计了两种不同的供电方式,分别引出接口给两舵机5V/6V供电,实测5V(1117-5.0进行稳压)效果也不错,所以可以不对6V(AS1015稳压电路)供电部分电路进行焊接。

三、机械结构设计

由于项目本身是“智能家居”嘛,所以DIY了一个小房子,并且利用3D打印技术将小房子模型打印了出来,拼接起来。(没有3D打印机可以用的同学可以用纸板粘一个出来)。

四、程序设计部分

01# 主函数部分

// 硬件初始化
void BoardInit()
{//  GPIO_InitTypeDef GPIO_InitStructure; //GPIO的初始化BEEP_Init();  //蜂鸣器初始化TIM4_LightPWM_Init(10000,168);   //照明装置初始化--频率50HZ(由于照明与舵机在同一个定时器下初始化,故定时器频率只能按照舵机的50Hz进行初始化)TIM4_SERVOPWM_Init(10000,168);   //舵机初始化--频率50HZuart_init(115200);   //串口1初始化,波特率为115200delay_init(168);   //delay函数的初始化OLED_Init();   //OLED的初始化LED_GPIO_Config();  //LED初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   //中断优先级组别为2(抢占优先级和响应优先级均为4位)EXTIX_Init();   //外部中断初始化}int main()
{BoardInit();TIM_SetCompare2(TIM4,550);    //设定两舵机的初始位置TIM_SetCompare4(TIM4,300);
//  TIM_SetCompare1(TIM4,10000);     //测试照明灯亮度是否可控
//  TIM_SetCompare3(TIM4,10000);while(1){if(oled_flag != 0){OLED_P6x8Str(3, 2,"SMART HOME!");}else{OLED_Cls();}}
}

大部分的动作代码放在串口中断服务函数中,主函数主要是对各模块进行初始化,具体的初始化函数分别在各外设的.c文件中。这里就不一一展示了。

02# 串口1中断服务函数

该部分的代码主要是对接收到的指令进行对应操作(存在一些不足,具体会在后面章节中详细说明)

void USART1_IRQHandler(void)            //串口1中断函数
{u8 Res;#if SYSTEM_SUPPORT_OS       OSIntEnter();    #endifif(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  {Res = USART_ReceiveData(USART1);//(USART1->DR);  读取串口1的存储数据的寄存器  switch(Res){//case('1'):{//发送1激活        printf("Welcome to smart home system!!\r\n");printf("Please send order to choose the mode:\r\n");oled_flag = 1;   //屏幕标志位置1,开始显示printf("2--DoorBell\r\n3--Open Door\r\n4--Lighting\r\n5--Draw the Curtain\r\n6--Close thr Curtain\r\no--Close All\r\n");LED_Bling(2);   //指示灯闪2次,表示智能家居系统已被激活USART1_ClearBUF();  //清除串口1缓冲区数据(自己编写)以保证串口1设定的100个数据不会溢出break;}case('2'):{Beep_Bling();USART1_ClearBUF();break;}case('3'):{TIM_SetCompare2(TIM4,900);delay_ms(2000);TIM_SetCompare2(TIM4,550);USART1_ClearBUF();break;}case('4'):{printf("Please send l,m or h to choose Brightness!");break;}case('l'):{TIM_SetCompare1(TIM4,2000);TIM_SetCompare3(TIM4,2000);break;} case('m'):{TIM_SetCompare1(TIM4,6000);TIM_SetCompare3(TIM4,6000);break;}case('h'):{TIM_SetCompare1(TIM4,10000);TIM_SetCompare3(TIM4,10000);break;}case('5'):{TIM_SetCompare4(TIM4,1100);
//        delay_ms(3000);
//        TIM_SetCompare4(TIM4,800);USART1_ClearBUF();break;   }case('6'):{TIM_SetCompare4(TIM4,300);USART1_ClearBUF();break;}case('o'):{printf("GoodBye!");oled_flag = 0;TIM_SetCompare4(TIM4,300);TIM_SetCompare1(TIM4,0);TIM_SetCompare3(TIM4,0);USART1_ClearBUF();LED_Bling(1);break;}}if((USART_RX_STA&0x8000)==0){if(USART_RX_STA&0x4000){if(Res!=0x0a)USART_RX_STA=0;else USART_RX_STA|=0x8000;  }else //۹û˕ս0X0D{   if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;}}}          } #if SYSTEM_SUPPORT_OS    //ɧڻSYSTEM_SUPPORT_OSΪ֦ìղѨҪ֧ԖOS.OSIntExit();
#endif
}

五、蓝牙模块/Wifi模块的配置

01# 蓝牙模块

本项目中我选择的是BT08b蓝牙模块,购买之后,商家会给出具体的AT指令集以及配置指南,该模块只需要配置一次,故可以通过USB-TTL模块连接PC端先把模块配置好之后再连接单片机使用,这样该模块与普通的无线串口模块使用方式没有区别。

02# Wifi模块(esp8266)

相比蓝牙模块,Wifi模块的配置相对比较复杂,需要在每次上电之后对我们需要连接的上位机端的热点,以及进行模式选择进入TCP/UDP透传模式,但是由于正点原子给出的例程较为复杂(实现“闭环”进行状态确定,接收指令反馈),本人接触时间也并没有很久,所以没有使用官方给出的例程,只是像esp8266发送指令,不对其反馈进行操作。具体实现代码如下:

#include "wifi.h"
#include "usart.h"
#include "delay.h"void WIFI_Init(void)
{printf("AT+CWMODE=1\r\n");delay_ms(3000);printf("AT+CWAUTOCONN=0\r\n");delay_ms(3000);printf("+++");delay_ms(3000);printf("AE0\r\n");delay_ms(3000);printf("AT+CWMODE=1\r\n");delay_ms(3000);printf("AT+RST\r\n");delay_ms(5000);printf("AT+CWAUTOCONN=0\r\n");delay_ms(3000);printf("AT+CWJAP=\"Name\",\"xxxxxxxx\"\r\n");    //热点名称(英文),后面为热点密码delay_ms(8000);printf("AT+CIPMUX=0\r\n");delay_ms(3000);printf("AT+CIPSTART=\"TCP\",\"10.41.75.244\",8080\r\n");   //地址及端口好delay_ms(3000);printf("AT+CIPMODE=1\r\n");delay_ms(3000);printf("AT+CIPSEND\r\n");delay_ms(3000);
}

由于模块接收指令需要一定时间对指令进行处理并做出对应的操作,所以每输出一条指令之后,都进行一段时间的演示,所以Wifi模块在每次上电之后都需要一段较长的时间进行初始化。

更新------电子钟 & 温湿度

此次的更新内容是在原先工程的基础上,完善了相关的用户界面,实现了在不同界面下调节时间、时制转换、秒表的开始/暂停、闹钟的设定、设定温湿度报警的阈值的功能。

01# 电子钟

(1)时制转换的功能是由拨码开关实现的----通过读取单片机IO口的高低电平。检测到电平不一致的时候就会进行时制转换;
(2)秒表和普通时钟&闹钟没有放在同一个定时器中,所以定时其采用了不同频率;
具体如何实现见如下代码(工程中的 tim.c 文件):

//时钟变量初始化
ClockNode CLK_interface =
{.year = 2021,    //闰年被四整除不被100整除.month = 11,    //月份数组.date = 17,.weekday = 3,.h = 10,.min = 0,.s = 0,.tomorrow_flag = 0
};int month_days;
int month_1[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};      //闰年/非闰年每月天数
int month_2[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int timer_flag = 0;   //计时器开始与结束//计时器初始化(定时器2---0.01s)
ClockNode Millisecond =
{.h = 0,.min = 0,.s = 0,.ms_10 = 0
};//闹钟初始化
ClockNode Alarm =
{.h = 0,.min = 0, .s = 0};void clock_24(void)
{CLK_interface.s += 1;if(CLK_interface.s > 59) {CLK_interface.min += 1;CLK_interface.s  = 0;if(CLK_interface.min > 59){CLK_interface.h += 1; CLK_interface.min = 0;Beep_Bling_once();if(CLK_interface.h > 23){CLK_interface.date += 1;CLK_interface.h = 0;if(CLK_interface.year % 4 == 0 && CLK_interface.year % 100 != 0)  //判断是否为闰年{month_days = month_2[CLK_interface.month - 1];}else month_days = month_1[CLK_interface.month - 1];if(CLK_interface.date > month_days){CLK_interface.month += 1;CLK_interface.date = 1;if(CLK_interface.month > 12){CLK_interface.year += 1;CLK_interface.month = 1;}}}}}
}void clock_12(void)
{CLK_interface.s += 1;if(CLK_interface.s > 59) {CLK_interface.min += 1;CLK_interface.s  = 0;if(CLK_interface.min > 59){CLK_interface.h  += 1; CLK_interface.min = 0;Beep_Bling_once();if(CLK_interface.h > 11){                CLK_interface.h = 0;if(CLK_interface.tomorrow_flag % 2 == 1){CLK_interface.date += 1;CLK_interface.tomorrow_flag = 0;}                    if(CLK_interface.year % 4 == 0 && CLK_interface.year % 100 != 0)  //判断是否为闰年{month_days = month_2[CLK_interface.month - 1];}else month_days = month_1[CLK_interface.month - 1];if(CLK_interface.date > month_days){CLK_interface.month += 1;CLK_interface.date = 1;if(CLK_interface.month > 12){CLK_interface.year += 1;CLK_interface.month = 1;}}}}}
}void Millisecond_clock(void)
{if(timer_flag % 2 ==1 ) Millisecond.ms_10 += 1;  if(Millisecond.ms_10 > 99){Millisecond.s += 1;Millisecond.ms_10 = 0;if(Millisecond.s > 59){Millisecond.min += 1;Millisecond.s = 0;if(Millisecond.min > 59){Millisecond.h += 1;Millisecond.min = 0;}}}
}int time_conv_flag = 1;void TIM3_IRQHandler(void)
{month_days = month_1[CLK_interface.month - 1];if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){//time_conv_flag = SWITCH6_READ;   //标记拨码开关状态反转if(CLK_interface.h >= 12) CLK_interface.tomorrow_flag = 1;if(CLK_interface.tomorrow_flag == 0 && CLK_interface.h == 11 && CLK_interface.min == 59 && CLK_interface.s == 59){CLK_interface.tomorrow_flag = 1;}if(SWITCH6_READ == 0){if(CLK_interface.tomorrow_flag%2 == 1 && SWITCH6_READ != time_conv_flag && CLK_interface.h > 12){CLK_interface.h -= 12;time_conv_flag = SWITCH6_READ;   //记忆上一次拨码开关的状态}clock_12();}else{if(CLK_interface.tomorrow_flag%2 == 1 && SWITCH6_READ != time_conv_flag && CLK_interface.h < 12){CLK_interface.h += 12;time_conv_flag = SWITCH6_READ;   //记忆上一次拨码开关的状态}clock_24();if(CLK_interface.h == Alarm.h && CLK_interface.min == Alarm.min && CLK_interface.s == Alarm.s) Beep_Bling();}int alarm_flag = 0;getTem_Humi();if(DHT11.tempereture >= tempereture || DHT11.humidity >= humidity){alarm_flag = 1;if(DHT11.tempereture >= tempereture && DHT11.humidity >= humidity){alarm_flag = 2;}}if(alarm_flag == 1) LED_Bling(1);if(alarm_flag == 2) Beep_Bling_once();}TIM_ClearITPendingBit(TIM3, TIM_IT_Update);   //清除TIM3更新中断标志
}void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){   if(Millisecond.h > 12){Millisecond.h = 0;}      Millisecond_clock(); }TIM_ClearITPendingBit(TIM2, TIM_IT_Update);   //清除TIM2更新中断标志
}

02# 用户界面部分

#include "User-interface.h"
#include "oled.h"
#include "tim.h"
#include "key.h"
#include "delay.h"
#include "DHT11.h"UserinterfaceNode UserInterface =
{.PageNum = 4,.paraNum = 5
};int Para = 0;//时钟界面
void Clock_Interface(void)
{OLED_P6x8Str(1, 3, "Custom_clock!");OLED_P6x8Str(3, 1, "Date:");OLED_P6x8Int(4, 2, CLK_interface.year, 4);OLED_P6x8Str(4, 8, "-");OLED_P6x8Int(4, 9, CLK_interface.month , 2);OLED_P6x8Str(4, 13, "-");OLED_P6x8Int(4, 14, CLK_interface.date, 2);OLED_P6x8Str(5, 1, "Time:");OLED_P6x8Int(6, 2, CLK_interface.h, 2);OLED_P6x8Str(6, 5, ":");OLED_P6x8Int(6, 6, CLK_interface.min, 2);OLED_P6x8Str(6, 9, ":");OLED_P6x8Int(6, 10, CLK_interface.s, 2);OLED_P6x8Int(7, 15, Para % UserInterface.paraNum, 1);
}void timer_clock(void)
{OLED_P6x8Str(1, 5, "TIMER!!");OLED_P6x8Str(3, 0, "Hour:");OLED_P6x8Int(3, 5, Millisecond.h, 2);OLED_P6x8Int(5, 2, Millisecond.min, 2);OLED_P6x8Str(5, 5, ":");OLED_P6x8Int(5, 6, Millisecond.s, 2);OLED_P6x8Str(5, 9, ":");OLED_P6x8Int(5, 10, Millisecond.ms_10, 2); OLED_P6x8Int(7, 15, Para % UserInterface.paraNum, 1);
}void Alarm_clock(void)
{OLED_P6x8Str(1, 5, "Alarm clock!!");OLED_P6x8Int(5, 2, Alarm.h, 2);OLED_P6x8Str(5, 5, ":");OLED_P6x8Int(5, 6, Alarm.min, 2);OLED_P6x8Str(5, 9, ":");OLED_P6x8Int(5, 10, Alarm.s, 2);OLED_P6x8Int(7, 15, Para % UserInterface.paraNum, 1);
}void Tem_Hum_DBG(void)
{OLED_P6x8Str(1, 3, "TEM&HUMI-Debug");OLED_P6x8Str(3, 0, "Temp:");OLED_P6x8Int(3, 4, (int)DHT11.tempereture, 2);OLED_P6x8Str(4, 0, "Humi:");OLED_P6x8Int(4, 4, (int)DHT11.humidity, 2);OLED_P6x8Str(5, 0, "Threshold:");OLED_P6x8Str(6, 0, "Tem:");OLED_P6x8Int(6, 4, tempereture, 2);OLED_P6x8Str(6, 9, "Humi:");OLED_P6x8Int(6, 14, humidity, 2);OLED_P6x8Int(7, 15, Para % UserInterface.paraNum, 1);
}void Key_Hub(void)
{delay_ms(168);if((KeyMessage.KeyValue = Key_Scan()) == KEY_PAGE){   ++UserInterface.PageStatus;UserInterface.PageStatus = (PAGE_STATUS)(UserInterface.PageStatus % UserInterface.PageNum);OLED_Cls();}if(KeyMessage.KeyValue == KEY_PARA) Para += 1;switch (UserInterface.PageStatus){case Custom_clock:{UserInterface.paraNum = 6;     Clock_Interface();switch(Para % UserInterface.paraNum){case(0):{DebugI(&CLK_interface.year, 1);break;               }case(1):{if(CLK_interface.month <= 12 && CLK_interface.month > 0) DebugI(&CLK_interface.month, 1); else CLK_interface.month = 1;break;}case(2):{if(CLK_interface.year % 4 == 0 && CLK_interface.year % 100 != 0)  //判断是否为闰年{month_days = month_2[CLK_interface.month - 1];}else month_days = month_1[CLK_interface.month - 1];if(CLK_interface.date <= month_days && CLK_interface.date > 0) DebugI(&CLK_interface.date, 1); else CLK_interface.date = 1;break;}case(3):{if(CLK_interface.h < 24 && CLK_interface.h >= 0) DebugI(&CLK_interface.h, 1);else CLK_interface.h = 0;break;}case(4):{if(CLK_interface.min < 60 && CLK_interface.min >= 0) DebugI(&CLK_interface.min, 1);else CLK_interface.min = 0;break;}case(5):{if(CLK_interface.s < 60 && CLK_interface.s > 0) DebugI(&CLK_interface.s, 1);else CLK_interface.s = 0;break;}         }break;}case Timer_clock:{timer_clock();if(KeyMessage.KeyValue == KEY_START_STOP) {timer_flag += 1;    //决定定时器的使能与失能}if(timer_flag > 8){Millisecond.h = 0;Millisecond.min = 0;Millisecond.s = 0;Millisecond.ms_10 = 0;timer_flag = 0;}break;}case Alarm_Clock:{UserInterface.paraNum = 3;Alarm_clock();switch(Para % UserInterface.paraNum){case(0):{if(Alarm.h < 24 && Alarm.h >= 0) DebugI(&Alarm.h, 1); else Alarm.h = 0;break;}case(1):{if(Alarm.min < 60 && Alarm.min >= 0) DebugI(&Alarm.min, 1); else Alarm.min = 0;break;}case(2):{if(Alarm.s < 60 && Alarm.s >= 0) DebugI(&Alarm.s, 1); else Alarm.s = 0;break;}}break;}case Tem_Hum:{UserInterface.paraNum = 2;Tem_Hum_DBG();switch(Para % UserInterface.paraNum){case(0):{DebugI(&tempereture, 1);break;}case(1):{DebugI(&humidity, 2);break;}}break;}}
}

03# 温湿度模块

此部分代码较为简单,相关的配置函数该博主的分享, 单总线通信的配置函数很好理解,看过之后复制之后很快就可以读取到温湿度数值了。

更新后的主函数

变化不大,基本上的功能都封装成函数了,主函数中非常干净整洁:

#include "headfile.h"
#include "User-interface.h"// 硬件初始化
void BoardInit()
{//  GPIO_InitTypeDef GPIO_InitStructure; //GPIO的初始化BEEP_Init();  //蜂鸣器初始化TIM4_LightPWM_Init(10000,168);   //照明装置初始化--频率50HZTIM4_SERVOPWM_Init(10000,168);   //舵机初始化--频率50HZuart_init(115200);   //串口1初始化,波特率为115200delay_init(168);   //delay函数的初始化OLED_Init();   //OLED的初始化LED_GPIO_Config();  //LED初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   //中断优先级组别为2(抢占优先级和响应优先级均为4位)//EXTIX_Init();   //外部中断初始化TIM3_Init(10000, 8400);   //定时器3初始化-----1sTIM2_Init(10000, 84);      //定时器2初始化----0.01sKey_Init();    //按键初始化switch_Init();    //拨码开关初始化DHT11_Init();     //温湿度模块初始化
} int main()
{BoardInit();TIM_SetCompare2(TIM4,300);TIM_SetCompare4(TIM4,300);
//  TIM_SetCompare1(TIM4,10000);
//  TIM_SetCompare3(TIM4,10000);while(1){//oled_flag = 1;      //调试的时候方便看屏幕if(oled_flag != 0){//OLED_P6x8Str(3, 2,"SMART HOME!");Key_Hub();}else{OLED_Cls();}}
}

六、项目的不足

01# 串口指令

由于当时对于串口接收的缓冲区数据了解不足,所以只能读取到一位数据,所以每个指令都设置为一位字符,并且没有区分指令的优先级(e.g.:没有设置开机指令执行之后才能执行其他指令、也没有设置控制灯亮度的指令必须在执行控灯指令执行之后才能执行),可以通过设置对应的标志位进行状态判别,从而实现指令的不同优先级设定。

02# 上位机

由于没学过上位机的设计,所以导致用到的上位机都是网上界面比较简陋的上位机,之后如果有接触到的话,可以对应设计对应的上位机,使UI更加美观。

完整资料已上传百度网盘(有需要可以下载)
链接:https://pan.baidu.com/s/1RE_kGghCOCSc6G-6EwNKOA
提取码:0727

  • 更新后的工程也已经上传百度网盘:
    链接:https://pan.baidu.com/s/1R-kOQKB72baMar47mIdwrw
    提取码:0727

PS:希望该文对有需要的同学们能有一定的帮助,项目本身还有很多缺陷以及可以优化提升的方面,希望大佬们轻喷,不足的地方可以指正出来!!!

基于STM32的“智能家居”课程设计相关推荐

  1. 基于stm32的智能家居项目

    基于stm32的智能家居 具体教程可以看文中的B站链接,上面有手把手教程 本人其他项目链接基于linux的智能仓储项目 基于Qt的人脸识别 移植人脸识别到Linux开发板上 基于正点原子的IMX6UL ...

  2. 基于linux的 设计,基于Linux的智能家居的设计(一)

    本课题主要目的是设计和实现一个基于Linux开发平台的智能家居系统.本系统主要使用PVC板做成的家居模型.本系统硬件使用基于ARM架构的samsung S3C6410芯片做成的OK6410开发板为手持 ...

  3. 基于ZigBee的智能家居的设计与实现—目录

    基于ZigBee的智能家居的设计与实现-开篇 基于ZigBee的智能家居设计与实现-CC2530开发 基于ZigBee的智能家居设计与实现-WiFi模块开发 基于ZigBee的智能家居设计与实现-MQ ...

  4. 基于STM32的智能小车--电机驱动设计

    基于STM32的智能小车 第一章 基于STM32的智能小车方案设计 基于STM32的智能小车--电机驱动设计 基于STM32的智能小车 前言 一.电机是什么? 二.常见电机分类 1.有刷电机 2.无刷 ...

  5. 基于Linux的智能家居的设计(3)

    2  硬件设计 本课题的硬件设计包含主控制器.传输数据设计.数据採集设计.控制驱动设计.显示设计.门禁设计. 2.1  主控制器 依据方案三选择S3C6410主控芯片,S3C6410是由Samsung ...

  6. 基于ZigBee的智能家居的设计与实现—开篇

    目录 需求与功能 需求介绍 网络设计 实现功能介绍 系统选型 硬件选型 技术选型 需求与功能 需求介绍 设计一套 基于ZigBee的智能家居 ,要求: 使用ZigBee完成硬件组网 使用WiFi将硬件 ...

  7. 基于Linux的智能家居的设计(1)

    写在前面:做了半年的毕业设计,找到的工作与这个完全无关,发现自己现在有写不甘心,但是我还是在关注这方面的发展,自己的摸索和前人的帮助我完成了智能家居的一部分,希望这个能够给一些初学者 能够一些便利,毕 ...

  8. 基于linux智能家居系统设计,基于Linux的智能家居的设计(2)

    智能家居系统的是一个实时查询家庭的温湿度.照明控制.自己主动控制的设定.集家庭娱乐.智能安防为一体,大量数据快处理.可靠的系统,因此在硬件和软件上都有非常大的要求,因此在这里进行了多方面的考虑有下面两 ...

  9. 基于STM32的智能家居控制系统设计与实现(带红外遥控控制空调)

    1. 前言 智能家居作为家庭信息化的实现方式,已经成为社会信息化发展的重要组成部分,物联网因其巨大的应用前景,将是智能家居产业发展过程中一个比较现实的突破口,对智能家居的产业发展具有重大意义. 本文基 ...

最新文章

  1. 服务器 上传文件 杀毒,一种实现文件上传网站后自动进行杀毒的方法及系统
  2. MPLS TE基本配置-OSPF
  3. MyBatis——动态SQL讲解
  4. Hackbar PJ
  5. 可以直接在C++里面写类似RSL的shader了
  6. 常数除以0的极限是什么_酶动力学中的一些常数简介
  7. c# post 读取返回html_PHP GET与POST
  8. python generator转为list_Python中的 List Comprehension 以及 Generator
  9. CABasicAnimation animationWithKeyPath Types
  10. linux dhcpv6 客户端,Linux(RedHat6.4)下配置radvd和dhcpv6
  11. Excel批量随机生成姓名
  12. sam-ba_2.15 使用usb Device 连接AT91SAM9261EK开发板
  13. linux 查找pcre源码,pcre使用例子
  14. 约坡慈尉仪特诨谙凹毖仍怯滋傥丛
  15. 科普 | 什么是稀疏默克尔树多值证明
  16. Xcode 用Ad_Hoc方式打包
  17. 华为面试题c/c++
  18. matlab sym 画图,poly2sym之后的画图问题
  19. java ognl表达式_Arthas的高级操作-Ognl表达式
  20. 3dmax 视图切换

热门文章

  1. 塔望食品品牌策划:中国植物肉市场品牌总结分析及盘点
  2. ZkClient之读取数据。
  3. 标签打印软件如何打印指定日期
  4. 以太坊之ganache命令行参数的详解
  5. nginx配置wss协议
  6. 惠普(HP)笔记本的型号解析
  7. 开环快速峰值检波器电路
  8. EXCEL中如何删除某一行及以下的所有单元格
  9. Oracle创建序列的方式
  10. 使用ResNet18实现CIFAR10数据集的训练