一、功能介绍

项目名:家用空调外机振动监测与报警系统的设计
项目编号:mcu-1212
单片机类型:STM32F103C8T6
具体功能:
1、通过声音监测模块监测当前空调外机的声音是否大于最大值,监测到声音大于最大值进行声光报警提醒;
2、通过震动模块监测当前空调外机是否震动,监测到当前空调外机震动进行声光报警提醒;
3、通过OLED显示屏空调外机的声音和震动情况;
4、通过按键可以设置当前空调外机的声音最大子;
5、通过WiFi模块将监测的数据上传到云平台然后下发到手机端,异常手机弹窗震动提醒;

二、资料总览

实物资料

请添加图片描述

仿真资料

请添加图片描述

三、部分资料展示

1、实物展示

供电接口:TYPE-C
板子类型:PCB集成板,两层板(上下层覆铜接地)
器件类型:元器件基本上为插针式,个别芯片会使用贴片式。
在这里插入图片描述

2、仿真展示

仿真软件版本:proteus8.17
电路连线方式:网络标号连线方式
注意:部分实物元器件仿真中没有,仿真中会用其他工作原理相似的元件代替,这样可能导致实物程序和仿真程序不一样
在这里插入图片描述

3、原理图展示

软件版本:AD2013
电路连线方式:网络标号连线方式
注意:原理图只是画出了模块的引脚图,而并不是模块的内部结构图
在这里插入图片描述

4、PCB图展示

由原理图导出,两层板,上下覆铜接地。
在这里插入图片描述

5、系统框图

绘制软件:VISIO
在这里插入图片描述

6、软件设计流程

绘制软件:VISIO
在这里插入图片描述

7、部分程序展示

软件版本:keil5

/* USER CODE BEGIN Header */

/**********************************
**********************************/

/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#include "./DELAY/delay.h"
#include "./OLED/oled.h"
#include "./KEY/key.h"
#include "./ALIYUN/aliyun.h"
#include "./ESP8266/esp8266.h"
#include "./MQTT/mqtt.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

uint8_t key_num = 0;										//按键键值
uint8_t display_num = 0;								//显示界面
uint16_t time_num = 0;									//计时值
char display_buf[16] = {0};							//显示数组

extern uint8_t esp8266_rx_buf[1024];		//esp8266接收数据数组
extern uint8_t esp8266_rx_finish;				//esp8266接收完成标志位
uint8_t *esp8266_dataPtr = NULL;				//esp8266返回的格式
uint8_t *esp8266_data = NULL;						//esp8266下发的数据
char *esp8266_result = NULL;  					//esp8266解析结果

uint8_t flag_begin_5s = 0;							//5s计时开始标志位
uint8_t flag_finish_5s = 0;;						//5s计时完成标志位

uint16_t sound_value = 0;								//声音值
uint16_t sound_max = 50;								//声音最大值
uint8_t flag_sound = 0;									//声音标志位
uint16_t sound_jl = 0;									//声音记录值

uint16_t alert_num = 0;									//声光报警标志位
uint8_t flag_zd = 0;										//震动标志位


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void Key_Function(void);								//按键函数
void Monitor_Function(void);						//监测函数
void Display_Function(void);						//显示函数
void Manage_Function(void);							//处理函数
void Aliyun_Send_Data(void);						//数据上报函数

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/**********************************
函数名:按键函数
传参值:无
返回值:无
**********************************/
void Key_Function(void)
{
	key_num = Chiclet_Keyboard_Scan(0);		//按键扫描,获取键值
	if(key_num != 0)								      //有按键按下
	{
		switch(key_num)
		{
			case 1:								            //按键1:切换界面
				display_num++;
				if(display_num >= 2)
				{
					display_num = 0;
				}
				
				Oled_Clear_All();					      //清屏
			break;

			case 2:											      //按键2
				switch(display_num)
				{
					case 1:											  //界面1:声音最大值+5
						if(sound_max < 100)
						{
							sound_max += 5;
						}
					break;
					
					default:
					break;
				}
			break;

			case 3:														//按键3
				switch(display_num)
				{
					case 1:											  //界面1:声音最大值-5
						if(sound_max > 0)
						{
							sound_max -= 5;
						}
					break;
					
					default:
					break;
				}
			break;

			default:
			break;
		}
	}
}


/**********************************
函数名:读取指定ADC通道的数据
传参值:通道
返回值:ADC值
**********************************/
uint32_t ADC_Get_Value(uint32_t Channel)
{
	ADC_ChannelConfTypeDef sConfig;
	
  sConfig.Channel = Channel;
  sConfig.Rank = 1;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  
  HAL_ADC_Start(&hadc1);									//启动转换并等待结束
  HAL_ADC_PollForConversion(&hadc1, 10); 	//等待转换完成,10是超时时间(单位ms)
  
  return HAL_ADC_GetValue(&hadc1);				//返回转换后的数据
}


/**********************************
函数名:监测函数
传参值:无
返回值:无
**********************************/
void Monitor_Function(void)
{
	if(time_num % 10 == 0)								//监测数据
	{
		sound_value = 35 * (ADC_Get_Value(ADC_CHANNEL_0) / 4096.0 * 3.3);               //获取声音值
	}
	
	if(sound_value > sound_max)																												//记录声音最大值
	{
		flag_sound = 1;
		
		sound_jl = sound_value;
	}
	
	if(ZD == 0)																																				//判断是否震动
	{
		flag_zd = 1;
	}
	
	esp8266_dataPtr = ESP8266_GetIPD(0);																							//获取平台返回的数据
	if(esp8266_dataPtr != NULL)
	{
		Aliyun_RevPro(esp8266_dataPtr);																									//平台返回数据检测

		esp8266_result = strstr((char *)esp8266_data, "sound_max");											//判断下发数据
		if(esp8266_result != NULL)
		{
			esp8266_result = strstr(esp8266_result, ":") + 1;
			sound_max = atoi((const char *)esp8266_result);

		}
		
		esp8266_result = strstr((char *)esp8266_data, "flag_sound");										//判断声音状态
		if(esp8266_result != NULL)
		{
//			esp8266_result = strstr(esp8266_result, ":") + 1;
			if(sound_value <= sound_max)
			{
				flag_sound = 0;
				
				sound_jl = 0;
			}
		}
		
		esp8266_result = strstr((char *)esp8266_data, "flag_zd");												//判断震动状态
		if(esp8266_result != NULL)
		{
//			esp8266_result = strstr(esp8266_result, ":") + 1;
			if(ZD == 1)
			{
				flag_zd = 0;
			}
		}
	}
	
	MQTT_FreeBuffer(esp8266_data);																										//释放内存
}


/**********************************
函数名:显示函数
传参值:无
返回值:无
**********************************/
void Display_Function(void)
{
	if(time_num % 10 == 0)
	{
		switch(display_num)																				//根据不同的显示界面,显示不同的内容
		{
			case 0:									      													//界面0:显示测量数据
				Oled_ShowCHinese(1,0,"声音:");
				sprintf(display_buf,"%ddB  ",sound_value);
				Oled_ShowString(1,6,display_buf);

				if(flag_sound == 1)																		//显示声音状态
				{
					Oled_ShowCHinese(2,0,"声音:异常");
					sprintf(display_buf,"%ddB  ",sound_jl);
					Oled_ShowString(2,12,display_buf);
				}	
				else
				{
					Oled_ShowCHinese(2,0,"声音:正常");
					
					Oled_ShowString(2,12,"    ");
				}
			
				if(flag_zd == 1)																			//显示震动状态
				{
					Oled_ShowCHinese(3,0,"震动:异常");
				}	
				else
				{
					Oled_ShowCHinese(3,0,"震动:正常");
				}
			break;
			
			case 1:																									//界面1:显示设置声音最大值
				Oled_ShowCHinese(1,0,"设置声音最大值");
				if(time_num % 100 == 0)
				{
					sprintf(display_buf,"%d  ",sound_max); 
					Oled_ShowString(2,7,display_buf);
				}
				if(time_num % 200 == 0)
				{
					Oled_ShowString(2,7,"    ");
				}
			break;

			default:
			break;
		}
	}
}


/**********************************
函数名:处理函数
传参值:无
返回值:无
**********************************/
void Manage_Function(void)
{
	if(display_num == 0)								  								    //测量界面
	{
		if(sound_value > sound_max || ZD == 0)								  //声音值大于设置最大值或震动触发,进行声光报警
		{
			alert_num = 6;
		}
		
		if(alert_num > 0)																				//声光报警三声
		{
			if(time_num % 100 == 0)
			{
				ALERT = !ALERT;
				
				alert_num--;
			}
		}
		else																										//否则,关闭声光报警
		{
			ALERT = 0;
		}
	}
	else																											//设置界面,关闭声光报警
	{
		ALERT = 0;
	}

	if(flag_finish_5s == 1)																		//5秒上传一次数据
  {
    flag_begin_5s = 0;
    Aliyun_Send_Data();
    flag_begin_5s = 1;
  }
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* 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_TIM1_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */

	Delay_Init();													//延时初始化
	Oled_Init();													//OLED初始化
	Key_Init();														//KEY初始化
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
	Oled_Clear_All();											//清屏
	
	HAL_TIM_Base_Start_IT(&htim1);				//启动定时器
	
	HAL_UARTEx_ReceiveToIdle_IT(&ESP8266_HUART, esp8266_rx_buf, sizeof(esp8266_rx_buf) / sizeof(esp8266_rx_buf[0]));		//获取串口接收数据
	
	Oled_ShowString(1,6,"WIFI ");
	Oled_ShowCHinese(2, 2, "初始化中");
	ESP8266_Init();											//初始化ESP8266
	Oled_ShowString(3,4,"........");
	while(Aliyun_DevLink())							//接入阿里云
	Delay_ms(500);
	Oled_ShowString(4,4,"........");
	Aliyun_Subscribe(topics_set, 1);		//订阅主题
	Delay_ms(500);
	Aliyun_Send_Data();									//数据上报初始状态
  flag_begin_5s = 1;									//开启定时
  Oled_Clear_All();										//清屏

  while (1)
  {
		Key_Function();										  //按键函数
		Monitor_Function();									//监测函数
		Display_Function();									//显示函数
		Manage_Function();									//处理函数
		
		if(time_num % 100 == 0)							//指示灯闪烁
		{
			SYSTEM_LED = !SYSTEM_LED;
		}
		
		Delay_ms(1);												//延时1ms
		time_num++;											    //计时值+1
		if(time_num >= 10000)
		{
			time_num = 0;
		}

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */


/**********************************
函数名:定时器中断回调函数
传参值:无
返回值:无
**********************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_count_5s = 0;

	if(htim->Instance == htim1.Instance)		//定时器1触发中断
	{
		if(flag_begin_5s == 1)
		{
			time_count_5s++;
			
			if(time_count_5s >= 5000)						//5s计时
			{
				time_count_5s = 0;
				
				flag_finish_5s = 1;
			}
		}
		else
		{
			time_count_5s = 0;
			flag_finish_5s = 0;
		}
	}
}

/**********************************
函数名:串口事件回调函数
传参值:huart:串口号		Size:数据大小
返回值:无
**********************************/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart->Instance == ESP8266_HUART.Instance)				//4g串口触发中断
	{
		HAL_UARTEx_ReceiveToIdle_IT(&ESP8266_HUART, esp8266_rx_buf, sizeof(esp8266_rx_buf) / sizeof(esp8266_rx_buf[0]));
		esp8266_rx_finish = 1;
	}
}

/**********************************
函数名:串口错误回调函数
传参值:huart:串口号
返回值:无
**********************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_DeInit(huart);
	HAL_UART_Init(huart);
	
	if(huart->Instance == ESP8266_HUART.Instance)
	{
		HAL_UARTEx_ReceiveToIdle_IT(&ESP8266_HUART, esp8266_rx_buf, sizeof(esp8266_rx_buf) / sizeof(esp8266_rx_buf[0]));
		esp8266_rx_finish = 1;
	}
}


/**********************************
函数名:数据上报函数
传参值:无
返回值:无
**********************************/
void Aliyun_Send_Data(void)
{
	char send_data[512];								//发送数据数组
	
	sprintf(send_data,"{\"method\":\"thing/event/property/post\",\"id\":\"203302322\",\"params\":{\"sound_value\":%d,\"flag_sound\":%d,\"sound_max\":%d,\"flag_zd\":%d},\"version\":\"1.0.0\"}",
					sound_jl,flag_sound,sound_max,flag_zd);

	Aliyun_Publish(topics_post, send_data);  		//添加数据,发布给服务器
}


/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐