基于物联网技术的智慧病房管理系统(三)——定时开关灯与信息获取
基于物联网技术的智慧病房管理系统(三)—— 定时开关灯与信息获取
这里我们主要实现能够定时开关灯,并且能够获取如下信息:
-
病人按下紧急呼叫信号
-
定时获取病人脉搏血氧数据
定时开关灯
这里要求我们能够实现在早上 7 点开灯,晚上 22 点灭灯,所以我们就要设计 RTC 系统时间与日历读取,确定我们当前的时间与日期,然后判断时间数,最终通过 PWM 实现灯的渐亮与渐灭
这里首先我们需要配置 RTC:
这里先设置两个变量用于获取时间和日期:
RTC_DateTypeDef Date;
RTC_TimeTypeDef Time;
然后我们可以通过时间进行判断从而实现开关灯的效果:
void ledauto_task_entry(void *parameter){
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
while(1){
HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);
if(Time.Hours == 7&&Time.Minutes == 0&&Time.Seconds == 0){
printf("开灯!");
for(uint16_t i=1;i<500;i++){
htim2.Instance->CCR2 = i;
rt_thread_delay(5);
}
}
else if(Time.Hours == 22&&Time.Minutes == 0&&Time.Seconds == 0){
printf("关灯!");
for(uint16_t i=499;i>=1;i--){
htim2.Instance->CCR2 = i;
rt_thread_delay(5);
}
}
}
}
前面在博客中已经介绍了如何通过 RTC 读取日历和时间:
这里我们只需要照做就可以,但是,由于开发板掉电,时间会重置,所以这里设计时间掉电保存,如果使用外接 RTC 并有电池,则会在掉电后继续计时,这里我设计将代码直接写道 RTC 初始化的函数中即可,完整初始化代码如下:
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
/* USER CODE BEGIN RTC_Init 1 */
__HAL_RCC_BKP_CLK_ENABLE();// 开启后背区域时钟
__HAL_RCC_PWR_CLK_ENABLE();// 开启电源时钟
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!= 0x5051)
{
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x7;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
DateToUpdate.WeekDay = RTC_WEEKDAY_THURSDAY;
DateToUpdate.Month = RTC_MONTH_JANUARY;
DateToUpdate.Date = 0x12;
DateToUpdate.Year = 0x23;
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC); //开启RTC时钟秒中断
datebuff = DateToUpdate; //把日期数据拷贝到自己定义的data中
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x5051);//向指定的后备区域寄存器写入数据
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)datebuff.Year);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)datebuff.Month);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)datebuff.Date);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)datebuff.WeekDay);
}
else
{
datebuff.Year = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
datebuff.Month = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);
datebuff.Date = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);
datebuff.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);
DateToUpdate = datebuff;
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC); //开启RTC时钟秒中断
}
getRealTime();
/* USER CODE END RTC_Init 2 */
}
然后我们需要在运行时,实时获取一次时间:
void getRealTime(void)
{
HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &datebuff, RTC_FORMAT_BIN);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)datebuff.Year);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)datebuff.Month);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)datebuff.Date);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)datebuff.WeekDay);
}
void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
{
if(hrtc->Instance == RTC)
{
getRealTime();
}
}
这部分代码要写在初始化代码前面
这样我们就实现了定时开关灯
信息获取
这里的信息获取多是通过串口进行发送信息,所以这里不会单独进行介绍,需要的可以参考前面的串口发送数据的代码:
这里我们采用的是通过 modbus 协议对数据进行收发,我们直接采用我们前面的博客的教程:
STM32 —— FreeModbus 从机移植,基于 Modbus 协议读取从机温度(AHT20)
成功将 FreeModbus 移植后实现对 AHT20 模块的读取就成功的获取了数据
由于现在手中没有心率与血氧传感器模块,所以暂时用温度代替血氧模块进行开发,这里暂时不考虑血氧模块,这里将血氧异常报警的功能改为温度异常报警:
//读取温度任务
void usart1_task_entry(void *parameter)
{
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
uint32_t CT_data[2]={0,0}; //
volatile int c1,t1;
rt_thread_delay(50);
AHT20_Init();
rt_thread_delay(2500);
while(1)
{
AHT20_Read_CTdata_crc(CT_data); //经过CRC校验,读取AHT20的温度和湿度数据 推荐每隔大于1S读一次
c1 = CT_data[0]*1000/1024/1024; //计算得到湿度值c1(放大了10倍)
t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)
//printf("温度:%d%d.%d",t1/100,(t1/10)%10,t1%10); // 这里需要对温度进行计算后才能得到我们需要的温度值
//printf("湿度:%d%d.%d",c1/100,(c1/10)%10,c1%10); // 这里同样需要对适度进行计算
//printf("\r\n");
if(t1/100,(t1/10)%10,t1%10>30){
printf("error!");
}
(void)eMBPoll();
rt_thread_delay(3000);
}
}