当前位置:   article > 正文

【STM32G4】备战蓝桥杯嵌入式---实战---第七届嵌入式国赛(温、湿度监控设备)_蓝桥杯嵌入式摄氏度符号

蓝桥杯嵌入式摄氏度符号


前言

准备国赛第一天,发现之前做的第八届模拟赛是第七届决赛,是我书买错了?奇奇怪怪。
但是还是给第一天来个完整的结尾。

一、题目

功能简述

1、功能简述
“温湿度监控设备”通过采集传感器输出电压信号和信号频率得到环境温湿度数据, 并能够根据设定的温湿度阈值执行相应动作,系统框图如图 1 所示:
在这里插入图片描述
2、设计任务及要求
(1)温度测量功能
通过竞赛板上电位器 R37 输出电压模拟温度传感器输出信号, 温度测量范围为-20℃~60℃, 电压温度关系为如下式所示:
T = k*VR37 + b, 其中 T 代表环境温度, VR37为电位器输出信号, k、 b 为常数, 0V时对应温度为-20℃, 3.3V 对应 60℃。

(2)湿度测量功能
通过竞赛板 PA7 引脚检测输入信号频率, 相对湿度测量范围为 10%~90%, 频率湿度关系如下式所示:H = m*F + n, 其中 H 代表环境湿度, F 为传感器输入到设备信号频率, m、 n 为常数, 1KHz 对应相对湿度为 10%, 10KHz 对应 90%。

(3)测试信号
通过竞赛板 PA1 引脚输出频率 1KHz 到 10KHz 方波, 模拟湿度传感器输出信号。

(4)参数设置与数据记录功能
可以通过按键设定温、 湿度上限和数据采样间隔, 温湿度数据记录间隔可设置为 1 - 5秒, 要求至少保存 60 组数据, 数据不需要写入 FLASH 或 E2PROM 存储器。

(5)RTC功能
通过单片机片内 RTC 设计实现实时时钟功能。

(6)按键功能定义
设备上电后, 通过 LCD 显示实时温、 湿度数据和数据记录次数, 显示格式如图 2 所示:
在这里插入图片描述
B1 按键:“功能” 按键, 按下后进入功能设定界面(如图 3 所示), 再次按下 B1 按键时退出设置界面, 保存用户设定的结 果到 E2PROM, 并返回图 2 所示的实时数据显示界面。
在这里插入图片描述
B2 按键:“切换” 按键, 切换选择 4 个待修改的运行参数, 被选中的参数突出显示(如图 2“湿度上限”)。
B3 按键:“加” 按键, 当前选择的参数是温度时, 参数加 1℃; 选择采样间隔时, 参数加 1 秒; 选择参数为湿度时, 参数 加 5%; 选择测试信号时, 测试信号频率加 500Hz;
B4 按键:“减” 按键,当前选择的参数是温度时, 参数减 1℃; 选择采样间隔时, 参数减 1 秒, 选择参数为湿度时,参数减 5%; 选择测试信号时, 测试信号频率减 500Hz;
备注:“加”、 减按键应根据当前调整的参数属性, 设计合理的边界值。

7)串口功能
设备通过串口完成阈值和数据查询功能, 使用 STM32 USART2 完成上述串口功能, 波特率设置为 9600。
①. 阈值查询
通过 PC 机给设备发送字符‘C’, 设备返回包含当前温湿度阈值和当前时间的字符串, 格式可自定义。
②. 数据查询
通过 PC 机给设备发送字符‘T’, 设备返回包含当前采集到的所有温、 湿度数据的字符串, 每条温、 湿度数据应包含该条数据的记录时间, 格式可自定义。

(8)报警指示功能
当前温度值超过温度上限时, 指示灯 L1 闪烁报警;
当前温度值超过湿度上限时, 指示灯 L2 闪烁报警;
每次数据采集时, 指示灯 L3 亮、 灭的状态反转。

二、模块初始化以及功能分析

1.模块的初始化

需要用的模块:LCD、四个按键、LED、ADC(PB15)、IIC、TIM、RTC

2.模块功能分析

LCD–>屏幕显示
按键–>对参数进行调整
EEPROM–>读取和存储信息到
ADC(PB15)–>读取温度传感器输出的信号
TIM3_CH2(PA7)–>输入捕获
TIM2_CH2(PA1)–> 输出不同频率的方波

三、函数实现

1.主函数分析

参数获取:EEPROM检测是否第一次写入,若为第一次写入则默认参数,反则读取存储的参数

	/* IIC初始化 */
	I2CInit();
	/* LCD初始化 */
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	/* RTC初始化 */
	HAL_RTC_Init(&hrtc);//RTC初始化
	/* 定时器开启PWM输出、输入捕获 */
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
	/* 参数初始化 */
	Number = 0;
	if(IIC_Read(0x04) != 1)
	{
		IIC_Write(0x00, 40);HAL_Delay(5);
		IIC_Write(0x01, 80);HAL_Delay(5);
		IIC_Write(0x02, 1);HAL_Delay(5);
		IIC_Write(0x03, 15);HAL_Delay(5);
		IIC_Write(0x04, 1);HAL_Delay(5);
	}
	EEPROM_Read();
	/* 关闭LED提示 */
	GPIOC->ODR |= 0xff00;
	GPIOD->ODR |= (1 << 2);
	GPIOD->ODR &= ~(1 << 2);
  • 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

while(1)

 		Display();
		key = KEY_Scan(0);
		KEY_Handle(key);
		/* RTC获取时间 */
		HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc,&Date,RTC_FORMAT_BIN);
		/* 获取温度和湿度部分 */
		Temperature[0] = (Get_ADC()*3.3/4096)/3.3*80 - 20;
		Humidity[0] = (TIM3_Frequency-1) * 80 / 9 + 10;
		/* 报警部分 */
		if(Temperature[0] > Temperature[1] && i%2)
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
		else HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
		
		if(Humidity[0] > Humidity[1] && j%2)
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);
		else HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);
		
		if(z%2)	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);
		else HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET);
		
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		/* 串口接收中断 */
		HAL_UART_Receive_IT(&huart1, ass, 1);
		if(mode == 0 && (Time.Seconds >= (Last_Second + Period)%60) && Number < 60)//页面一并且到达采集间隔时间
		{
			Last_Second = Time.Seconds;//重置上次时间
			z++;
			/* 记录参数部分 */
			Data[Number].hour = Time.Hours;
			Data[Number].minute = Time.Minutes;
			Data[Number].second = Time.Seconds;// 保存记录时间
			Data[Number].humidity = Humidity[0];
			Data[Number].temperature = Temperature[0];//保存温度
			
			Number++;
		}
  • 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

2.子函数分析

1.void Display(void);

Temperature[0]表示当前温度;Temperature[1]表示上限温度
Humidity[0]表示当前获取湿度;Humidity[1]表示上限湿度
RTC_TimeTypeDef Time;RTC时间结构体
Number;记录次数
Period;获取间隔时间
Frequency;设定的值
TIM3_Frequency;TIM3输入捕获的值

void Display(void)
{
	if(mode == 0)
	{
		LCD_DisplayStringLine(Line1, "   Current Data     ");
		if(Temperature[0] < 0)
			sprintf((char *)Str,"Tempe:  -%.1f", -Temperature[0]);
		else 
			sprintf((char *)Str,"Tempe:   %.1f", Temperature[0]);
		LCD_DisplayStringLine(Line3, Str);
		
		sprintf((char *)Str,"Humidity:  %d%%", Humidity[0]);
		LCD_DisplayStringLine(Line5, Str);
		
		sprintf((char *)Str,"Time:  %.2d-%.2d-%.2d", Time.Hours, Time.Minutes, Time.Seconds);
		LCD_DisplayStringLine(Line7, Str);
		
		sprintf((char *)Str,"         times:  %d", Number);
		LCD_DisplayStringLine(Line9, Str);
	}
	else if(mode == 1)
	{
		LCD_DisplayStringLine(Line1, "   Parameter setting     ");

		sprintf((char *)Str,"Temp:  %.0f", Temperature[1]);
		if(Location == 0)	LCD_SetTextColor(Red);
		LCD_DisplayStringLine(Line3, Str);
		LCD_SetTextColor(Black);
		
		sprintf((char *)Str,"Humi:  %d%%", Humidity[1]);
		if(Location == 1)	LCD_SetTextColor(Red);
		LCD_DisplayStringLine(Line5, Str);
		LCD_SetTextColor(Black);
		
		sprintf((char *)Str,"Interval:  %dS", Period);
		if(Location == 2)	LCD_SetTextColor(Red);
		LCD_DisplayStringLine(Line7, Str);
		LCD_SetTextColor(Black);
		
		sprintf((char *)Str,"Signal:  %.1fKHz", Frequency);
		if(Location == 3)	LCD_SetTextColor(Red);
		LCD_DisplayStringLine(Line9, Str);
		LCD_SetTextColor(Black);
	}
}
  • 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

2.uint8_t KEY_Scan(uint8_t mode);

uint8_t KEY_Scan(uint8_t mode)
{
	static uint8_t flag=1;
	if(mode)	flag = 1;
	if(flag &&(KEY_B1 == 0 || KEY_B2	== 0 || KEY_B3 == 0 ||	KEY_B4== 0 ))
	{
		HAL_Delay(10);
		flag = 0;
		if (KEY_B1 == 0)	return B1_Press;
		else if (KEY_B2 == 0) return B2_Press;
		else if (KEY_B3 == 0) return B3_Press;
		else if (KEY_B4 == 0) return B4_Press;
	}else if(KEY_B1 == KEY_B2 == KEY_B3 == KEY_B4 == 1)	flag = 1;
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.void KEY_Handle(uint8_t key);

对于四个按键,不同的按键对应不同的操作

void KEY_Handle(uint8_t key)
{
	if(key == B1_Press)
	{
		mode = !mode;
		if(mode == 1)	EEPROM_Write();
		LCD_Clear(White);
	}
	else if(key == B2_Press)
	{
		if(Location == 4)	Location = 0;
		else Location++;
		Location = Location % 4;
	}
	else if(key == B3_Press)
	{
		if(Location == 0 && Temperature[1] < 60)	Temperature[1]++;
		else if(Location == 1 && Humidity[1] < 90)	Humidity[1] = Humidity[1] + 5;
		else if(Location == 2 && Period <= 5)	Period++;
		else if(Location == 3 && (double)Frequency <= 10.0)	
		{
			Frequency = (double)Frequency + 0.5;
			TIM2->PSC = (double)1000/Frequency - 1;
			TIM2->ARR = 80-1;
		}
	}
	else if(key == B4_Press)
	{
		if(Location == 0 && Temperature[1] > -20)	Temperature[1]--;
		else if(Location == 1 && Humidity[1] > 10.0)	Humidity[1] = Humidity[1] - 5;
		else if(Location == 2 && Period > 1)	Period--;
		else if(Location == 3 && Frequency > 1)	
		{
			Frequency = (double)Frequency - 0.5;
			TIM2->PSC = (double)1000/Frequency - 1;
			TIM2->ARR = 80-1;
		}
	}
}
  • 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

4.uint16_t Get_ADC(void);

读取电压值,电压值为Get_ADC()*3.3/4096;

uint16_t Get_ADC(void)
{
	uint16_t temp = 0 ;
	HAL_ADC_Start(&hadc2);
	temp = HAL_ADC_GetValue(&hadc2);
	HAL_ADC_Stop(&hadc2);
	return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5.EEPROM_Write(void);EEPROM_Read(void);

void EEPROM_Write(void)
{
	IIC_Write(0x00, Temperature[1]);HAL_Delay(5);
	IIC_Write(0x01, Humidity[1]);	HAL_Delay(5);
	IIC_Write(0x02, Period);		HAL_Delay(5);
	IIC_Write(0x03, Frequency*10);	HAL_Delay(5);
}
void EEPROM_Read(void)
{
	Temperature[1] = IIC_Read(0x00);HAL_Delay(5);
	Humidity[1] = IIC_Read(0x01);	HAL_Delay(5);
	Period = IIC_Read(0x02);		HAL_Delay(5);
	Frequency = IIC_Read(0x03)/10.0;HAL_Delay(5);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

6.HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

串口中断服务函数,处理串口接收到的数据做出对应发送数据。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(ass[0] == 'C')
	{
		sprintf((char *)Str,"Temperature: %f, Humidity:	%d\r\n",Temperature[1], Humidity[1]);
		HAL_UART_Transmit(&huart1, Str, sizeof(Str), 100);
		sprintf((char *)Str,"Date: %d-%d-%d\r\n",Time.Hours, Time.Minutes, Time.Seconds);
		HAL_UART_Transmit(&huart1, Str, sizeof(Str), 100);
	}
	else if(ass[0] == 'T')
	{
		uint8_t i;
		for(i = 0 ; i < Number ; i++)
		{
			sprintf((char *)Str,"Date: %d-%d-%d Temperature: %f℃, Humidity:	%d%%\r\n",
				Data[i].hour, Data[i].minute, Data[i].second, Data[i].temperature, Data[i].humidity);
			HAL_UART_Transmit(&huart1, Str, sizeof(Str), 100);
		}
	}
	memset(ass,0,sizeof(ass));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

7.HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);

输入捕获,获取TIM3->CCR2的值,计算频率。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	uint32_t Value2 = 0;
	
	HAL_TIM_IC_Stop_IT(&htim3,TIM_CHANNEL_2);
	Value2 = TIM3->CCR2;//__HAL_TIM_GET_COUNTER(&htim3);
	TIM3->CCR2 = 0;//__HAL_TIM_SetCounter(&htim3,0);
	
	TIM3_Frequency = (float)(1000000/Value2) / 1000;//Frequency是KHz
	
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

9.void SysTick_Handler(void);

	if(num++ >= 200)	
	{
		i++;
		j++;
		i %= 50;
		j %= 50;
		num = 0;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

总结

国赛准备第一弹完美结束

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/684096
推荐阅读
相关标签
  

闽ICP备14008679号