基于物联网技术的智慧病房管理系统(三)——定时开关灯与信息获取

基于物联网技术的智慧病房管理系统(三)—— 定时开关灯与信息获取

这里我们主要实现能够定时开关灯,并且能够获取如下信息:

  1. 病人按下紧急呼叫信号

  2. 定时获取病人脉搏血氧数据

定时开关灯

这里要求我们能够实现在早上 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 读取日历和时间:

STM32 —— 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();	
	}
}

这部分代码要写在初始化代码前面

这样我们就实现了定时开关灯

信息获取

这里的信息获取多是通过串口进行发送信息,所以这里不会单独进行介绍,需要的可以参考前面的串口发送数据的代码:

STM32 —— 串口通信1 Hello Windows

这里我们采用的是通过 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);
	}
}
posted @ 2023-01-13 12:44  ppqppl  阅读(25)  评论(0编辑  收藏  举报