1.功能实现

本代码主要实现了日期星期和时间显示以及心率和血氧浓度的检测功能。

2.硬件连接

使用了MAX32600的一个SPI接口、一个I2C接口和一个UART接口。

1.14寸LCD屏引脚 板卡引脚
SCL P0_6
SDA P0_5
DC P0_12
CS P0_7
RES RSTN
VCC/GND 单独供电3.3V(防止屏幕供电对控制器USB供电影响)
MAX30100引脚
SCL P0_8
SDA P0_9
VCC/GND USB供电
时间校准
USB转TTL的TX P0_11
USB转TTL的RX P0_10

3.数据处理

时间显示代码

static void display_real_time(void)
{uint32_t ge, shi, bai, qian, tmp;uint8_t enum_tmp;r_time.sec = RTC_GetSecond();r_time.update.bit.usec = UPDATE_ENABLE;/* sec */tmp = r_time.sec + p_time.sec[1] * 10 + p_time.sec[0];if((tmp % 60) == 0){r_time.min = tmp / 60;r_time.update.bit.umin = UPDATE_ENABLE;}tmp %= 60;ge = tmp % 10;shi = tmp / 10;if(r_time.update.bit.usec){r_time.update.bit.usec = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W + 120, WATCH_H, shi, 1, WHITE, BLACK, 32);LCD_ShowIntNum(WATCH_W + 140, WATCH_H, ge, 1, WHITE, BLACK, 32);}/* min */tmp = r_time.min + p_time.min[1] * 10 + p_time.min[0];if((tmp % 60) == 0){r_time.hr = tmp / 60;r_time.update.bit.uhr = UPDATE_ENABLE;}tmp %= 60;ge = tmp % 10;shi = tmp / 10;if(r_time.update.bit.umin){r_time.update.bit.umin = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W + 60, WATCH_H, shi, 1, WHITE, BLACK, 32);LCD_ShowIntNum(WATCH_W + 80, WATCH_H, ge, 1, WHITE, BLACK, 32);LCD_ShowChar(WATCH_W + 100, WATCH_H - 2, ':', WHITE, BLACK, 32, 0);  }/* hr */tmp = r_time.hr + p_time.hr[1] * 10 + p_time.hr[0];if((tmp % 24) == 0){r_time.day = tmp / 24;r_time.update.bit.uday = UPDATE_ENABLE;}tmp %= 24;ge = tmp % 10;shi = tmp / 10;if(r_time.update.bit.uhr){r_time.update.bit.uhr = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W, WATCH_H, shi, 1, WHITE, BLACK, 32);LCD_ShowIntNum(WATCH_W + 20, WATCH_H, ge, 1, WHITE, BLACK, 32);LCD_ShowChar(WATCH_W + 40, WATCH_H - 2, ':', WHITE, BLACK, 32, 0);   }/* day */enum_tmp = (month_enum_t)(p_time.mon[1] * 10 + p_time.mon[0]);tmp = r_time.day + p_time.day[1]*10 + p_time.day[0];if(enum_tmp == JAN || enum_tmp == MAR || enum_tmp == MAY || enum_tmp == JUL || enum_tmp == AUG ||enum_tmp == OCT || enum_tmp == DEC){if((tmp % 31) == 0){r_time.mon = tmp / 31;r_time.update.bit.umon = UPDATE_ENABLE;}tmp %= 31;}else if(enum_tmp == APR || enum_tmp == JUN || enum_tmp == SEP || enum_tmp ==NOV){if((tmp % 30 == 0)){r_time.mon = tmp / 30;r_time.update.bit.umon = UPDATE_ENABLE;}tmp %= 30;}else{if((tmp % 28 == 0)){r_time.mon = tmp / 28;r_time.update.bit.umon = UPDATE_ENABLE;}tmp %= 28;}ge = tmp % 10;shi = tmp / 10;if(r_time.update.bit.uday){r_time.update.bit.uday = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W + 120, WATCH_H - 25, shi, 1, WHITE, BLACK, 24);LCD_ShowIntNum(WATCH_W + 135, WATCH_H - 25, ge, 1, WHITE, BLACK, 24);}/* mon */tmp = r_time.mon + p_time.mon[1]*10 + p_time.mon[0];if((tmp % 12) == 0){r_time.year = tmp / 12;r_time.update.bit.uyear = UPDATE_ENABLE;}tmp %= 12;ge = tmp % 10;shi = tmp / 10;if(r_time.update.bit.umon){r_time.update.bit.umon = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W + 75, WATCH_H - 25, shi, 1, WHITE, BLACK, 24);LCD_ShowIntNum(WATCH_W + 90, WATCH_H - 25, ge, 1, WHITE, BLACK, 24);LCD_ShowChar(WATCH_W + 105, WATCH_H - 20, '/', WHITE, BLACK, 16, 0);}/* year */tmp = r_time.year + p_time.year[3] * 1000 + p_time.year[2] * 100 + p_time.year[1] * 10 + p_time.year[0];ge = tmp % 10;shi = tmp / 10 % 10;bai = tmp / 100 % 10;qian = tmp / 1000 % 10;if(r_time.update.bit.uyear){r_time.update.bit.uyear = UPDATE_DISABLE;LCD_ShowIntNum(WATCH_W, WATCH_H - 25, qian, 1, WHITE, BLACK, 24);LCD_ShowIntNum(WATCH_W + 15, WATCH_H - 25, bai, 1, WHITE, BLACK, 24);LCD_ShowIntNum(WATCH_W + 30, WATCH_H - 25, shi, 1, WHITE, BLACK, 24);LCD_ShowIntNum(WATCH_W + 45, WATCH_H - 25, ge, 1, WHITE, BLACK, 24);LCD_ShowChar(WATCH_W + 60, WATCH_H - 20, '/', WHITE, BLACK, 16, 0);   }/* wday */enum_tmp = (wday_enum_t)p_time.wday;if(r_time.update.bit.uwday){r_time.update.bit.uwday = UPDATE_DISABLE;switch(enum_tmp){case SUN:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期天", WHITE, BLACK, 24, 0);break;case MON:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期一", WHITE, BLACK, 24, 0);break;case TUES:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期二", WHITE, BLACK, 24, 0);break;case WED:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期三", WHITE, BLACK, 24, 0);break;case THUR:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期四", WHITE, BLACK, 24, 0);break;case FRI:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期五", WHITE, BLACK, 24, 0);break;case SAT:LCD_ShowChinese(WATCH_W + 150, WATCH_H - 25, (uint8_t*)"星期六", WHITE, BLACK, 24, 0);break;default:break;}}}

时间校准代码

import serial
from datetime import datetimeser = serial.Serial("COM8", 115200, *timeout*=1)  # 这里有三个参数,第一个是连接的端口,第二个是波特率,第三个是超时时间
now = datetime.now() # 获取当前datetime
now_data = now.strftime('%Y-%m-%d %H:%M:%S %w')
print(now_data)
if ser.isOpen():print("串口已打开")
else:print("串口未打开")
# 测试
send_data = 0x01
# ser.write(send_data.encode())
print(now_data.encode())
# 发送数据
ser.write(now_data.encode())
ser.close()
if ser.isOpen():print ('串口未关闭')
else:print ('串口已关闭')

心率和血样检测代码

void blood_data_update(void)
{fifo_t raw_data;uint16_t temp_num = 0;char buf[100] = {0};uint8_t index = 0;temp_num = max30100_bus_read(INTERRUPT_STATUS_REG);//标志位被使能时 读取FIFOif(INTERRUPT_STATUS_REG_A_FULL & temp_num){//读取FIFOmax30100_fifo_readBytes(FIFO_DATA_REG, &raw_data, 1); //read the hr and spo2 data form fifo in reg=0x05
//      index = sprintf(buf, "%d", raw_data.rawIR);
//      print_data((uint8_t*)buf, index);/* 直流滤波 */blood.dcFilterIR = dcRemoval((float)raw_data.rawIR, blood.dcFilterIR.w, ALPHA);blood.dcFilterRed = dcRemoval((float)raw_data.rawRed, blood.dcFilterRed.w, ALPHA);
//      index = sprintf(buf, "%.6f", dcFilterIR.result);
//      print_data((uint8_t*)buf, index);/* 均值中值滤波 */float meanDiffResIR = meanDiff(blood.dcFilterIR.result, &blood.meanDiffIR);float meanDiffResRed = meanDiff(blood.dcFilterRed.result, &blood.meanDiffRed);
//      index = sprintf(buf, "%.6f", meanDiffResIR);
//      print_data((uint8_t*)buf, index);/* 巴特沃斯过滤器 */lowPassButterworthFilter(meanDiffResIR, &blood.lpbFilterIR);lowPassButterworthFilter(meanDiffResRed, &blood.lpbFilterRed);blood.irACValueSqSum += blood.dcFilterIR.result * blood.dcFilterIR.result;blood.redACValueSqSum += blood.dcFilterRed.result * blood.dcFilterRed.result;
//      index = sprintf(buf, "%.6f", blood.lpbFilterIR.result);
//      buf[index] = ',';
//      index += 1;
//      index += sprintf(&buf[index], "%.6f", blood.lpbFilterRed.result);
//      print_data((uint8_t*)buf, index);blood.samplesRecorded++;/* 心跳脉冲检测 */if(detectPulse(blood.lpbFilterIR.result)){blood.updateDisplay = BLOOD_UPDATE_DISPLAY_ENABLE;blood.pulsesDetected++;float red_log_rms = log(sqrt(blood.redACValueSqSum / blood.samplesRecorded));float ir_log_rms = log(sqrt(blood.irACValueSqSum / blood.samplesRecorded) );float ratioRMS = 0.0f;if(red_log_rms != 0.0f && ir_log_rms != 0.0f){ratioRMS = red_log_rms / ir_log_rms;}blood.currentSaO2Value = 110.0f - 14.0f * ratioRMS;   // SPo2 value by pulse-rate
//          index = sprintf(buf, "%.6f", blood.currentSaO2Value);
//          print_data((uint8_t*)buf, index);if(blood.pulsesDetected % RESET_SPO2_EVERY_N_PULSES == 0){blood.irACValueSqSum = 0;blood.redACValueSqSum = 0;blood.samplesRecorded = 0;} } balanceIntesities(blood.dcFilterRed.w, blood.dcFilterIR.w);}
}

4.心得体会

这次活动,第一让我对SPI、I2C以及UART又复习一遍,对照手册的说明,了解这些接口还有其它许多功能是我以前是没有使用过的,这次借此机会重新对这些接口有了更深认识。平时使用意法半导体开发都是使用STM32CUBEMX一键生成,省去很多偏向底层的东西,但美信半导体MAX32660控制器让我重新复习一遍底层知识。第二点是使用了美信半导体MAX30100传感器来检测心率和血氧浓度,数据处理对我种小白来说还挺难的,也不知道如何去处理这些数据,最后参考网上一篇博文,并用串口工具VOFA+去显示波形来直观分析数据,血氧浓度检测还行,但心跳检测欠佳。

最后,感谢硬禾学堂和得捷电子,让我接触到了美信半导体的开发板,让我能在空余时间能更多参与有趣项目学习,也感谢群的小伙伴提供很多种实现题目功能的思路,感谢大家一路的折腾与陪伴,谢谢!

Funpack第六期-基于MAX32660-EVSYS具有心率和血氧检测智能手环相关推荐

  1. 基于51单片机的心率脉搏计检测系统

    1.功能原理 脉搏传感器采样脉搏信号,采用STC89C51单片机作为控制器,脉搏传感器输出方波传入单片机,触发单片机进去外部中断函数,每接收一个脉冲波形,显示屏就计数一次.如果脉搏次数超过设定值是,用 ...

  2. 计算机系统应用的书,基于领域本体与上下文感知计算的智能图书-计算机系统应用.PDF...

    计 算 机 系 统 应 用 2015 年 第 24 卷 第 5 期 基于领域本体与上下文感知计算的智能图书① 张文博, 张 霞 (武汉大学 印刷与包装系, 武汉 430079) 摘 要: 随着信息化时 ...

  3. 飞谷云六期第三组——基于Spark的机器学习

    项目正式开始时间:2015.10.15. 随笔内容:本次项目的主题是基于Spark的ML.对于ML的学习有大概半年了,正好在网上关注到了由上海交通大学所主办的这个飞谷云的大数据项目,我所报名的这期已经 ...

  4. 第六期 自定义IP添加-PWM 基于ARTY A7的MicroBlaze系统搭建与应用

    第六期 自定义IP添加-PWM 基于ARTY A7的MicroBlaze系统搭建与应用 说明 演示:在软核中添加自定义的ip bd文件的编辑 vitis文件 说明 直接在cpu中添加p产生pwm的IP ...

  5. 2019微生物组—宏基因组分析技术研讨会第六期

    在广大粉丝的期待下,<生信宝典>联合<宏基因组>在2019年11月1-3日,北京鼓楼推出<宏基因组分析>专题培训第六期,为大家提供一条走进生信大门的捷径.为同行提供 ...

  6. 王建民做客第六期青年学者月度沙龙 分享工业软件的开源创新发展模式

    3月25日,第六期清华大学青年学者月度沙龙在教师发展中心举办,软件学院院长.大数据研究中心副主任王建民作为主讲嘉宾,作了题为"工业软件与开源创新"的主旨报告,来自全校多个单位的40 ...

  7. 【第六期】拿不到offer全额退款 人工智能工程师培养计划招生

    前 言 学院第四期课程在2019年10月结课,第一至第四期具有求职意向的同学中,目前已经有80%的同学拿到了国内外名企的AI算法岗位offer,或者国外名校的AI 硕士.全奖博士录取 offer.在大 ...

  8. 【第六期】拿不到offer全额退款 !人工智能工程师培养计划招生

    前 言 学院第四期课程在2019年10月结课,第一至第四期具有求职意向的同学中,目前已经有80%的同学拿到了国内外名企的AI算法岗位offer,或者国外名校的AI 硕士.全奖博士录取 offer.在大 ...

  9. 阿里云MVP第六期发布——覆盖全球20多个国家和地区,成为数字化转型的中坚力量...

    9月27日,阿里云MVP(最有价值专家)第六期发布.截止本期,全球已有20多个国家和地区,300余位云计算专家成为阿里云MVP. 2017 年 6 月,阿里云总裁胡晓明在上海云栖大会上发布了阿里云MV ...

最新文章

  1. Shell脚本应用(五)if语句
  2. java jsp中的日历表_JAVA简单的日历程序
  3. java oca_OCA第5部分中的Java难题
  4. cs106a编程方法学作业解答(3)
  5. 机器学习朴素贝叶斯算法_机器学习中的朴素贝叶斯算法
  6. 草稿 datagridview的显示与修改
  7. 三星堆的青铜机器人_三星堆“青铜纵目人像”到底仿照谁的相貌?专家终于讲出真相...
  8. 【报告分享】科技产业2021年投资策略:科技进步与中美再平衡下的新机遇.pdf(附下载链接)...
  9. 示例演示公告通知标题无缝向上滚动,文字段落无缝向上滚动,简单的wangeditor富文本编辑器,简单的音乐播放demo...
  10. 单链表的归并算法思路总结
  11. 【Shiro第八篇】SpringBoot + Shiro使用Shiro标签
  12. CCNA 视频教程下载 -chinalab版
  13. java 面单模板_顺丰电子面单JSON请求格式
  14. 【Android】实现应用简单的用户登录界面
  15. r语言和python的区别-r语言和python的详细对比
  16. 用c语言软件制作监察病毒,弄了个病毒。用的是C语言,大家看看!
  17. 2021-11-24【数据结构练习题】【二叉搜索树的插入删除】
  18. 《乔布斯的魔力演讲》读书笔记
  19. 小武与FasterRCNN
  20. 华为防火墙及它的工作原理

热门文章

  1. # Ajax提交Form表单以及后端取值(java)
  2. 正三角形孔的机构原理及运动仿真
  3. 【Python知识点梳理】8.飞机大战(面向对象设计思维)
  4. js jquery 获取元素(父节点,子节点,兄弟节点)
  5. 适用于C/C++开发人员的HOOPS
  6. linux ssh快捷登录服务器
  7. systemctl 启动redis
  8. 微信小程序警告之Do not have regionchange handler in component: pages/maps/maps.
  9. 取得手机通话历史记录
  10. 聚财云库团队给大家分享这些年经历的网赚时代