STM32嵌入式实现智能家居控制系统
. ^' l l4 g" t3 V
+ g& @( s" h0 G6 Q本文将讲述如何用STM32嵌入式实现智能家居控制系统,所谓智能就是实时监测自主控制一些因素,如,温度、湿度、光照强度等,当室内光线较暗时自动打开灯,根据光线亮度的不同开灯数量也不同,当室内温度过高时红灯不停的闪烁,蜂鸣器也报警提醒主人室内温度过高要打开空调,当室内湿度过高时风扇开始工作,让室内湿度降下来,那么如何实现这些功能呢?下面我们开始介绍!
' s- r! l- B9 x" t, Y! o2 E' U$ k5 v2 N3 V0 f
一、本文用到的器件有:
2 a, J1 k6 l: MSTM32F103R6 单片机- g! A# T w; X7 @
LCD12864 液晶显示屏
, l# p& t6 E C- {; GDHT11 温湿度传感器
. e$ y6 o: x9 G& d( XRETCH 光敏电阻
& L8 Z% z/ {5 Z% j. d: _$ `FAN-DC 直流风扇/ R' x( D. _- T! B4 d D
BUZZER 蜂鸣器
5 Z7 t" C8 {; g. g6 Y0 U# a6 `& _电阻、按键等
" \$ V5 Y2 n9 Y9 _9 t2 N V1 ~ w4 C! @5 S3 m( M2 ~
+ ~1 _: [% z0 g% Y# \, }& V
二、实现的功能是:% t n: v k" L. K: W
有两种控制模式,分别是默认的智能控制模式和手动控制模式,按下按键MODE可切换控制模式( W3 n X/ g! Y
0 `! [8 p+ v! b$ B& t) c3 X
: J6 J; r5 \6 K# R
智能控制模式中温湿度传感器实时监测当前温湿度,当温度大于30红灯闪烁,蜂鸣器报警,当湿度大于50时,风扇工作,当光照强度小于3000时点亮一个灯,小于2000时点亮二个灯
9 C, K! I( Y0 d1 O6 _- r4 e. r% K0 G2 n Z' x: Y- j
0 n' X& t8 m( k# h9 u1 n0 Z; z: A
手动控制模式中,按下UP键或者 DOWN键可上下移动光标,按下OK键可打开或关闭当前状态
2 c* J2 p: T2 J; }/ p; T/ x, P! D1 h- ^* @4 y
& [) @9 |/ s1 u! ? h# n
自动模式中手动可调节,手动模式中自动模式不能调节
0 ?- [* h1 h d& }& v3 F% P2 X2 y0 \2 D2 V
4 R( f* v1 G! O$ X% F三、原理图如下:
) E) `$ A! e+ l) n/ K3 Y; D四、代码实现:
- A: N% s, t; X! d
4 S9 B8 [9 K: j b$ R- #include "stm32f10x.h"
# y2 x5 I3 E4 ` - #include "LQ12864.h" k, ]& h5 ^+ _5 o2 r
- #include "DTH11.h"
1 D" j- n8 ^+ a! O - #include <stdio.h>
# P4 K( N- t$ W/ H4 J/ e - #include "adc.h"
9 B" c* z1 o. X8 I - & w3 M( q' h+ p4 a
- #define UP 1
' t; ?: A; T" s7 |$ {, z - #define DOWN 2$ b' O' e! N6 g$ l9 P3 Q
- #define OK 3% n. H; l' V$ V2 ?" k, |
- #define MODE 42 x, @* u- d( m/ Q% H) j
- #define NONE 0% q, N3 o. X( d% x5 q
2 A4 h8 K4 l& ?# w
3 E3 L% V+ j4 L0 B- void main_delay(int time)2 |/ j$ S1 i) o5 b& A7 B
- {
; l# L5 M9 o) k* Y2 I; _) [: a# h - int i,j;
6 N/ X w5 b- W& {: n: e: v - for(i = 0; i < time; i++)4 v1 Y4 k. H5 i2 D& \
- {
0 r2 m) a9 \& l# @) c. p# m$ c% h. w - for(j = 0; j < 1000; j++)6 J) c" V5 |$ J) O
- {
& B% ~$ z# B1 {" `( d1 j - j++;" u3 L3 J& R; |- o6 I
- j--;
8 w" V: s: g; x+ y" i - }
/ B& L) x$ _3 m' [) d - }9 P( j+ d* @+ b. N3 \- @. F' O
- }
0 f; T4 r& Z$ L2 t. B @* O - # L/ Y' V* M1 w; @, W
- //按键初始化
) n- D- f& I& K y - void keyInit()- u3 c0 F9 @3 p- R% j
- {
5 t6 q" N9 V! h - GPIO_InitTypeDef init;
8 W# F8 t/ b/ u - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
: U7 b+ g$ T2 Z0 Y1 t* K - init.GPIO_Mode = GPIO_Mode_IPU;//输入模式
@ O7 R6 x: \$ k - init.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;! t8 d; |3 u% A# b8 t
- init.GPIO_Speed = GPIO_Speed_50MHz;. f/ v/ m9 f ?$ F3 C
- GPIO_Init(GPIOA,&init);7 c* ?& g& M5 W$ N" F' _8 T
- }5 _5 [ o1 y" W
- //读取按键的值* ]1 y3 n8 H% X, u' T: v) S
- int keyRead()% v5 u! N! I4 I D# l1 m1 i
- {
! J4 e( p: p) A - if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) == 0)7 l ~5 v; K+ l/ f5 @$ P7 T9 I
- return UP;//上! T& w8 G5 a% Q# w0 Q
- if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3) == 0)
' a9 o: \& a2 W4 ~ - return DOWN;//下
& U0 G- h$ F/ g- }- l' p- j, i - if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 0)
/ t i5 x6 g/ ~& \0 ?2 G6 R - return OK;//确定3 n, G$ E2 }4 V9 t7 q& e
- if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0)
( q0 b1 m1 z# u - return MODE;//模式切换
% W2 N6 O: {, G* | - return NONE;* {3 H h5 P/ p$ C
- }
) R0 F: ?# ^; s7 t- x5 m - t' _7 a- f& F# U* ]1 z
- //风扇初始化
" s e& _ _0 P9 c2 f, W" ]9 t - void fanInit()4 R# `; Q1 I; K1 G
- {
$ `+ X/ D. I W# Y n. `$ x - GPIO_InitTypeDef init;
* _' x" q! c& Q5 q3 C4 V ?8 \" b - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
- Q( c* v8 }1 U) S - init.GPIO_Mode = GPIO_Mode_Out_PP;//输出模式
6 h) B) ]. n7 g6 V - init.GPIO_Pin = GPIO_Pin_1;
" H# G) ^+ k2 D# { - init.GPIO_Speed = GPIO_Speed_50MHz;
( F" m0 }! h) b4 Q* k - GPIO_Init(GPIOC,&init);
( ^, C7 E; y4 u$ h( I - GPIO_SetBits(GPIOC,GPIO_Pin_1);//置1 风扇关
; q2 y8 K& n! i - }
6 t" }& S2 o+ D6 Z - //控制风扇开关 fanSwitch(1);//开风扇 fanSwitch(0);//关风扇3 e) T( p, d7 P) s1 N2 }' v$ t
- void fanSwitch(int sw)// 参数 传递1 开 传递0 关
/ B! a" f) U" S9 {7 C7 z, s - {// 1 真 0 假 真执行:左边,开风扇,假执行:右边,关风扇
8 Q5 P& {0 {! B3 |/ { - sw ? GPIO_ResetBits(GPIOC,GPIO_Pin_1) : GPIO_SetBits(GPIOC,GPIO_Pin_1);
h& I* Y+ J" T6 N# x0 Q$ q - }0 T7 c8 C+ g) u, w1 q
& Y8 z, s6 S; P6 Y# Z. n3 m s- //蜂鸣器初始化
2 F8 V8 U0 o/ l# g - void buzzerInit()
2 \* F- ^2 c: ~# U( C6 c5 v7 W& @4 Z - {/ p( I: Y" D) Z# t2 m7 d2 c
- GPIO_InitTypeDef init;. _* r" ]) M. i$ E
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
. z0 c( x" M1 [& C8 p" a9 x - init.GPIO_Mode = GPIO_Mode_Out_PP;//输出模式6 [' H2 F- n4 J" N. u
- init.GPIO_Pin = GPIO_Pin_2;4 M+ C/ f+ P& ]# X6 D
- init.GPIO_Speed = GPIO_Speed_50MHz;5 v' i0 i# N. n0 A8 B$ k2 T4 Z
- GPIO_Init(GPIOC,&init);
% A; C2 `5 p' i2 y+ J; Q - GPIO_SetBits(GPIOC,GPIO_Pin_2);//置1 蜂鸣器关8 P R o0 d6 j$ A
- }
9 K. }! w8 t) w: `+ w - //蜂鸣器开关
4 r1 O) N2 q2 Q' v% M7 v1 [ - void buzzerSwitch(int sw) //1开 0关
) N, C6 r7 e0 _# ]4 E5 o - {
# X# b! y/ {: {) \8 y- q0 B7 \) x - sw ? GPIO_ResetBits(GPIOC,GPIO_Pin_2) : GPIO_SetBits(GPIOC,GPIO_Pin_2);4 n/ I+ R# e' z6 i: x
- }" V6 z( A& y' o' `0 s E
1 K6 U- r. q0 J3 o( u- //LED初始化
% k3 E. ]5 @7 y% S q7 W4 u+ G - void ledInit()! _: ?8 w4 n& ?! ~4 j$ L0 h$ {
- {
9 h7 L& S. h. k" a( G, B - GPIO_InitTypeDef init;8 X6 F. l+ q0 U4 i) {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);7 ^# }, ^' z% ?! Q
- init.GPIO_Mode = GPIO_Mode_Out_PP;//输出模式
. H$ W/ M Y. L o. h( D8 I v - init.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_6|GPIO_Pin_7;, \' s8 B* l9 v+ H. w
- init.GPIO_Speed = GPIO_Speed_50MHz;+ N, \4 |( D, b3 x5 O
- GPIO_Init(GPIOA,&init);
6 B) p0 T- L2 Q. N( E7 k - GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_6|GPIO_Pin_7);//置1 LED关) L3 `7 A& w5 D4 {& G, P
- }
$ J, P) U, @8 L% K+ P - 5 s9 X t; T2 L! @9 k% o7 P
- //控制LED的开关 ledSwitch(3,1);
6 S' M( o* H3 d% J* K( |" k - void ledSwitch(int n,int sw)//n代表灯的编号 sw 1开 0关% y' X" ^# k4 `4 v+ H9 o7 T
- {
, x- J1 W, H, O8 B1 g0 T! _ - switch(n)9 `9 @" T. ^' n9 D+ p7 Q
- {- y7 t: V, ^8 v, K
- case 1: //编号为1的LED
' b- @) o' X. M0 }& @5 f - sw ? GPIO_ResetBits(GPIOA,GPIO_Pin_6) : GPIO_SetBits(GPIOA,GPIO_Pin_6);
8 N% a3 w9 j) t4 J - break;
5 o% q) z$ |! J - case 2: //编号为2的LED
7 w7 `2 Z& |! M' J9 r. R. i. u - sw ? GPIO_ResetBits(GPIOA,GPIO_Pin_7) : GPIO_SetBits(GPIOA,GPIO_Pin_7); F% f; P. B7 D4 Y2 |9 M: H
- break;
' F5 O5 `1 x0 b1 c - case 3: //编号为3的LED9 W8 ?: Y* i$ p# f; y
- sw ? GPIO_ResetBits(GPIOA,GPIO_Pin_1) : GPIO_SetBits(GPIOA,GPIO_Pin_1);
4 h4 a1 N# k+ v# M1 k% u( Y - break;
3 x y/ G- D$ `: T$ w; L - }$ i& z4 U- W" V' } [
- }
- }3 D/ X r" A - 3 C4 R8 o* E! s/ ]2 J: ^2 U
! ^' t" Q9 H/ R( _% j- //系统初始化函数(相关初始化的函数)
( R1 T$ V5 v; y3 P9 J8 p# k1 F - void systemInit()
$ _' m6 `+ f% X F; T2 L# Y! p - {
2 P+ y# _! G/ |# g6 b0 x - LCD_Init();//LCD屏幕初始化
- I7 Z: o+ a! L) }7 \' g. [ - Adc_Init();//ADC初始化9 O+ X. L9 ~6 v Y7 W
- DHT11_Init();//温湿度传感器初始化; E9 W3 B) W5 R/ @8 z8 e4 m
- keyInit();//按键初始化
, r) D$ k: c7 [7 N) K, V - fanInit();//风扇初始化
0 E1 X, p, t5 r. A/ m; b4 S - buzzerInit();//蜂鸣器初始化+ G3 u$ R( n% c0 d, F' \% @" F! J
- ledInit();//led初始化
5 R/ m& H- {: ~: b - }& e j5 H( B6 t3 B+ f# q1 Z
4 k& r: z0 }, s, V" J- int main(void)% }4 Q1 z" k+ ~. l
- {
+ s/ P* K* ]9 t: i- B3 `, Q - char status[5] = {0,0,0,0,0};//LED1 LED2 FAN BUZZER MODE 状态 1开 0关
/ t4 W0 S: h& c. f+ ] - u8 temp,hum;//保存温湿度
$ p8 O, I. [' o4 R - int light;//保存光照强度
0 e/ {7 i! L, ]( _0 l ~+ v - int key;//保存读取到的按键的值
" G W8 N5 i7 t# [$ g7 w: @$ q - char buf[100] = { 0 };//用来保存格式化出的字符串
! K3 I& P: _: C! |$ L% F. | - int flag = 3;//flag时刻代表当前星星的行数
$ N# W7 X9 D- `( c; `' x. y- M - u8 *menu[4] = {"LED1","LED2","FAN","BUZZER"};//字符指针数组( b, ?" Q7 a2 t' b5 Z
- int i;//循环变量& s3 M4 w4 m! |8 C: t
- 0 d7 l# B" b8 B4 R3 ~% C
- systemInit();//系统初始化
7 N5 r% m: Z& ]% G* W: O6 r% W( P0 R - ( S& o; N$ F7 ^+ F" c2 N
- while(1)
% F, \* Q: \! `5 v6 b - {5 I2 T6 |4 ]* L) @
- //在第0-1行显示温湿度和光照强度
6 U, s! w( h+ |" \/ Z" s* S - DHT11_Read_Data(&temp,&hum);//读取温湿度
5 N3 o" g9 _* ~' p7 y - light = Get_Adc();//读取光照强度) O& t; C5 p6 H" \$ }8 L3 Q
- sprintf(buf,"TEMP:%d HUM:%d",temp,hum);//格式化字符串
% v; ?7 P# \3 `2 x - LCD_P6x8Str(0,0,(u8*)buf);//第0行打印温度和湿度
/ q; x$ z5 S' K8 B7 h& Z" ~( ? - sprintf(buf,"LIGHT:%d ",light);//格式化字符串, L/ {) B- `9 Q+ D6 K6 R7 u0 x1 ?
- LCD_P6x8Str(0,1,(u8*)buf);//第1行打印光照强度
6 Z" t+ O6 I: H - //默认就是智能控制模式 temp > 30 报警红灯闪烁 hum > 50 风扇开 0-2000开一个LED 2000-4500开两个灯# W3 m+ Q( n0 C0 K* ?; n+ ?
- if(!status[4])//status[4] 初始值是0
6 |# x. [: l8 _. z& e% D - {
# D8 B, Z0 V* z; u2 S - //温度
/ E5 Y8 A7 Z4 P! L* k$ L- P3 A - if(temp > 30)
2 l' ~) L- s- o; a7 @ - {
# |4 p& S+ p8 L/ e4 Q - buzzerSwitch(status[3]=1);//蜂鸣器响
. {2 F% L* E0 H' M; r - ledSwitch(3,1);//红灯亮1 _) ]! q1 ` c2 E5 L$ B
- main_delay(200);
4 w0 P% i3 }0 n: B+ A% N - ledSwitch(3,0);//红灯灭
+ I/ A `! K# Z& \5 i, I& ~2 M - }. V @0 E/ d# q4 u
- else: I+ c% `! | C: f! x7 d
- {# h2 G+ d3 U3 \# Z3 \" i v6 v
- buzzerSwitch(status[3]=0);//蜂鸣器关
7 Z! \& q# t: m, p7 j" v, x - ledSwitch(3,0);//红灯灭/ L% ^& T- T |4 K! v4 S
- }
8 s4 } `) b4 M9 \' G+ N - //湿度% J8 O" B. {9 W
- hum > 50 ? fanSwitch(status[2]=1) : fanSwitch(status[2]=0);8 h- W* T: r$ ?( q- M+ y
- //光照强度
5 @* u' \& W- g - if(light > 0 && light <= 1000)
$ Y0 ^6 y' n& C- _% n# Z5 \ - {
2 l& _$ O. _0 a( W3 U0 |$ _ - ledSwitch(1,status[0]=0);//1号灯灭9 y+ v+ b: n2 Z R, F8 L
- ledSwitch(2,status[1]=0);//2号灯灭
$ {3 J& E! b, g4 h1 V0 v5 \# H - }
# d- q/ D8 ?* ^! A, j - else if(light > 1000 && light <= 2000)
" y" o, ~4 `' `6 J2 X) \! ~ - {; G" E) l0 R' \
- ledSwitch(1,status[0]=1);//1号灯亮
" o- z) O5 b9 z/ M4 \% G - ledSwitch(2,status[1]=0);//2号灯灭
: d) L2 \) t. S* i' w s - }
) Z8 \9 e( B; G( P0 \ - else if(light > 2000 && light < 4500)
2 }* N( T% t: Z* \ - {
% d! H! q- d3 U9 Y* p: X - ledSwitch(1,status[0]=1);//1号灯亮# n Z8 Q. q; h, n l
- ledSwitch(2,status[1]=1);//2号灯亮# ^$ E1 F# p3 d. s8 Z
- }
/ v5 C7 |- g* u ~& b" _ - }
7 g$ n! l4 m8 M* @ - //在第3-6行显示菜单
; w- H( G9 q6 {* A% z, X - for(i = 0; i < 4; i++)//i == 0 1 2 38 X1 m2 @" F* z
- LCD_P6x8Str(0,i+3,menu[i]);// i+2 3 4 5 6 行
; q C/ Z1 J% F3 f, n - LCD_P6x8Str(40,flag,"*");" r+ @( R3 ] V5 ]% r7 S$ v0 ?" g
- " e! }( v8 L% r' E- W, b3 U
- //添加按键输入0 g' z+ J! `& O% p
- key = keyRead();
4 c: s6 s2 L; W( P9 a1 s1 R - if(key == UP)//向上键
# t. U! g" w W6 `$ R - {
, B$ L4 @' x% V! b9 ~# _ - LCD_P6x8Str(40,flag," ");( X8 D2 {! R) z
- flag = flag == 3 ? 6 : flag-1;; ^$ y$ @' \4 d5 z C2 |2 @! Q
- }
1 V+ R$ A' |3 B! [6 A. j - else if(key == DOWN)//向下键4 U' q. x( g+ Y* h* Q3 X
- {
# P2 j& s6 |1 S3 p8 m6 P6 @ - LCD_P6x8Str(40,flag," ");
7 a! y& q; k& {6 _$ \, u& } - flag = flag == 6 ? 3 : flag+1;7 ]! x# ^3 K/ s" B a
- }
7 E8 b2 G' e; M" q1 k - else if(key == OK)//按了OK键$ i3 W* i. j( U1 W3 z" q
- {
0 P; L. E5 q" N! `( V - //判断星星在哪一行,控制哪个器件
3 v( u' f. x: } - switch(flag)& |% L, b# T! a! a
- {
) ^/ i4 h% S- ?7 ` - case 3://LED1: R- v5 l. a. d& p: z4 @: a
- ledSwitch(1,status[0]= !status[0]);1 C! R' r! _5 @
- break;
% C: R1 V- v% g$ t - case 4://LED2( H' l) w$ c" X: B6 r9 X/ o6 n
- ledSwitch(2,status[1]= !status[1]);
1 K) B9 b0 N, U7 Q. m* k - break;& @8 y% i+ O9 K. n' a" w, O5 k; O) N; c
- case 5://FAN8 z+ H |3 `0 }" t; |2 S
- fanSwitch(status[2]= !status[2]);7 ~, H; p. x0 b" N& I0 Q4 O
- break;
/ D/ ?6 G: {5 ~# R* V- u5 Y/ ~; \1 z - case 6://BUZZER
+ O+ c* ~/ V. ?+ D! C - buzzerSwitch(status[3]= !status[3]);: P# B& x4 F& U9 g5 _
- break;
1 S4 p0 |' V8 g- E+ J3 R1 g2 J# H - }* w" r3 \% W' [$ k3 w5 x
- }* I, u, a7 U4 ^. q: q" D( n# U
- else if(key == MODE )//按了模式切换键
) Z( S1 a4 P. O5 e2 F9 S' F - {3 w9 F( v, D# C F! ?
- status[4] = !status[4];
- ]9 B. W; o* |; }; H6 a - }3 j! Q( X d* Q6 A
- 6 `5 ]0 i3 S) T5 {2 i! U
- //在第7行显示 开关状态
]: r1 a6 r$ L1 b2 `3 ^7 O - sprintf(buf,"L1:%d L2:%d F:%d B:%d M:%d",status[0],status[1],status[2],status[3],status[4]);
/ W! T9 T% a% t& _ - LCD_P6x8Str(0,7,(u8*)buf);//显示到屏幕上
( X+ W+ [0 p1 A" ~1 u* V -
) v' n) b! P( ^4 d - main_delay(200);" I. `9 T& T4 N" E1 ?
- }2 j1 V# w: G/ H$ r$ i( X
-
' R0 d. U/ n1 t0 Y/ c/ C - }
复制代码
/ u2 P; o% Z4 x% A; c {* @$ S; W& J% S
% G K7 f1 h) W6 L1 ~+ L |
早上好啊,好东西要分享出来给大家