【mcu-1215】基于单片机的智能雨伞防丢及天气提醒装置设计与研究【单片机毕业设计项目参考】
·
一、功能介绍
项目名:基于单片机的智能雨伞防丢及天气提醒装置设计与研究
项目编号:dz-1215
单片机类型:STM32F103C8T6
具体功能:
1、通过知心天气获取当前天气情况“温度”“下雨或晴“;
2、通过人体热释电监测当前是否有人从雨伞前经过,监测到有人经过温度大于最大值或者下雨手机弹窗震动提醒”请注意带伞“;
3、通过GPS定位模块获取当前雨伞的位置,用户可以通过手机端查看当前雨伞的位置;
4、通过OLED显示当前环境的温度、下雨或晴、当前雨伞的经纬度、是否有人;
5、通过4G模块将监测的数据传输到手机端;
6、通过按键可以设置温度阈值
二、资料总览
实物资料

仿真资料

三、部分资料展示
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 "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 "./4G/4g.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t huart1_tx_buf[100];
#define Huart1_Send_Str(...) HAL_UART_Transmit(&huart1,huart1_tx_buf,sprintf((char *)huart1_tx_buf,__VA_ARGS__),0xffff) //重定义串口1发送函数
/* 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; //显示界面
uint8_t flag_time_10ms = 0; //计时数
uint32_t time_num = 0; //计时值
char display_buf[32] = {0}; //显示数组
uint8_t huart1_rx_data = 0; //串口1接收单个数据
extern uint8_t Air_4G_buf[512]; //数据接收数组
extern uint16_t Air_4G_cnt; //数据接收数组下标
extern uint16_t Air_4G_cntPre; //数据接收数组下标
uint8_t flag_begin_5s = 0; //5s计时开始标志位
uint8_t flag_finish_5s = 0; //5s计时完成标志位
uint8_t flag_begin_1m = 0; //1m计时开始标志位
uint8_t flag_finish_1m = 0; //1m计时标志位
uint8_t flag_bj = 0; //报警标志位
uint8_t flag_tq = 1; //天气标志位
int16_t temp_max = 40; //温度最大值
Real_Weather weather;
#define Location "xiangyang" //城市地区
#define HUART3_RX_SIZE 1024 //串口3接收数组最大值
uint8_t huart3_rx_buf[HUART3_RX_SIZE]; //串口3接收数组
uint8_t huart3_rx_finish = 0; //串口3接收完成标志位
uint16_t N_du; //纬度的度
float N_fen; //纬度的分
uint16_t E_du; //经度的度
float E_fen; //经度的分
float N_num,E_num; //解析的经纬度
char *result = NULL; //结果
float E_value; //经度值
float N_value; //维度值
/* 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); //处理函数
/* 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:温度最大值+1
if(temp_max < 99)
{
temp_max++;
}
break;
default:
break;
}
break;
case 3: //按键3
switch(display_num)
{
// case 0: //界面1:温度最大值-1
// weather.temperature = 0;
// break;
case 1: //界面1:温度最大值-1
if(temp_max > 0)
{
temp_max--;
}
break;
default:
break;
}
break;
default:
break;
}
}
}
/**********************************
函数名:监测函数
传参值:无
返回值:无
**********************************/
void Monitor_Function(void)
{
if(flag_finish_1m >= 10)
{
flag_begin_1m = 0;
Air_4G_Get_Weather_Once1(Location); //获取实时天气数据
flag_begin_1m = 1;
}
Air_4G_GetData(); //获取4G模块下发数据
if(huart3_rx_finish == 1) //解析GPS数据,获取经纬度
{
result = strstr((char *)huart3_rx_buf,"RMC");
if(result != NULL)
{
result = strstr((char *)result,"A,"); //获取纬度
if(result != NULL)
{
result += 2;
N_num = (float)atof(result);
N_du = (uint16_t)(N_num / 100.0);
N_fen = N_num-N_du*100;
N_num = N_du + N_fen/60.0;
if(0 < N_num && N_num < 60)
N_value = N_num;
}
result = strstr((char *)result,"N,"); //获取经度
if(result != NULL)
{
result += 2;
E_num = (float)atof(result);
E_du = (uint16_t)(E_num / 100.0);
E_fen = E_num-E_du*100;
E_num = E_du + E_fen/60.0;
if(70 < E_num && E_num < 150)
E_value = E_num;
}
}
memset(huart3_rx_buf, 0 ,HUART3_RX_SIZE);
huart3_rx_finish = 0;
}
}
/**********************************
函数名:显示函数
传参值:无
返回值:无
**********************************/
void Display_Function(void)
{
if(time_num % 10 == 0)
{
switch(display_num) //根据不同的显示界面,显示不同的内容
{
case 0: //界面0:显示测量数据
Oled_ShowCHinese(1,0,"温度:"); //显示温度最大值
sprintf(display_buf,"%dC ",weather.temperature);
Oled_ShowString(1,6,display_buf);
Oled_ShowCHinese(1,7,RTRSD == 0? "有": "无"); //有没有人在
Oled_ShowCHinese(2,0,"天气:");
switch(weather.code)
{
case 0:
case 1:
case 2:
case 3:
Oled_ShowCHinese(2,3,"晴");
Oled_ShowString(2,8," ");
break;
case 4:
Oled_ShowCHinese(2,3,"多云");
Oled_ShowString(2,10," ");
break;
case 5:
case 6:
Oled_ShowCHinese(2,3,"晴间多云");
Oled_ShowString(2,14," ");
break;
case 7:
case 8:
Oled_ShowCHinese(2,3,"大部多云");
Oled_ShowString(2,14," ");
break;
case 9:
Oled_ShowCHinese(2,3,"阴");
Oled_ShowString(2,8," ");
break;
case 10:
Oled_ShowCHinese(2,3,"阵雨");
Oled_ShowString(2,10," ");
break;
case 11:
Oled_ShowCHinese(2,3,"雷阵雨");
Oled_ShowString(2,12," ");
break;
case 12:
Oled_ShowCHinese(2,3,"雷阵雨冰雹");
break;
case 13:
Oled_ShowCHinese(2,3,"小雨");
Oled_ShowString(2,10," ");
break;
case 14:
Oled_ShowCHinese(2,3,"中雨");
Oled_ShowString(2,10," ");
break;
case 15:
Oled_ShowCHinese(2,3,"大雨");
Oled_ShowString(2,10," ");
break;
case 16:
Oled_ShowCHinese(2,3,"暴雨");
Oled_ShowString(2,10," ");
break;
case 17:
Oled_ShowCHinese(2,3,"大暴雨");
Oled_ShowString(2,12," ");
break;
case 18:
Oled_ShowCHinese(2,3,"特大暴雨");
Oled_ShowString(2,14," ");
break;
case 19:
Oled_ShowCHinese(2,3,"冻雨");
Oled_ShowString(2,10," ");
break;
case 20:
Oled_ShowCHinese(2,3,"雨夹雪");
Oled_ShowString(2,12," ");
break;
case 21:
Oled_ShowCHinese(2,3,"阵雪");
Oled_ShowString(2,10," ");
break;
case 22:
Oled_ShowCHinese(2,3,"小雪");
Oled_ShowString(2,10," ");
break;
case 23:
Oled_ShowCHinese(2,3,"中雪");
Oled_ShowString(2,10," ");
break;
case 24:
Oled_ShowCHinese(2,3,"大雪");
Oled_ShowString(2,10," ");
break;
case 25:
Oled_ShowCHinese(2,3,"暴雪");
Oled_ShowString(2,10," ");
break;
case 26:
Oled_ShowCHinese(2,3,"浮尘");
Oled_ShowString(2,10," ");
break;
case 27:
Oled_ShowCHinese(2,3,"扬沙");
Oled_ShowString(2,10," ");
break;
case 28:
Oled_ShowCHinese(2,3,"沙尘暴");
Oled_ShowString(2,12," ");
break;
case 29:
Oled_ShowCHinese(2,3,"强沙尘暴");
Oled_ShowString(2,14," ");
break;
case 30:
Oled_ShowCHinese(2,3,"雾");
Oled_ShowString(2,8," ");
break;
case 31:
Oled_ShowCHinese(2,3,"霾");
Oled_ShowString(2,8," ");
break;
case 32:
Oled_ShowCHinese(2,3,"风");
Oled_ShowString(2,8," ");
break;
case 33:
Oled_ShowCHinese(2,3,"大风");
Oled_ShowString(2,10," ");
break;
case 34:
Oled_ShowCHinese(2,3,"飓风");
Oled_ShowString(2,10," ");
break;
case 35:
Oled_ShowCHinese(2,3,"热带风暴");
Oled_ShowString(2,14," ");
break;
case 36:
Oled_ShowCHinese(2,3,"龙卷风");
Oled_ShowString(2,12," ");
break;
case 37:
Oled_ShowCHinese(2,3,"冷");
Oled_ShowString(2,8," ");
break;
case 38:
Oled_ShowCHinese(2,3,"热");
Oled_ShowString(2,8," ");
break;
case 99:
Oled_ShowCHinese(2,3,"未知");
Oled_ShowString(2,10," ");
break;
default:
break;
}
Oled_ShowCHinese(3,0,"经度:");
sprintf(display_buf,"%f",E_value);
Oled_ShowString(3,6,display_buf);
Oled_ShowCHinese(4,0,"纬度:");
sprintf(display_buf,"%f ",N_value);
Oled_ShowString(4,6,display_buf);
break;
case 1: //界面1:显示设置温度最大值
Oled_ShowCHinese(1,0,"设置温度最大值");
if(time_num % 20 == 0)
{
sprintf(display_buf,"%d ",temp_max);
Oled_ShowString(2,7,display_buf);
}
if(time_num % 40 == 0)
{
Oled_ShowString(2,7," ");
}
break;
default:
break;
}
}
}
/**********************************
函数名:处理函数
传参值:无
返回值:无
**********************************/
void Manage_Function(void)
{
if(display_num == 0) //测量界面
{
if(((weather.temperature > temp_max) || (9 <= weather.code && weather.code <= 25)) && RTRSD == 0) //监测到有人经过温度大于最大值或者下雨手机弹窗震动提醒”请注意带伞“;
{
if(flag_bj == 0)
{
flag_bj = 1;
}
}
else //温度处于设置的上下限值之间,两个继电器断开
{
if(flag_bj == 2)
{
flag_bj = 0;
}
}
}
if(flag_finish_5s == 1) //5秒上传一次数据
{
flag_begin_5s = 0;
Air_4G_SendData();
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_USART3_UART_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_UART_Receive_IT(&huart1, &huart1_rx_data, 1); //获取串口1接收数据
HAL_UARTEx_ReceiveToIdle_IT(&huart3, huart3_rx_buf, HUART3_RX_SIZE); //获取串口3接收数据
Oled_ShowString(1,7,"4G");
Oled_ShowCHinese(2, 2, "初始化中");
Air_4G_Init(); //4G初始化
Oled_ShowCHinese(2, 2, "获取天气");
Air_4G_Get_Weather_Once("suzhou");
Oled_ShowCHinese(2, 2, "初始化中");
Oled_ShowString(3,4,"........");
Air_4G_MQTT_Init(); //MQTT初始化
Delay_ms(500);
Oled_ShowString(4,4,"........");
Delay_ms(500);
Air_4G_SendData(); //数据上报初始状态
flag_begin_5s = 1; //开启定时
flag_begin_1m = 1; //开启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};
/** 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();
}
}
/* USER CODE BEGIN 4 */
/**********************************
函数名:定时器中断回调函数
传参值:无
返回值:无
**********************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint32_t time_count_5s = 0;
static uint32_t time_count_1m = 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;
}
if(flag_begin_1m == 1)
{
time_count_1m++;
if(time_count_1m >= 60000) //1m计时
{
time_count_1m = 0;
flag_finish_1m ++;
}
}
else
{
time_count_1m = 0;
flag_finish_1m = 0;
}
}
}
/**********************************
函数名:串口中断回调函数
传参值:串口号
返回值:无
**********************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == huart1.Instance) //串口1触发中断
{
if(Air_4G_cnt < sizeof(Air_4G_buf))
{
Air_4G_buf[Air_4G_cnt++] = huart1_rx_data;
}
else
{
Air_4G_cnt = 0;
Air_4G_cntPre = 0;
}
HAL_UART_Receive_IT(&huart1, &huart1_rx_data, 1);
}
}
/**********************************
函数名:串口事件回调函数
传参值:huart:串口号 Size:数据大小
返回值:无
**********************************/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance == huart3.Instance) //串口3触发中断
{
HAL_UARTEx_ReceiveToIdle_IT(&huart3, huart3_rx_buf, HUART3_RX_SIZE);
huart3_rx_finish = 1;
}
}
/**********************************
函数名:串口错误回调函数
传参值:huart:串口号
返回值:无
**********************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
HAL_UART_DeInit(huart);
HAL_UART_Init(huart);
if(huart->Instance == huart1.Instance)
{
HAL_UART_Receive_IT(&huart1, &huart1_rx_data, 1);
}
if(huart->Instance == huart3.Instance)
{
HAL_UARTEx_ReceiveToIdle_IT(&huart3, huart3_rx_buf, HUART3_RX_SIZE);
}
}
/* 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)