基于STM32的智能家居控制系统 - 嵌入式开发期末项目
项目概述
本项目是一个基于STM32微控制器的智能家居控制系统,集成了温湿度监测、灯光控制、OLED显示和蓝牙通信等功能。通过手机APP可以远程监控家居环境并控制家电设备,实现了智能化的家居管理。
硬件组成
主控芯片:STM32F103C8T6
温湿度传感器:DHT11
显示模块:0.96寸OLED显示屏
通信模块:HC-05蓝牙模块
执行器件:继电器模块
其他:LED指示灯、按键、蜂鸣器
系统架构
text
手机APP <--> 蓝牙模块 <--> STM32主控制器 <--> 各传感器和执行器|+--> DHT11温湿度传感器+--> OLED显示屏+--> 继电器(灯光控制)+--> LED状态指示
核心代码实现
1. 主程序框架
c
#include "stm32f10x.h" #include "dht11.h" #include "oled.h" #include "bluetooth.h" #include "relay.h" #include "led.h" #include "delay.h"// 全局变量定义 uint8_t Temperature, Humidity; uint8_t Light_Status = 0; // 0:关, 1:开 uint8_t BT_Data[20];int main(void) {// 系统初始化System_Init();// 外设初始化DHT11_Init();OLED_Init();Bluetooth_Init();Relay_Init();LED_Init();// 开机显示OLED_ShowString(0, 0, "Smart Home System");OLED_ShowString(0, 2, "Initializing...");Delay_ms(1000);OLED_Clear();while(1){// 读取温湿度数据if(DHT11_Read_Data(&Temperature, &Humidity) == SUCCESS){Display_Sensor_Data();}// 处理蓝牙数据if(Bluetooth_Receive_Data(BT_Data)){Process_BT_Command(BT_Data);}// 状态监测与更新System_Status_Update();Delay_ms(500);} }
2. 温湿度传感器驱动
c
// dht11.h #ifndef __DHT11_H #define __DHT11_H#include "stm32f10x.h"#define DHT11_GPIO_PORT GPIOB #define DHT11_GPIO_PIN GPIO_Pin_12#define DHT11_OUT_H GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN) #define DHT11_OUT_L GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN) #define DHT11_IN GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)void DHT11_Init(void); uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi); uint8_t DHT11_Read_Byte(void);#endif
c
// dht11.c #include "dht11.h" #include "delay.h"void DHT11_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);DHT11_OUT_H; }uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi) {uint8_t buf[5];uint8_t i;DHT11_OUT_L;Delay_ms(18);DHT11_OUT_H;Delay_us(30);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);if(DHT11_IN == 0){while(DHT11_IN == 0);while(DHT11_IN == 1);for(i=0; i<5; i++){buf[i] = DHT11_Read_Byte();}while(DHT11_IN == 0);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);DHT11_OUT_H;if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4]){*humi = buf[0];*temp = buf[2];return SUCCESS;}}return ERROR; }
3. OLED显示驱动
c
// oled.c - 显示传感器数据函数 void Display_Sensor_Data(void) {char display_buf[20];OLED_Clear();OLED_ShowString(0, 0, "Smart Home System");OLED_ShowString(0, 1, "----------------");// 显示温度sprintf(display_buf, "Temp: %d C", Temperature);OLED_ShowString(0, 2, display_buf);// 显示湿度sprintf(display_buf, "Humi: %d %%", Humidity);OLED_ShowString(0, 3, display_buf);// 显示灯光状态sprintf(display_buf, "Light: %s", Light_Status ? "ON " : "OFF");OLED_ShowString(0, 4, display_buf);// 显示连接状态OLED_ShowString(0, 5, "BT: Connected"); }
4. 蓝牙通信处理
c
// bluetooth.c void Bluetooth_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 使能时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// 配置TX引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置RX引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置USARTUSART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE); }uint8_t Bluetooth_Receive_Data(uint8_t *data) {uint8_t i = 0;if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET){while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET && i < 20){data[i] = USART_ReceiveData(USART1);i++;}return 1;}return 0; }void Process_BT_Command(uint8_t *cmd) {if(strcmp((char*)cmd, "LIGHT_ON") == 0){Light_Status = 1;Relay_Control(1);Bluetooth_Send_String("Light turned ON");}else if(strcmp((char*)cmd, "LIGHT_OFF") == 0){Light_Status = 0;Relay_Control(0);Bluetooth_Send_String("Light turned OFF");}else if(strcmp((char*)cmd, "GET_DATA") == 0){Send_Sensor_Data();} }
5. 继电器控制
c
// relay.c void Relay_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;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_13); // 默认关闭 }void Relay_Control(uint8_t status) {if(status){GPIO_SetBits(GPIOB, GPIO_Pin_13); // 打开继电器}else{GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 关闭继电器} }
Android手机APP代码
主要界面布局
xml
<!-- activity_main.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="智能家居控制系统"android:textSize="24sp"android:gravity="center"android:layout_marginBottom="20dp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_connect"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="连接设备"/><Buttonandroid:id="@+id/btn_disconnect"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="断开连接"/></LinearLayout><TextViewandroid:id="@+id/tv_temp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="温度: --°C"android:textSize="18sp"android:layout_marginTop="10dp"/><TextViewandroid:id="@+id/tv_humi"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="湿度: --%"android:textSize="18sp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginTop="20dp"><Buttonandroid:id="@+id/btn_light_on"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="开灯"android:background="@color/green"/><Buttonandroid:id="@+id/btn_light_off"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="关灯"android:background="@color/red"/></LinearLayout><Buttonandroid:id="@+id/btn_refresh"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="刷新数据"android:layout_marginTop="10dp"/><TextViewandroid:id="@+id/tv_status"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="状态: 未连接"android:layout_marginTop="20dp"/></LinearLayout>
Android主Activity
java
// MainActivity.java public class MainActivity extends AppCompatActivity {private BluetoothAdapter bluetoothAdapter;private BluetoothSocket bluetoothSocket;private ConnectedThread connectedThread;private TextView tvTemp, tvHumi, tvStatus;private Button btnConnect, btnDisconnect, btnLightOn, btnLightOff, btnRefresh;private static final String DEVICE_ADDRESS = "00:18:E4:34:XX:XX"; // 蓝牙模块地址private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();setupBluetooth();}private void initViews() {tvTemp = findViewById(R.id.tv_temp);tvHumi = findViewById(R.id.tv_humi);tvStatus = findViewById(R.id.tv_status);btnConnect = findViewById(R.id.btn_connect);btnDisconnect = findViewById(R.id.btn_disconnect);btnLightOn = findViewById(R.id.btn_light_on);btnLightOff = findViewById(R.id.btn_light_off);btnRefresh = findViewById(R.id.btn_refresh);btnConnect.setOnClickListener(v -> connectToDevice());btnDisconnect.setOnClickListener(v -> disconnectDevice());btnLightOn.setOnClickListener(v -> sendCommand("LIGHT_ON"));btnLightOff.setOnClickListener(v -> sendCommand("LIGHT_OFF"));btnRefresh.setOnClickListener(v -> sendCommand("GET_DATA"));}private void setupBluetooth() {bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (bluetoothAdapter == null) {Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();finish();}if (!bluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, 1);}}private void connectToDevice() {new ConnectThread().start();}private void disconnectDevice() {if (connectedThread != null) {connectedThread.cancel();connectedThread = null;}updateStatus("已断开连接");}private void sendCommand(String command) {if (connectedThread != null) {connectedThread.write(command.getBytes());} else {Toast.makeText(this, "请先连接设备", Toast.LENGTH_SHORT).show();}}private void updateStatus(String status) {runOnUiThread(() -> tvStatus.setText("状态: " + status));}private void updateSensorData(String temp, String humi) {runOnUiThread(() -> {tvTemp.setText("温度: " + temp + "°C");tvHumi.setText("湿度: " + humi + "%");});}private class ConnectThread extends Thread {private final BluetoothDevice device;public ConnectThread() {BluetoothDevice tempDevice = bluetoothAdapter.getRemoteDevice(DEVICE_ADDRESS);device = tempDevice;try {bluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID);} catch (IOException e) {updateStatus("连接失败: " + e.getMessage());}}public void run() {bluetoothAdapter.cancelDiscovery();try {bluetoothSocket.connect();connectedThread = new ConnectedThread(bluetoothSocket);connectedThread.start();updateStatus("已连接到智能家居系统");} catch (IOException e) {updateStatus("连接失败: " + e.getMessage());try {bluetoothSocket.close();} catch (IOException closeException) {// 忽略关闭异常}}}}private class ConnectedThread extends Thread {private final BluetoothSocket mmSocket;private final InputStream mmInStream;private final OutputStream mmOutStream;private byte[] mmBuffer;public ConnectedThread(BluetoothSocket socket) {mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;try {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) {// 处理异常}mmInStream = tmpIn;mmOutStream = tmpOut;}public void run() {mmBuffer = new byte[1024];int numBytes;while (true) {try {numBytes = mmInStream.read(mmBuffer);String receivedData = new String(mmBuffer, 0, numBytes);processReceivedData(receivedData);} catch (IOException e) {updateStatus("连接断开");break;}}}public void write(byte[] bytes) {try {mmOutStream.write(bytes);} catch (IOException e) {updateStatus("发送失败: " + e.getMessage());}}public void cancel() {try {mmSocket.close();} catch (IOException e) {// 忽略关闭异常}}private void processReceivedData(String data) {if (data.contains("Temp:") && data.contains("Humi:")) {// 解析温湿度数据String[] parts = data.split(" ");if (parts.length >= 4) {updateSensorData(parts[1], parts[3]);}}}} }
项目特色与创新点
完整的系统集成:将传感器数据采集、执行器控制、数据显示和无线通信完美结合
低功耗设计:STM32的睡眠模式和定时唤醒机制
稳定通信:蓝牙通信的数据校验和重传机制
用户友好:直观的OLED显示和简单的手机APP操作
可扩展性:模块化设计便于添加新功能
遇到的问题及解决方案
问题1:DHT11数据读取不稳定
解决方案:调整时序延时,添加数据校验机制
问题2:蓝牙通信数据丢失
解决方案:实现数据帧格式和简单的通信协议
问题3:多任务处理冲突
解决方案:合理分配系统时钟和任务优先级
项目成果
通过本项目,我们成功实现了:
实时环境监测(温湿度)
远程设备控制(灯光)
本地数据展示(OLED)
无线通信功能(蓝牙)
手机APP控制
系统运行稳定,响应及时,达到了智能家居控制的基本要求。
未来改进方向
添加更多传感器(烟雾、光照等)
实现WiFi连接和云端数据存储
开发语音控制功能
增加能耗统计和智能场景模式
改进手机APP界面和用户体验
总结
本项目综合运用了嵌入式系统开发、传感器技术、无线通信和Android开发等多方面知识,成功构建了一个功能完整的智能家居控制系统。通过实践,我们加深了对STM32编程、外设驱动开发、通信协议设计等核心技术的理解,为后续更复杂的嵌入式系统开发打下了坚实基础。