扫码加入

  • 方案介绍
  • 相关推荐
申请入驻 产业图谱

基于STM322单片机的煤气检测蓝牙手机APP报警设计

2小时前
174
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

基于STM322单片机的煤气检测蓝牙手机APP报警设计

  • 1、项目简介
    • 1.1 系统功能
    • 1.2 演示视频
  • 2、部分电路设计
  • 3、单片机代码展示
    • 3.1 系统初始化
    • 3.2 oled显示程序
    • 3.3 蓝牙通讯程序

1、项目简介

1.1 系统功能

  • 功能介绍:
    • 1,采集燃气信息并通过oled显示数据
    • 2、使用蓝牙无线模块与手机APP通信
    • 3、当燃气值超过报警阈值,蜂鸣器进行报警,并将报警信息与燃气值实时发送到手机app

通过本篇内容,可编写开题报告、任务书、毕业论文等。

1.2 演示视频

  • 演示视频:https://www.bilibili.com/video/BV1i94y1J7TQ

2、部分电路设计

2.1 STM32单片机核心板电路设计

  • ‌基于 ARM Cortex-M3内核的STM32F1系列单片机属于主流STM32单片机,其中增强型STM32F103子系列单片机的CPU 主频高达72MHz,片内Flash容量高达1MB,芯片引脚数量多达144个,有 QFN、LQFP、CSP、BGA 等多种芯片封装形式,并具有多种片内外设、USB接口和CAN 接口。根据STM32F103单片机片内Flash容量的不同,ST 公司将其分为小容量(16-32KB)、中等容量(64-128KB)、大容量(256KB-1MB)3种。
  • 电源电路:为单片机提供稳定的工作电压,通常采用3.3V电源供电。电源电路的设计要保证单片机在不同工作条件下都能获得稳定的电压输出,以确保单片机的正常工作。
  • 晶振电路:提供单片机工作所需的时钟信号。晶振电路通过晶振和电容组成,为单片机提供稳定的工作脉冲,确保单片机的定时和同步需求。
  • 复位电路:实现单片机的复位功能,类似于电脑的重启。复位电路通过电容和电阻的配合,实现单片机在上电启动时的自动复位,以及通过手动按键实现复位功能,保证单片机在程序跑飞或异常情况下能够重新开始执行程序。

STM32单片机是一种功能强大、易于使用、灵活且可靠的32位微控制器,基于ARM Cortex™-M内核。其主要功能特点包括:

  • 高性能和低功耗‌:STM32系列单片机提供多种内核选择,如Cortex-M0、Cortex-M3、Cortex-M4等,满足不同应用场景对性能的需求,同时保持低功耗特性。‌
  • 多种通信和外设接口‌:STM32单片机具备广泛的通信和外设接口,如I2CSPI、USART、USB等,便于开发者实现各种复杂功能。‌
  • 易于开发和调试‌:STM32单片机提供了丰富的软件和硬件工具,如HAL库、CubeMX等,帮助开发者快速创建和调试嵌入式系统
  • 高集成度和设计灵活性‌:STM32系列单片机全系列产品共用大部分引脚、软件和外设,优异的兼容性为开发人员带来最大的设计灵活性

单片机最小系统原理图如下图所示:

实物图:

2.2 MQ-5 煤气 天然气采集电路设计

  • MQ-5气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。当传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大。MQ-5气体传感器对丁烷、丙烷、甲烷的灵敏度高,对甲烷和丙烷可较好的兼顾。这种传感器可检测多种可燃性气体,特别是天然气,是一款适合多种应用的低成本传感器。

其具体电路原理图如下图所示:

实物图如下:

2.3 ESP8266 WIFI无线通信电路设计

  • OLED的显存分布情况。我们可以理解为:水平方向分布了128个像素点,垂直方向分布了64个像素点。而驱动芯片在点亮像素点的时候,是以8个像素点为单位的。官方的例程推荐的是垂直扫描的方式,也就是先画垂直方向的8个像素点,所以我们在画点的时候Y的取值为0-7,X的取值为0-127。
  • 页是芯片设计者为了方便将同一列的8个点阵编成一组,用一个8bit数表示,这样的8行128个数被称为1页。

产品参数

  • 工作电压:3.3V / 5V(IO高电平电压和供电电压需相同)
  • 通信接口: I2C
  • 屏幕类型:OLED
  • 分辨率:128 × 64 Pixels
  • 外形尺寸:26.0mm × 26.0mm
  • 显示尺寸:21.74mm × 11.18mm
  • 显示颜色:蓝色 / 白色 / 黄蓝双色块(顶部1/4为黄色)
  • 工作温度:-20°C ~ 70°C
  • 存储温度:-30°C ~ 80°C
  • 视角:> 160°

其具体电路原理图如下图所示:

实物图如下:

2.4 HC05蓝牙通信电路设计

  • STM32单片机与HC-05蓝牙模块通信电路设计涉及电源管理、串口连接和状态指示等部分。
  • HC-05蓝牙模块的供电电压通常为3.3V至5V,但其逻辑电平为3.3V,因此在设计中中需要注意电平匹配问题。
  • 电源部分,HC-05的VCC引脚连接到稳压的5V电源,GND引脚连接到地,同时建议在VCC和GND之间加一个0.1μF去耦合电容,用于抑制和抑制电源噪声。
  • 通信部分,STM32单片机的USART引脚与HC-05的TXD和RXD引脚相连,HC-05的TXD可以直接连接到STM32的RX 引脚,因为 3.3V 的输出逻辑电平可以被 STM32 正确识别;而 STM32 的 TX引脚需要通过一个分压电路或电平转换模块降低到3.3V,以保护 HC-05 的 RXD 引脚未被 5V 信号损坏
  • 在STM已32程序设计中,需要将USART配置为异步通信模式,设置波特率与 HC-05 默认波特率一致(如 9600bps),通过 UART 接口实现与蓝牙模块的数据通信。在调试时,可以通过串口助手或者蓝牙调试工具对 HC -05 发送数据,并通过STM32解析接收数据,实现与手机或其他蓝牙设备的数据交互功能。

其具体电路原理图如下图所示:

实物图如下:

3、单片机代码展示

3.1 系统初始化

void HardWare_Init(void)
{
	//STM32内部初始化
	Delay_Init(72);        //滴答时钟初始化
	NVIC_Config();         //中断配置配置初始化
	Beep_Init();           //蜂鸣器初始化
	USART1_Init(115200);   //串口初始化
	Bluetooth_Init(9600); //蓝牙串口初始化
	
	Adc_Init();   //adc初始化
	TIM3_Init(4999,7199);//定时器初始化,定时器中断时间为500ms  	计数到 5000 为 500ms
	
	//OLED设备初始化
	OLED_Init();
	OLED_Clear();
	
	OLED_ShowString(0,0,(u8 *)"MQ:       ",16);      //打印温度
	OLED_ShowString(0,2,(u8 *)"MQT:",16);      //打印湿度
	
	Delay_ms(100);         //等待初始化完成
	
	
	BUZZER_ON
	Delay_ms(500);
	BUZZER_OFF
}

3.2 oled显示程序

void Write_IIC_Command(unsigned char IIC_Command)
{
	IIC_Start();
	IIC_Send_Byte(0x78);            //Slave address,SA0=0
	IIC_Wait_Ack();	
	IIC_Send_Byte(0x00);			//write command
	IIC_Wait_Ack();	
	IIC_Send_Byte(IIC_Command); 
	IIC_Wait_Ack();	
	IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
	IIC_Start();
	IIC_Send_Byte(0x78);			//D/C#=0; R/W#=0
	IIC_Wait_Ack();	
	IIC_Send_Byte(0x40);			//write data
	IIC_Wait_Ack();	
	IIC_Send_Byte(IIC_Data);
	IIC_Wait_Ack();	
	IIC_Stop();
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
	if(cmd)
			{

   Write_IIC_Data(dat);
   
		}
	else {
   Write_IIC_Command(dat);
		
	}


}


/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		OLED_WR_Byte(0xb0+m,0);		//page0-page1
		OLED_WR_Byte(0x00,0);		//low column start address
		OLED_WR_Byte(0x10,0);		//high column start address
		for(n=0;n<128;n++)
			{
				OLED_WR_Byte(fill_Data,1);
			}
	}
}


/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{
	unsigned int m;
	for(;Del_50ms>0;Del_50ms--)
		for(m=6245;m>0;m--);
}

void Delay_1ms(unsigned int Del_1ms)
{
	unsigned char j;
	while(Del_1ms--)
	{	
		for(j=0;j<123;j++);
	}
}

//坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 
	OLED_WR_Byte(0xb0+y,OLED_CMD);
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte((x&0x0f),OLED_CMD); 
}   	  
//开启OLED显示    
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}		   			 
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
void OLED_Clear(void)  
{  
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
	} //更新显示
}
void OLED_On(void)  
{  
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); 
	} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{      	
	unsigned char c=0,i=0;	
		c=chr-' ';//得到偏移后的值			
		if(x>Max_Column-1){x=0;y=y+2;}
		if(Char_Size ==16)
			{
			OLED_Set_Pos(x,y);	
			for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
			OLED_Set_Pos(x,y+1);
			for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
			}
			else {	
				OLED_Set_Pos(x,y);
				for(i=0;i<6;i++)
				OLED_WR_Byte(F6x8[c][i],OLED_DATA);
				
			}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{
	u32 result=1;	 
	while(n--)result*=m;    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{         	
	u8 t,temp;
	u8 enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
} 
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
	unsigned char j=0;
	while (chr[j]!='�')
	{		OLED_ShowChar(x,y,chr[j],Char_Size);
			x+=8;
		if(x>120){x=0;y+=2;}
			j++;
	}
}

3.3 蓝牙通讯程序

void Bluetooth_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure; 
	
	/* config USART2 clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	/* USART2 GPIO config */
	/* Configure USART2 Tx (PA.02) as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);    
	/* Configure USART2 Rx (PA.03) as input floating */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	/* USART2 mode config */
	USART_InitStructure.USART_BaudRate = bound;
	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(USART2, &USART_InitStructure);
	
	
	/* Configure the NVIC Preemption Priority Bits */  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
	/* Enable the USARTy Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	/* 使能串口1接收中断 */
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	
	USART_Cmd(USART2, ENABLE);
}


//蓝牙发送到手机
void USART2_Send(unsigned char *tx_buf, int len)
{
		USART_ClearFlag(USART2, USART_FLAG_TC);
		USART_ClearITPendingBit(USART2, USART_FLAG_TXE);
	while(len--)
	{
		USART_SendData(USART2, *tx_buf);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TC) != 1);
		USART_ClearFlag(USART2, USART_FLAG_TC);
		USART_ClearITPendingBit(USART2, USART_FLAG_TXE);
		tx_buf++;
	}
	
}

相关推荐