目录
五、中断处理
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);//关
}
}