【mcu-1212】家用空调外机振动监测与报警系统的设计【单片机毕业设计项目参考】
·
一、功能介绍
项目名:家用空调外机振动监测与报警系统的设计
项目编号: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 */
更多推荐

所有评论(0)