基于max30102的物联网病房监测系统(中断处理和主题逻辑)

news2024/11/19 9:23:21

目录

五、中断处理

六、主体框架

对采集数据的初始化

核心功能的实现

烟雾

通信帧格式

wifi接收数据的处理

OLED显示


 

五、中断处理

void SysTick_Handler(void)
{
	TimingDelay_Decrement();
}

void ESP8266_USART_INT_FUN(void)
{
	uint8_t ucCh;
	
	if ( USART_GetITStatus (ESP8266_USARTx, USART_IT_RXNE ) != RESET )
	{
		ucCh  = USART_ReceiveData(ESP8266_USARTx );
		if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符
			strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = ucCh;

	}
	 	 
	if ( USART_GetITStatus(ESP8266_USARTx, USART_IT_IDLE ) == SET )                                         //数据帧接收完毕
	{
    strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;
		
		ucCh = USART_ReceiveData(ESP8266_USARTx );
		ucTcpClosedFlag = strstr(strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;
		
  }
}


void ADC_IRQHandler_FUN(void)
{
  if(ADC_GetITStatus(ADCx,ADC_IT_EOC)!=RESET)
  {
    ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
    /* 读取ADC的转换值 */
    ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
    
  }
}

主要就是3个ESP8266的通信中断,定时器中断和ADC采集中断

六、主体框架

对采集数据的初始化

 for(i=0;i<n_ir_buffer_length;i++)
    {
        while(MAX30102_INT==1);   //wait until the interrupt pin asserts
        
		max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
		aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
		aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
            
        if(un_min>aun_red_buffer[i])
            un_min=aun_red_buffer[i];    //update signal min
        if(un_max<aun_red_buffer[i])
            un_max=aun_red_buffer[i];    //update signal max
    }
	un_prev_data=aun_red_buffer[i];
	//calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 
		//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
        for(i=100;i<500;i++)
        {
            aun_red_buffer[i-100]=aun_red_buffer[i];
            aun_ir_buffer[i-100]=aun_ir_buffer[i];
            
            //update the signal min and max
            if(un_min>aun_red_buffer[i])
            un_min=aun_red_buffer[i];
            if(un_max<aun_red_buffer[i])
            un_max=aun_red_buffer[i];
        }
		//take 100 sets of samples before calculating the heart rate.
        for(i=400;i<500;i++)
        {
            un_prev_data=aun_red_buffer[i-1];
            while(MAX30102_INT==1);
            max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
			aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
			aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
        
            if(aun_red_buffer[i]>un_prev_data)
            {
                f_temp=aun_red_buffer[i]-un_prev_data;
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness-=(int)f_temp;
                if(n_brightness<0)
                    n_brightness=0;
            }
            else
            {
                f_temp=un_prev_data-aun_red_buffer[i];
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness+=(int)f_temp;
                if(n_brightness>MAX_BRIGHTNESS)
                    n_brightness=MAX_BRIGHTNESS;
            }
			//send samples and calculation result to terminal program through UART
			if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
			{
				dis_hr = n_heart_rate;
				dis_spo2 = n_sp02;
			}
			else
			{
				dis_hr = 0;
				dis_spo2 = 0;
			}
//				printf("HR=%i, ", n_heart_rate); 
//				printf("HRvalid=%i, ", ch_hr_valid);
//				printf("SpO2=%i, ", n_sp02);
//				printf("SPO2Valid=%i\r\n", ch_spo2_valid);
		}
        maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);

核心功能的实现

		if(order[0] == 1)
		{
			show2(order[1],order[2],order[3],order[4]);
			Delay_ms(500);
			printf("可燃气体浓度  %f\r\n", Smog_GetPPM());
			if(order[1] == 1)
			{
				LED1_ON;
				
			}else{
				LED1_OFF;
			}
			
			if(order[2] == 1)
			{
				LED2_ON;
		
			}else{
				LED2_OFF;
			}

			if(order[3] == 1)
			{
				LED3_ON;
				
			}else{
				LED3_OFF;
			}

			if(order[4] == 1)
			{
				BEEP_StateSet(BEEPState_ON);
			}else{
				BEEP_StateSet(BEEPState_OFF);
			}			
			
		}else{
			sprintf(cStr,"%d+%d+%d+%d+%d+%d+%d",DHT11_Data.temp_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci,dis_hr,dis_spo2,m);
			ESP8266_SendString(ENABLE,cStr,0,Single_ID_0);  
			show((u8 *)temp_1,(u8 *)hum_2,(u8 *)s_3,(u8 *)o_4);
			
			
			if( DHT11_Data.temp_int > order[1] || DHT11_Data.temp_int < order[2] )
			{
				LED1_ON;
				LED2_OFF;
				LED3_OFF;
				BEEP_StateSet(BEEPState_ON);
				Delay_ms(1000);
			}else if( DHT11_Data.humi_int > order[3] || DHT11_Data.humi_int < order[4] ){
				LED2_ON;
				LED1_OFF;
				LED3_OFF;
				BEEP_StateSet(BEEPState_ON);
				Delay_ms(1000);
			}else if( dis_hr > order[6] || dis_hr < order[5]){
				if( dis_hr == 0)
				{}else{
					LED1_ON;
					LED2_ON;
					LED3_OFF;
					BEEP_StateSet(BEEPState_ON);
					Delay_ms(1000);
				}
			}else if( dis_spo2 < order[7] || dis_spo2 > order[8]){
				if( dis_spo2 == 0)
				{}else{
					LED2_ON;
					LED3_ON;
					LED1_OFF;
					BEEP_StateSet(BEEPState_ON);
					Delay_ms(1000);
				}
			}else if(m == 1){
				LED1_OFF;
				LED2_OFF;
				LED3_ON;
				BEEP_StateSet(BEEPState_ON);
				Delay_ms(1000);
			}else{
				LED1_OFF;
				LED2_OFF;
				LED3_OFF;
				BEEP_StateSet(BEEPState_OFF);	
				Delay_ms(1000);
			}
			
			LED1_OFF;
			LED2_OFF;
			LED3_OFF;
			BEEP_StateSet(BEEPState_OFF);
		}

我把服务器数据重新转换放到了数组中,再用一个大分支结构对其中的数据进行判别然后实现对应功能。

烟雾

读取电压值 

float Smog_Get_Vol(void)
{
	u16 adc_value = 0;//这是从MQ-7传感器模块电压输出的ADC转换中获得的原始数字值,该值的范围为0到4095,将模拟电压表示为数字值
	float voltage = 0;//MQ-7传感器模块的电压输出,与一氧化碳的浓度成正比
	
	adc_value = ADC_ConvertedValue;//#define SMOG_ADC_CHX	ADC_Channel_4	定义烟雾传感器所在的ADC通道编号
	Delay_ms(5);
	
    voltage  = (3.3/4096.0)*(adc_value);
	
	return voltage;
}

/*********************
// 传感器校准函数,根据当前环境PPM值与测得的RS电压值,反推出R0值。
// 在空气中运行过后测出R0为26
float MQ7_PPM_Calibration()
{
    float RS = 0;
    float R0 = 0;
    RS = (3.3f - Smog_Get_Vol()) / Smog_Get_Vol() * RL;//RL    10  // RL阻值
    R0 = RS / pow(CAL_PPM / 98.322, 1 / -1.458f);//CAL_PPM  10  // 校准环境中PPM值
    return R0;
}
**********************/ 

// 计算Smog_ppm
float Smog_GetPPM()
{
	float RS = (3.3f - Smog_Get_Vol()) / Smog_Get_Vol() * RL;
	float ppm = 98.322f * pow(RS/R0, -1.458f);
	}

通信帧格式

接收帧格式

模式 1
1 LED1 LED2 LED3 BEEP
每个功能一位控制 1开 0关

模式2

0 两位数表示温度上限 左高位右低位 温度下限 湿度上限 湿度下限 心率用一位表示 0 1 2 分别为 小孩 成年人 老人 输入其它数值表示是个人就行 两位表示血氧下限 左高右低
模式2接收一共12位

050108020490

发送帧格式
sprintf(cStr,"%d+%d+%d+%d+%d+%d+%d",DHT11_Data.temp_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci,dis_hr,dis_spo2,m);
温度整数+温度小数+湿度整数+湿度小数+心率+血氧饱和度+是否有可燃气体

wifi接收数据的处理

 由于接收到的是字符串,所以剪掉字符0变成整数,传多位数据的时候乘10改变位置就行。

主要是确保数据不会出错。暂时没使用任何协议,算是自己指定了一个没有校验的简单协议吧。以后有机会改成MQTT格式或者MODBUS格式的协议。

u32* wifi_rec(void)
{
	u32 pCH;
	int i;
    ESP8266_ReceiveString(ENABLE);
	if ( strEsp8266_Fram_Record .InfBit .FramFinishFlag )
	{
    	strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';
			
		printf ( "\r\n%s\r\n", strEsp8266_Fram_Record .Data_RX_BUF );
		if(strEsp8266_Fram_Record .Data_RX_BUF[0] == '1'){
			for(i = 0; i < 12;i++)
			{
				order[i] = strEsp8266_Fram_Record .Data_RX_BUF[i] - '0';
			}	
		}else{
			for(i = 0; i < 9;i++)
			{
				if (i == 0)
				order[i] = strEsp8266_Fram_Record .Data_RX_BUF[i] - '0';
				else{
					if( i % 2 == 0)
					{
						order[i/2] = (((strEsp8266_Fram_Record .Data_RX_BUF[i-1] - '0') * 10) + (strEsp8266_Fram_Record .Data_RX_BUF[i] - '0'));
					}
				}
			}
		
			//0 模式 1234 温湿度 56心率 78血氧
			//第九位 0 1 2 小孩 成年人 老人   80-140  60-100  55-75  
			switch(strEsp8266_Fram_Record .Data_RX_BUF[9])
			{
				case 0:
					order[5] = 80;
					order[6] = 140;
					break;
				case 1:
					order[5] = 60;
					order[6] = 100;
					break;
				case 2:
					order[5] = 55;
					order[6] = 75;
					break;
				default:
					order[5] = 40;
					order[6] = 160;
					break;
			}
			//血氧饱和度正常人 90 - 100
		
			order[7] = (((strEsp8266_Fram_Record .Data_RX_BUF[10] - '0') * 10) + (strEsp8266_Fram_Record .Data_RX_BUF[11] - '0'));
			printf("血氧下限 %d",order[7]);
			order[8] = 100;
		}
      /*将接收到的字符串转成整形数*/
      pCH=atoi(strEsp8266_Fram_Record .Data_RX_BUF);

       switch(pCH)
       {
         case 0:
         break;
          
         case 1:
         break;
         
         case 2:

         break;
             
       }         
    }  
	return order;
}

OLED显示

void show(uint8_t *a,uint8_t *b, uint8_t *c, uint8_t *o)
{
	OLED_CLS();//清屏
	OLED_ShowCN(0,0,26);//温
	OLED_ShowCN(16,0,27);//度
	OLED_ShowCN(32,0,14);//:
	OLED_ShowStr(48,0,a,2);		//2表示8X16
	

	OLED_ShowCN(0,2,28);//湿
	OLED_ShowCN(16,2,27);//度
	OLED_ShowCN(32,2,14);//:
	OLED_ShowStr(48,2,b,2);		//2表示8X16
	
	OLED_ShowCN(0,4,29);//心
	OLED_ShowCN(16,4,30);//率
	OLED_ShowCN(32,4,14);//:
	OLED_ShowStr(48,4,c,2);		//2表示8X16
	
	OLED_ShowCN(0,6,37);//血
	OLED_ShowCN(16,6,38);//氧
	OLED_ShowCN(32,6,14);//:
	OLED_ShowStr(48,6,o,2);		//2表示8X16
}

上面是自主更新,下面是被控制模式,由于服务器童鞋没写远程改上下限功能,我的这部分也被注释掉了。真要用还得调试一下,毕竟没检验过。 

void show2(u32 a,u32 b, u32 c, u32 o)
{
	OLED_CLS();//清屏
	
	OLED_ShowCN(0,0,41);//红
	OLED_ShowCN(16,0,44);//灯
	OLED_ShowCN(32,0,14);//:
	if(a  == 1)
	{
		OLED_ShowCN(48,0,46);//开
	}else{
		OLED_ShowCN(48,0,47);//关
	}
	
	OLED_ShowCN(0,2,45);//绿
	OLED_ShowCN(16,2,44);//灯
	OLED_ShowCN(32,2,14);//:
	if(b  == 1)
	{
		OLED_ShowCN(48,2,46);//开
	}else{
		OLED_ShowCN(48,2,47);//关
	}
	
	OLED_ShowCN(0,4,42);//黄
	OLED_ShowCN(16,4,44);//灯
	OLED_ShowCN(32,4,14);//:
	if(c  == 1)
	{
		OLED_ShowCN(48,4,46);//开
	}else{
		OLED_ShowCN(48,4,47);//关
	}

	OLED_ShowStr(0,6,(u8*)"BEEP",2);
	OLED_ShowCN(32,6,14);//:
	if(o  == 1)
	{
		OLED_ShowCN(48,6,46);//开
	}else{
		OLED_ShowCN(48,6,47);//关
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/492243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

platform总线五级匹配解析

代码来源&#xff1a;开源linux内核linux-6.2.9 platform总线设备与驱动的匹配 对于device和driver无论哪个创建都会尝试主动寻找对方进行绑定&#xff0c;而platform bus总线的匹配原则如上面的代码所示&#xff0c;共有五级匹配&#xff0c;这里进行详细解析下&#xff1a; …

WRF模式

随着生态文明建设和“碳中和”战略的持续推进&#xff0c;我国及全球气候变化及应对是政府、科学界及商业界关注的焦点。气候是多个领域&#xff08;生态、水资源、风资源及碳中和等问题&#xff09;的主要驱动因素&#xff0c;合理认知气候变化有利于解释生态环境变化机理及过…

Android应用层开发学习 Framework 是必须的吗?

作为一名应用层 App 开发工程师&#xff0c;我们为什么要学习 Android Framework&#xff1f;答案很简单&#xff0c;为了不被淘汰&#xff01;在 2023 年的当下,不会点 Binder WMS AMS PMS 好像都找不到工作了&#xff0c;更过分的是应聘企业甚至希望你会点 RN Fluter 等跨平台…

元宇宙的重要底层技术

在元宇宙中&#xff0c;人们可以通过数字分身、化身&#xff08;可理解为虚拟化身&#xff09;、社交媒体化身和智能代理进行交互&#xff0c;这背后都需要底层技术支持。元宇宙的底层技术主要包括&#xff1a; VR/AR、5G/6G、区块链和人工智能。 VR/AR是元宇宙的主要交互设备…

JAVA新提案:努力简化Hello World写法

OpenJDK 的 JEP 445 提案正在努力简化 Java 的入门难度。这个提案主要是引入 “灵活的 Main 方法和匿名 Main 类” &#xff0c;希望 Java 的学习过程能更平滑&#xff0c;让学生和初学者能更好地接受 Java 。 提案的作者 Ron Pressler 解释&#xff1a;现在的 Java 语言非常适…

ES6-迭代器和生成器

一、迭代器概念 遍历器&#xff08; Iterator &#xff09;就是一种机制。它是一种接口&#xff0c;为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口&#xff0c;就可以完成遍历操作。 1) ES6 创造了一种新的遍历命令 for...of 循环&#…

虹科方案 | 助力高性能视频存储解决方案-2

上篇文章《虹科方案 | 助力高性能视频存储解决方案-1》我们分享了虹科&ATTO 和 Avid 共同创建协作解决方案&#xff0c;助力高性能视频存储&#xff0c;今天我们再深入介绍一下我们的案例详情。 一、行业挑战 从高端广播设施到小型独立工作室的媒体后期制作环境都需要允许多…

【C++】STL标准库之list

STL标准库之list list类的简介常用的list类的接口构造迭代器容量访问修改 list和vector的区别 list类的简介 list是一种序列式容器&#xff0c;可以在任意位置插入和删除元素&#xff0c;并且其时间复杂度为O(1)&#xff0c;在底层&#xff0c;list是双向链表结构&#xff0c;…

《CTFshow-Web入门》08. Web 71~80

Web 71~80 web71知识点题解 web72知识点题解 web73题解 web74题解 web75知识点题解 web76题解 web77知识点题解 web78知识点题解 web79题解 web80知识点题解 ctf - web入门 web71 知识点 ob_get_contents()&#xff1a;得到输出缓冲区的内容。ob_end_clean()&#xff1a;清除…

程序员:面试造飞机,入职拧螺丝?真难···

刚开始工作的时候&#xff0c;我也想不通这个问题&#xff0c;甚至很鄙视这种现象。后面当了面试官&#xff0c;做到了公司中层管理&#xff0c;也会站在公司以及行业角度去重新思考这个问题。 为什么这种现象会越来越普遍呢&#xff1f;尤其在 IT 行业愈加明显。 面试看的是…

树与二叉树

我们之前讲过的链表和顺序表都是线性结构的数据结构&#xff0c;那么我们肯定会想有没有一种数据结构的形式不是线性结构而是其他的形式呢&#xff1f;今天我们就来学习一种新的数据结构——树形结构。 &#x1f335;初识树形结构 树形结构就是像我们上面的图形一样。因为像是…

Java从入门到转行

Java开发从入门到转行 Java基本介绍Java学习路线Java学习须知Java学习文档Java SEJava 对象与类Java 基本数据类型Java 变量类型Java 修饰符Java 运算符Java 循环结构Java 条件语句Java switch caseJava 数组Java 日期与时间Java 正则表达式Java 方法Java 流(Stream)、 File、 …

A Restful API

SpringBoot 定义Restful API 定义POJOOrderBuyer 定义RestfulControllerGet API for queryPost API for addPut API for updateDelete API for delete 定义AjaxResponse Patavariable RequestParm RequestBodyRequestHeader 定义POJO Order import java.util.Date; import ja…

工厂方法模式

// 简单工厂模式 #include <iostream> #include <string>// 抽象产品类 class Product { public:virtual ~Product() {}virtual std::string getName() 0; };// 具体产品类A class ProductA : public Product { public:std::string getName() {return "Produ…

Swiper总结

文章目录 Swiper总结概述使用简单使用自动切换分页器样式切换效果预览视差效果延迟加载自适应高度放大缩小 案例tab切换引导页 Swiper总结 概述 Swiper是纯javascript打造的滑动特效插件&#xff0c;面向手机、平板电脑等移动终端。 Swiper能实现触屏焦点图、触屏Tab切换、触…

第三节课 Linux文件权限

Linux是多人多任务的操作系统&#xff0c;因此可能常常会有多人使用一台机器&#xff0c; 为了考虑每个人的隐私、方便用户合作&#xff0c;每个文件都有三类用户&#xff0c;权限是基于这三类用户设定的&#xff1a; 1) 文件拥有者&#xff08;user&#xff09; 2) 组用户&a…

SpringBoot 自定义注解实现Redis缓存功能

背景 最近小A的公司要做一个大屏可视化平台&#xff0c;主要是给领导看的&#xff0c;领导说这个项目要给领导演示&#xff0c;效果好不好直接关系到能不能拿下这个项目&#xff0c;领导还补了一句“这项目至少是百万级的&#xff0c;大伙要全力以赴”&#xff0c;早上小A还想…

走近大数据——什么是大数据、计算架构的发展

文章目录 一、什么是大数据二、大数据计算架构的发展1.RDBMS阶段2.Hadoop Map-Reduce阶段3.Spark阶段4.Flink阶段 参考 一、什么是大数据 大数据是指无法在有限时间内用常规软件工具对其进行获取、存储、管理和处理的数据集合。 大数据的特点&#xff1a; 海量化&#xff1a;数…

少年不懂孔乙己,读懂已是书中人

文章目录 前言梗从何来互联网文学背后的焦虑给学弟学妹的建议 前言 《孔乙己》是近代文学巨匠鲁迅所著的短篇小说。 大概故事讲的是孔乙己是站着喝酒而穿长衫的&#xff08;那时候穿长衫的人代表着有知识&#xff09;唯一人&#xff0c;穿的虽然是长衫&#xff0c;可是又脏又破…

SpringMVC概述

SpringMVC概述 1. SpringMVC概述1.1 SpringMVC概述 2. 入门案例【重点】2.1 实现步骤2.2 代码实现【第一步】创建web工程&#xff08;Maven结构&#xff09;【第二步】设置tomcat服务器&#xff0c;加载web工程【第三步】导入坐标&#xff08;SpringMVCServlet&#xff09;【第…