目录
1. 整体设计
2. 液晶显示
3. Ds18b20温度传感器
4. Mq2烟雾传感器
5. 火焰传感器传感器
6. 蜂鸣器驱动控制
7. 按键
8. Gsm短信模块
9. Esp8266wifi模块
10、源代码
11、资料内容
资料下载地址:STM32单片机wifi云平台+温度+烟雾+火焰+短信+蜂鸣器 源程序原理图
1. 整体设计
设计由stm32f103c8t6单片机为控制核心
2. 液晶显示
单片机通过iic接口(pa6、pa7)与oled12864的液晶显示屏(scl、sda)连接,驱动液晶数据和阈值。
3. Ds18b20温度传感器
Ds18b20温度传感器是单总线接口,把数据端接到单片机的pb9管脚,通过传感器协议读取温度值。
4. Mq2烟雾传感器
Mq2传感器输出模电压会随着烟雾浓度的增大而增大。单片机通过模拟量采集管脚PA0采集mq2传感器输出的电压值,然后单片机通过计算把0-vcc电压转化成0-100%烟雾浓度。
5. 火焰传感器传感器
火焰传感器是数字量do输出,当检测到有明火时输出低电平0,无明火时输出高电平1。单片机通过io口pa6读取火焰传感器状态。
6. 蜂鸣器驱动控制
如果蜂鸣器接电源3.3v和地,蜂鸣器有电就会发声。1k电阻是限流电阻。单片机通过控制pa7管脚输出高低电平,从而达到控制风扇转动的效果。单片机输出高电平1时,三极管导通,蜂鸣器接地,蜂鸣器响。输出低电平0时,三极管截至不导通,蜂鸣器没有接地,蜂鸣器不响。
7. 按键
单片机io口接按键,按键按下的接地。Io口读取到低电平0,按键松开时,由于单片机有内置上拉电阻,Io口读取到高电平1。其他两个按键原理一样。
8. Gsm短信模块
Sim900a gsm短信模块是通过串口通讯的,将单片机串口1发送端pa9接到gsm模块的接收端rxd,然后单片机通过at指令控制gsm模块发送短信。
9. Esp8266wifi模块
8266是串口控制得模块,单片机通过串口1(pa9和pa10)与wifi模块通讯,从而控制wifi模块工作。首先wifi模块上电自动连接热点,然后连接onenet云平台得ip地址,通过mqtt协议登录云平台设备,订阅app(订阅了才能接收到app下发得信息)。单片机会定时上传数据(以mcu得身份发布数据)到onenet云平台,在app订阅了mcu设备得前提下,云平台接收到单片机上传得数据后会自动转发到app显示。反之app下发数据过程也一样。
10、源代码
#include "stm32f10x.h" //头文件
#include "./usart/bsp_usart1.h"
#include "./OLED_I2C/OLED_I2C.h"
#include "./delay/delay.h"
#include "adc.h"
#include "string.h"
#include "bsp_ds18b20.h"
#include "./TIMER/timer.h"
#define Speaker PAout(7)//pa7接蜂鸣器
#define Key1 PBin(12)//按键
#define Key2 PBin(13)//按键
#define Key3 PBin(14)//按键
#define HY PAin(6)//火焰传感器
TIM_TimeBaseInitTypeDef TIM3_TimeBaseStructure;
TIM_OCInitTypeDef TIM3_OCInitStructure;
void DelayStm32(__IO u32 nCount)
{
for(; nCount != 0; nCount--);
}
u16 Time_1MS=0;
u16 TX_10MS=0;
u16 A0Value = 0; //烟雾值
u16 Ds18b20Value; //温度
u16 Cnt=0;
u8 AlarmT=35; //温度阈值
u8 AlarmM=60; //烟雾阈值
char dispBuff[10];
u8 FlagUpData = 0;
u8 FlagFS = 0; //风扇手动标志位
u8 FlagDelayA = 0; //继电器手动标志位
u8 StateDelayA = 0; //继电器状态
u8 StateFS = 0; //风扇状态
u8 Stm32[17];
u16 KeyCnt = 0;
u8 FlagSet=0; //按键设置标志位
u8 FlagAlarm=0; //告警标志位
u8 RxBuf1[32];
u8 RxBuf2[32];
u8 RxBuf3[32]; //串口3数据缓存
u8 pass[11];
/**********************MQTTdata***********************/
char MqttDataDL[37]=
{
0x10, 0x23, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0xC0,
0x00, 0x78, 0x00, 0x0A, 0x31, 0x30, 0x36, 0x35, 0x36, 0x30,
0x31, 0x35, 0x35, 0x39, 0x00, 0x06, 0x35, 0x38, 0x39, 0x35,
0x35, 0x34, 0x00, 0x03, 0x6D, 0x63, 0x75
};//mqtt登录数组
char MqttDataDY[10]=
{
0x82, 0x08, 0x00, 0x02, 0x00, 0x03, 'a', 'p', 'p', 0x00
};//mqtt订阅数组
char MqttDataFB[24]=
{
0x30, 0x16, 0x00, 0x03, 0x6D, 0x63, 0x75, 0x06, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};//mqtt发布数组
void SendASC1(u8 d) //串口1发送一个字节
{
USART_SendData(USART1, d);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void SendASC2(u8 d) //串口2发送一个字节
{
USART_SendData(USART2, d);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}
void SendASC3(u8 d)
{
USART_SendData(USART3, d);
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}
void DengLu(void) //mqtt登录函数
{
u8 k=0;
printf("AT+CIPSEND=37\r\n");
DelayS(1);
for(k=0; k<37; k++)
{
SendASC1(MqttDataDL[k]);
}
}
void DingYue(void) //mqtt订阅函数
{
u8 k=0;
printf("AT+CIPSEND=10\r\n");
DelayS(1);
for(k=0; k<10; k++)
{
SendASC1(MqttDataDY[k]);
}
}
void FaBu(void) //mqtt发布函数
{
u8 k=0;
printf("AT+CIPSEND=24\r\n");
DelayS(1);
for(k=0; k<24; k++)
{
SendASC1(MqttDataFB[k]);
}
}
/*************************************************/
void GPIO_Config(void) //io口配置
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA and GPIOA clock enable */ //pb8、pb12、pb13、pb14设置为输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8 |GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* GPIOA and GPIOA clock enable */ //pa6设置为输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* GPIOA and GPIOA clock enable */ //pa7.pa4配置为推免输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* GPIOA and GPIOA clock enable */ //pc13配置为推免输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,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(GPIOC, &GPIO_InitStructure);
}
void DispOled(void)//液晶显示函数
{
//显示温度和阈值
sprintf(dispBuff,"WenDu=%d%d.%dC %d%dC", Ds18b20Value %1000/100, Ds18b20Value%100/10, Ds18b20Value%10, AlarmT%100/10, AlarmT%10);
OLED_ShowStr(0,0,dispBuff,2);
//显示烟雾和阈值
sprintf(dispBuff,"YanWu = %0.2d%% %0.2d%%",A0Value,AlarmM);
OLED_ShowStr(0,2,dispBuff,2);
//显示接收短信的号
sprintf(dispBuff,"%d%d%d%d%d%d%d%d%d%d%d",pass[10],pass[9],pass[8],pass[7],pass[6],pass[5],pass[4],pass[3],pass[2],pass[1],pass[0]);
OLED_ShowStr(0,6,dispBuff,2);
}
void SendDx(void) //发送短信函数
{
Uart3_printf("AT+CSCS=\"GSM\"\r\n");
DelayS(1);
Uart3_printf("AT+CMGF=1\r\n");
DelayS(1);
/*******************************************************/
//printf("AT+CMGS=\"18xxxxxxxx\"\r\n");
Uart3_printf("AT+CMGS=\""); //按设置的号码发送短信
SendASC3(pass[10]+0x30);
SendASC3(pass[9]+0x30);
SendASC3(pass[8]+0x30);
SendASC3(pass[7]+0x30);
SendASC3(pass[6]+0x30);
SendASC3(pass[5]+0x30);
SendASC3(pass[4]+0x30);
SendASC3(pass[3]+0x30);
SendASC3(pass[2]+0x30);
SendASC3(pass[1]+0x30);
SendASC3(pass[0]+0x30);
Uart3_printf("\"\r\n");
/*******************************************************/
DelayS(1);
Uart3_printf("Have a Fire!!!"); //发送短信的内容
DelayS(1);
SendASC3(0x1A); //启动发送短信
DelayS(1);
}
int main(void) //主函数
{
USART1_Config(); //串口初始化
GPIO_Config();//io口初始化
Adc_Init();//ad初始化
DelayInit(); //定时函数初始化
Speaker = 0;//关闭输出设备
I2C_Configuration();//iic初始化
OLED_Init();//液晶初始化
OLED_Fill(0xFF);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
printf("AT\r\n");
DelayS(1);
printf("AT\r\n");
DelayS(1);
printf("AT\r\n");
DelayS(1);
printf("AT+CWMODE=3\r\n"); //8266设置为模式3
DelayS(1);
printf("AT+CWJAP=\"win\",\"123123123\"\r\n"); //连接热点
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
while(DS18B20_Init()); //温度初始化
DelayS(1);
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10); //上电连续读取几次温度值使其稳定
DelayStm32(0xFFFFF);
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10);
DelayStm32(0xFFFFF);
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10);
DelayStm32(0xFFFFF);
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10);
DelayStm32(0xFFFFF);
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10);
DelayStm32(0xFFFFF);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
/*******************************************************/
printf("AT+CIPSTART=\"TCP\",\"183.230.x.x\",6002\r\n"); //连接云平台ip和端口号
/*******************************************************/
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DelayS(1);
DengLu(); //调用mqtt登录函数
DelayS(1);
DelayS(1);
DelayS(1);
DingYue(); //调用mqtt订阅函数
DelayStm32(0xFFFFF);
OLED_Fill(0x00);
DelayStm32(0xFFFFF);
TIM4_Int_Init(9,7199); //定时器初始化
while(1)
{
Ds18b20Value = (u16)(DS18B20_GetTemp_SkipRom ( )*10);//读取稳定
A0Value = (Get_Adc_Average(0,20)*100/4096);//读取烟雾
DispOled(); //调用显示函数
MqttDataFB[10] = Ds18b20Value/100; //把要上传得数据填进mqtt发布数据
MqttDataFB[11] = Ds18b20Value%100/10;
MqttDataFB[12] = Ds18b20Value%10;
MqttDataFB[13] = A0Value;
MqttDataFB[14] = 0;
MqttDataFB[15] = 0;
MqttDataFB[16] = FlagAlarm;
if(FlagUpData==1) //上传数据时间到,上传数据
{
FlagUpData = 0;
FaBu(); //发布数据
}
if( (Ds18b20Value>(AlarmT*10))||(A0Value>AlarmM)||(HY) ) //如果温度或者烟雾大于阈值或者有火焰
{
Speaker = 1; //蜂鸣器响
if(FlagAlarm==0) //每个告警值发送一次短信
{
SendDx(); //调用发送短信函数
}
FlagAlarm = 1;
}
else
{
FlagAlarm = 0;
Speaker = 0;
}
if(!Key1) //按键1
{
while(!Key1);
pass[0]++;
if(pass[0]>=10) pass[0]=0;
}
if(!Key2)//按键2
{
while(!Key2);
pass[10] = pass[9];
pass[9] = pass[8];
pass[8] = pass[7];
pass[7] = pass[6];
pass[6] = pass[5];
pass[5] = pass[4];
pass[4] = pass[3];
pass[3] = pass[2];
pass[2] = pass[1];
pass[1] = pass[0];
pass[0] = 0;
}
/**************************************************************************************/
/**************************************************************************************/
}
}
void TIM4_IRQHandler(void) //定时中断每1ms中断一次
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)//?????
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //??TIM4??????
TX_10MS++;
if(TX_10MS>=5000)
{
TX_10MS = 0;
FlagUpData = 1;
}
}
}
void USART1_IRQHandler(void)
{
uint8_t ucTemp;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData(USART1);
RxBuf1[0] = RxBuf1[1];
RxBuf1[1] = RxBuf1[2];
RxBuf1[2] = RxBuf1[3];
RxBuf1[3] = ucTemp;
if( (RxBuf1[0]=='F')&&(RxBuf1[1]=='t') ) //Ftxx 设置温度阈值
{
AlarmT = (RxBuf1[2]-0x30)*10 + (RxBuf1[3]-0x30);
}
else if( (RxBuf1[0]=='F')&&(RxBuf1[1]=='m') ) //Fmxx 设置烟雾阈值
{
AlarmM = (RxBuf1[2]-0x30)*10 + (RxBuf1[3]-0x30);
}
}
}
void USART2_IRQHandler(void)
{
uint8_t ucTemp2;
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
{
ucTemp2= USART_ReceiveData(USART2);
RxBuf2[0] = RxBuf2[1];
RxBuf2[1] = RxBuf2[2];
RxBuf2[2] = RxBuf2[3];
RxBuf2[3] = ucTemp2;
if( (RxBuf2[0]=='F')&&(RxBuf2[1]=='T') )
{
}
}
}
void USART3_IRQHandler(void)
{
uint8_t ucTemp3;
if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)
{
ucTemp3= USART_ReceiveData(USART3);
RxBuf3[0] = RxBuf3[1];
RxBuf3[1] = RxBuf3[2];
RxBuf3[2] = RxBuf3[3];
RxBuf3[3] = ucTemp3;
}
}