赞
踩
准备国赛第一天,发现之前做的第八届模拟赛是第七届决赛,是我书买错了?奇奇怪怪。
但是还是给第一天来个完整的结尾。
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 亮、 灭的状态反转。
需要用的模块:LCD、四个按键、LED、ADC(PB15)、IIC、TIM、RTC
LCD–>屏幕显示
按键–>对参数进行调整
EEPROM–>读取和存储信息到
ADC(PB15)–>读取温度传感器输出的信号
TIM3_CH2(PA7)–>输入捕获
TIM2_CH2(PA1)–> 输出不同频率的方波
参数获取: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);
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++;
}
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);
}
}
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;
}
对于四个按键,不同的按键对应不同的操作
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;
}
}
}
读取电压值,电压值为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;
}
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);
}
串口中断服务函数,处理串口接收到的数据做出对应发送数据。
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));
}
输入捕获,获取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);
}
if(num++ >= 200)
{
i++;
j++;
i %= 50;
j %= 50;
num = 0;
}
国赛准备第一弹完美结束
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。