第二部分
LCD程序选择的是显示中英文字符串:
/**
* @brief 在 ILI9341 显示器上显示中英文字符串
* @param line :在特定扫描方向下字符串的起始Y坐标
* 本参数可使用宏LINE(0)、LINE(1)等方式指定文字坐标,
* 宏LINE(x)会根据当前选择的字体来计算Y坐标值。
* 显示中文且使用LINE宏时,需要把英文字体设置成Font8x16
* @param pStr :要显示的字符串的首地址
* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
* @retval 无
*/
显示内容为当前血氧,当前脉搏,Red_min,Red_max,Ir_min,Ir_max。因为采集频率为500Hz即2ms刷新一下,所以显示前需要清除之前的显示内容:
sprintf(dispBuff,"当前血氧: %6.2f",spo2);
LCD_ClearLine(LINE(3)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(3),dispBuff);
ir_led=Pulse;sprintf(dispBuff,"当前脉搏: %d",ir_led);
LCD_ClearLine(LINE(5)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(5),dispBuff);
显示部分差不多到这边,根据个人需求可以修改显示部分的程序,我用的是黑底红字。
然后就是算法部分了,原理大家都懂无非是两个公式:
(1)R=(float)((float)(I_red_ac)/(I_red_dc))/((float)(I_ir_ac)/(I_ir_dc))
(2)spo2=A-B*R
其中,公式2的A,B需要根据实际情况得到。这里我用的是A=113.5,B=8.7,经过数据记录会发现有超过100%的数值,这个需要剔除,因为范围是95%~98%。
在编程中还需要定义I_red_ac,I_red_dc,I_ir_ac,I_ir_dc
(3)I_red_ac=red_led_max-red_led_min;
I_red_dc=(red_led_max+red_led_min)/2;
I_ir_dc=(ir_led_max+ir_led_min)/2;
I_ir_ac=ir_led_max-ir_led_min;
血氧的算法基本是这样,最大值最小值的算法相信你们都会。还有就是编程中试过用冒泡算法与求平均值算法相结合来提高准确度。但是在测试两段程序都没错误的情况下,相结合的程序会有数据丢失的错误。具体表示为LCD上的数值一直跳动但小段时间内(6~7s)值不会变。这个问题我没解决的了,一直存在疑惑。
还有就是脉搏值的算法,我用的黑匣子,逼近数值。显示值在72附近跳动,真正的测量方法分频域和时域。我论文用的时域法,算法还有待进一步研究。目前只能提供一个例子(数波峰):
signal=H_ADC_GetValue(&hadc1); //记录采样值
samplingtime+=2;//每秒2ms采集一次每2ms采集一次,记录采集时间
num=samplingtime-lastbeattime;//num用来记录本次采样时间与上次心跳时间差
H_ADC_Start(&hadc1);//复位ACD转换
if (signal<thresh&&num>(IBI*3/5))//thresh为上次心跳记录的中间值thresh=(P-T)/2+T
if (signal<T)
T=signal;//T为波谷值
if (signal>thresh&&signal>P)
P=signal;//P即为波峰值
以上就是我提供的一些编写算法的思路,供大家参考。希望大家可以提出宝贵的意见,和改进的方法。