• 【毕业设计】单片机家用燃气的可视化实时监控报警仪 - 物联网 嵌入式 stm32



    0 前言

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

    为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

    🚩 基于单片机的家用燃气的可视化实时监控报警仪

    🥇学长这里给一个题目综合评分(每项满分5分)

    • 难度系数:4分
    • 工作量:4分
    • 创新点:3分

    🧿 选题指导, 项目分享:

    https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md


    1 简介

    本项目设计主要功能是可以用于家用燃气的可视化实时监控的迷你报警器,传感器部分和米家等绝大多数网络上的家用燃气报警使用的一致,还支持便捷更换传感器。具备WIFI模块,支持AT命令的设置。

    2 主要器件

    • HK32F031K6U6主控芯片
    • SP485E芯片
    • ch340e芯片
    • MIC5219-3.3稳压芯片
    • WiFi模块

    3 实现效果

    在这里插入图片描述

    在这里插入图片描述

    4 设计原理

    4.1 硬件部分

    本项目涉及到的功能模块有:

    • USB转TTL通信
    • USB与单片机通信
    • USB与WIFI模块通信
    • 单片机驱动OLED液晶屏
    • 单片机驱动AHT20/21温湿度芯片
    • 单片机PWM驱动蜂鸣器
    • 单片机AD采集可燃传感器的电压值等功能。

    前面和USB相关的测试方法就是插电脑和正常使用的485转接线进行连线传输,尝试不同的波特率和传输速率进行收发通信,不丢包,稳定传输就是通过测试,否则要检查硬件电路上的问题,是否有虚焊和器件上的损坏。
    OLED和温湿度芯片采用IIC相关的驱动,单输出IIC可以不加上拉电阻能实现功能,但是交互式的,要获取数据的就必须加上上拉电阻才能收数正常。而且燃气传感器是催化燃烧方式的,本身会发热,且发热量还不小,故应该尽可能的把温湿度芯片和可燃传感器分的远点,不然温度和湿度测试的都不准确。每个功能模块通过软件编程实现功能后都要进行对比。屏幕驱动比较直观,看到什么就是什么了,温湿度需要进行一定的补偿。
    最后蜂鸣器和按键功能的增加,蜂鸣器是5020的封装,想要实现比较亮的声音就要分析和测试,不断调教,找到比较响亮的蜂鸣声。按键功能可以做很多的联动,这里把它做成了控制屏幕显示反转的功能。

    主要原理图
    在这里插入图片描述

    4.2 软件部分

    整体逻辑流程如下:
    在这里插入图片描述

    5 部分核心代码

    void HAL_Delay_us_init(uint8_t SYSCLK)
    {
    	fac_us=SYSCLK; 
    }
     
    void HAL_Delay_us(uint32_t nus)
    {
    	uint32_t ticks;
    	uint32_t told,tnow,tcnt=0;
    	uint32_t reload=SysTick->LOAD;
    	ticks=nus*fac_us; 
    	told=SysTick->VAL; 
    	while(1)
    	{
    		tnow=SysTick->VAL;
    		if(tnow!=told)
    		{
    				if(tnow<told)tcnt+=told-tnow;
    				else tcnt+=reload-tnow+told;
    				told=tnow;
    				if(tcnt>=ticks)break; 
    		}
    	};
    }
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    /*
    ****************************************************************************************************
    ** 函数名称: Get_analog_voltage(u8 ch)
    ** 完成时间:  2017.5.24
    ** 编 写 人:  DIX
    ** 入口参数: u8 ch
    ** 返 回 值: 电压值
    ** 功能说明: ADC信号转换为电压值mV
    ** 备注说明: 获得ADC模拟出的电压 12位精度 (0~3.3V之间的mV值)
    ****************************************************************************************************
    */
    uint16_t Get_analog_voltage(uint8_t AD)                  
    {
    	uint32_t sum=0;                                 //采样20次的累计和
    	uint8_t  count;	  
    	uint16_t A_AD_Value;                            //单通道AD的变量值
    	ADC_ChannelConfTypeDef sConfig;
    	hadc.Instance->CHSELR = 0;	
      if(AD==8)
    	{
    		sConfig.Channel = ADC_CHANNEL_8;	
    	}	
    	else
    	{
    		sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    	}	
    	sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    	sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
    	HAL_ADC_ConfigChannel(&hadc, &sConfig);			
    	A_AD_Value=0;                                   //AD值清0
    	for(count=0;count<50;count++)                   //重复采样50次
    	{
    		HAL_ADCEx_Calibration_Start(&hadc);           //校准ADC
    		HAL_ADC_Start(&hadc);                         //开启ADC
    		HAL_ADC_PollForConversion(&hadc, 10);		      //等待转换过程
    		sum += HAL_ADC_GetValue(&hadc);               //获得50采样的累计和
    	}
    	A_AD_Value=sum/50;                              //AD采样50次后取平均值
    	A_AD_Value=(uint16_t)(A_AD_Value*3300/4096);    //扩大了1000倍整数为1mV值
    	
    	sum=0;                                          //清0总值
    	return A_AD_Value;                              //返回值
    }
    
    int8_t Temper_Judgment(void)
    {
    	int8_t  temper;
    	uint16_t adc_value=0;
    	adc_value = Get_analog_voltage(0);
      temper = (int8_t)((adc_value-449)/1.61);
    	return temper;                                   //返回值
    }
    //u16进制转换为字符串
    void u16tostr(u16 dat) 
    {
    	u8 temp[4];
    	u8 i=0,j=0,k=0;
    	while(dat)
    	{
    		temp[i]=(dat%10+0x30);
    		i++;
    		dat/=10;
    	}
    	j=i;
    	k=j;
    //	for(i=0;i
    //	{
    //		str1[i] = temp[j-i-1];
    //	}
    	for(i=0;i<4;i++)
    	{
    		if(4-k>i)
    			str1[i] =' ';
    		else 
    		{	
    		  //j=j-1;
    		  str1[i] = temp[--j];
    		}
    	}	
    	if(!i) 
    	{str1[i++]='0';}
    	//return str1;
    }
    
    
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    	u8 x=1;
    //	u32 CT_data[2]={0};
    //  volatile float  hum=0,tem=0;   
      /* USER CODE END 1 */
      
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    	HAL_Delay_us_init(24);   //系统24MHz时钟
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_DMA_Init();
      MX_ADC_Init();
      MX_USART2_UART_Init();
      MX_TIM3_Init();
      MX_TIM1_Init();
      MX_TIM2_Init();
      MX_TIM6_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
    	HAL_TIM_Base_Start_IT(&htim2);                           //开启定时器2
    	HAL_TIM_Base_Start_IT(&htim3);                           //开启定时器3
    	HAL_TIM_Base_Start_IT(&htim1);                           //开启定时器6
      OLED_Init();
    	OLED_Clear(); 
    	OLED_DisplayTurn(1);
    	//AHT20.alive=!AHT20_Init();	                             //AHT20温湿度传感器初始化
    	temphum_init();                                          //ATH20初始化
    	/*打开串口1空闲中断*/
      //__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);           //使能串口2中断
    	/*打开串口1接收DMA中断*/
      //HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);   //串口接收DMA通道	
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    		if(btimer)                                  //1s中断
    		{
    			btimer = 0;bcont++;
    //			Now_U = Get_analog_voltage(8);            //采用内部ADC采样
    			if(bcont==1)
    			{			
    				OLED_Clear();                             //清屏
    				//HAL_Delay(1000);                          //延时1秒
    				OLED_DrawBMP(0,0,64,6,BMP5);              //图片显示LOGO
    			}
    			if(bcont==5)
    			{			
    				OLED_Clear();                             //清屏
    				OLED_ShowCHinese(4,0,11);                 //第
    				OLED_ShowCHinese(24,0,12);                //六
    				OLED_ShowCHinese(44,0,13);                //届
    				OLED_ShowCHinese(4,2,14);                 //立
    				OLED_ShowCHinese(24,2,15);                //创
    				OLED_ShowCHinese(44,2,16);                //杯	
    				OLED_ShowCHinese(0,4,3);                  //燃
    				OLED_ShowCHinese(16,4,17);                //气
    				OLED_ShowCHinese(32,4,19);                //监	
    				OLED_ShowCHinese(48,4,20);                //测
    				//OLED_ShowString(8,4,"Ex",16);  
    				//OLED_ShowString(0,4," O L E D",16);  
    				//OLED_ShowString(0,4," 29.1",16);           //数据
    				//OLED_ShowCHinese(44,4,21);                 //℃
    			}
    			if(bcont==9)
    			{	
    				OLED_Clear();                             //清屏
    				//OLED_ShowString(0,0,"12.6",16);           //数据
    				//OLED_ShowString(32,0,"%LEL",16);          //可燃单位
    				OLED_ShowCHinese(0,0,22);                 //温
    				OLED_ShowCHinese(16,0,23);                //湿
    				OLED_ShowCHinese(32,0,24);                //度	
    
    				OLED_ShowString(0,2," 26.2",16);          //数据
    				OLED_ShowCHinese(44,2,21);                //℃
    				OLED_ShowString(0,4,"50.7",16);           //数据
    				OLED_ShowString(40,4,"%RH",16);           //湿度单位
    			}
    			if(bcont>=19)
    			{	
    				Now_U = Get_analog_voltage(8);            //采用内部ADC采样
    				Temper=Temper_Judgment();                 //温度换算函数
    //				/*--------AHT20读取数据---------*/
    //				if(AHT20.alive)// 如果AHT20传感器存在,则读取温湿度数据
    //				{
    //					//读取AHT20的 20Bit原始数据
    //					AHT20.flag = AHT20_ReadHT(AHT20.HT);
    //					//实际标准单位转换
    // 					StandardUnitCon(&AHT20);
    //				}
    				if(bcont==19)
    				{	
    					OLED_Clear();                           //清屏
    				}
    				if(Now_U>=900 && Now_U<2000)
    				{	
    					OLED_ShowCHinese(32,4,7);               //警	
    					OLED_ShowCHinese(48,4,8);               //戒
    				}
            else if(Now_U>=2000)	
    				{	
    					OLED_ShowCHinese(32,4,9);               //危
    					OLED_ShowCHinese(48,4,10);              //险
    				}		
    				else
    				{	
    					OLED_ShowCHinese(32,4,5);               //安
    					OLED_ShowCHinese(48,4,6);               //全
    				}			
    				u16tostr(Now_U);
    				OLED_ShowString(0,0,"U:",16);             //电压
    				OLED_ShowString(16,0,str1,16);            //数据
    				OLED_ShowString(48,0,"mV",16);            //电压单位
    			  memset(str1,0,4);
    				OLED_ShowNum(4,2,Calculate_Concentration(Now_U),3,16);  //显示浓度
    				if(Calculate_Concentration(Now_U)>=10)
    					HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
    				else
    					HAL_TIM_PWM_Stop(&htim3,TIM_CHANNEL_4);
    			  memset(str1,0,4);
    				OLED_ShowString(32,2,"%LEL",16);          //可燃单位
    				OLED_ShowString(0,4,"Ex",16);             //可燃标致
    			}
    			if(bcont>=50)
    			{	
    //				AHT20_Read_CTdata(CT_data);            //不经过CRC校验,直接读取AHT20的温度和湿度数据 
    //        hum = CT_data[0]*100*10/1024/1024;     //计算得到湿度值(放大了10倍)
    //        tem = CT_data[1]*200*10/1024/1024-500; //计算得到温度值(放大了10倍)
    //				HAL_Delay(2000);                       //延时1秒
    				bcont=0;
    			}				
    		}
    		if(!HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin))
    		{		//读取KEY按键引脚,低电平表示按下
    			//HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);		//LED引脚电平取反
    			HAL_Delay(10);								                  //延时
    			OLED_Clear(); 
    			x=!x;                                           //变量取反
    			OLED_DisplayTurn(x);
    			while(!HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin))//等待松手,防松手抖动
    			HAL_Delay(10);								                  //延时
    		}
    		
    	}
      /* USER CODE END 3 */
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290

    6 最后

  • 相关阅读:
    设计模式七大原则
    yolov7训练
    李超线段树
    达梦:定时计划实现生产环境备份数据库策略
    spark3使用hive zstd压缩格式总结
    java版Spring Cloud+Spring Boot+Mybatis实现工程管理系统源码
    联合概率和条件概率的区别和联系
    08.K8S高可用方案
    LoadRunner录制脚本+编写脚本
    第22章 软件安装 RPM/ YUM
  • 原文地址:https://blog.csdn.net/m0_71572576/article/details/126657082