{"id":94910,"date":"2026-08-15T18:25:28","date_gmt":"2026-08-15T10:25:28","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/94910.html"},"modified":"2026-08-15T18:25:28","modified_gmt":"2026-08-15T10:25:28","slug":"stm32f103%e9%a9%b1%e5%8a%a8max30102%e8%a1%80%e6%b0%a7%e5%bf%83%e7%8e%87%e6%a3%80%e6%b5%8b%e5%ae%8c%e6%95%b4%e6%95%99%e7%a8%8b%ef%bc%88%e5%90%aboled%e6%98%be%e7%a4%ba%e3%80%81%e8%bd%af%e4%bb%b6i2c","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/94910.html","title":{"rendered":"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09"},"content":{"rendered":"<h3>\u524d\u8a00<\/h3>\n<p>\u672c\u7bc7\u57fa\u4e8e STM32F103C8T6 \u4e3b\u63a7\u642d\u914d MAX30102 \u5149\u7535\u8840\u6c27\u5fc3\u7387\u4f20\u611f\u5668\u30010.96 \u5bf8 I2C OLED \u663e\u793a\u5c4f\u5b8c\u6210\u6574\u5957\u8109\u640f\u8840\u6c27\u91c7\u96c6\u5de5\u7a0b&#xff0c;\u5168\u7a0b\u4f7f\u7528\u8f6f\u4ef6 I2C \u901a\u4fe1&#xff0c;\u5206\u5f00\u4e24\u8def I2C \u603b\u7ebf\u5206\u522b\u9a71\u52a8\u4f20\u611f\u5668\u4e0e\u5c4f\u5e55&#xff0c;\u89c4\u907f\u603b\u7ebf\u51b2\u7a81\u95ee\u9898\u3002\u6587\u7ae0\u5b8c\u6574\u62c6\u89e3\u786c\u4ef6\u63a5\u7ebf\u3001\u5149\u5b66\u68c0\u6d4b\u539f\u7406\u3001\u5bc4\u5b58\u5668\u914d\u7f6e\u3001FIFO \u6570\u636e\u8bfb\u53d6\u3001\u5fc3\u7387\u8840\u6c27\u7b97\u6cd5\u3001\u5b9e\u7269\u8c03\u8bd5\u3001\u5b8c\u6574\u6e90\u7801\u6a21\u5757&#xff0c;\u9002\u5408\u5d4c\u5165\u5f0f\u521d\u5b66\u8005\u3001\u8bfe\u7a0b\u8bbe\u8ba1\u3001\u7535\u5b50\u7ade\u8d5b\u76f4\u63a5\u53c2\u8003\u3002<\/p>\n<p>\u91cd\u8981\u8bf4\u660e&#xff1a;\u672c\u65b9\u6848\u4ec5\u4f5c\u6559\u5b66\u6f14\u793a\u4f7f\u7528&#xff0c;\u672a\u7ecf\u8fc7\u533b\u7597\u7ea7\u4e34\u5e8a\u6807\u5b9a&#xff0c;\u6d4b\u91cf\u6570\u503c\u4ec5\u7528\u4e8e\u5b66\u4e60\u4fe1\u53f7\u5904\u7406\u903b\u8f91&#xff0c;\u4e0d\u53ef\u4f5c\u4e3a\u533b\u7597\u8bca\u65ad\u4f9d\u636e\u3002<\/p>\n<p>\u89c6\u9891\u8bb2\u89e3&#xff1a;<span class=\"link-card-box\"><span class=\"link-title\">STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b&#xff08;\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801&#xff09;<\/span><span class=\"link-link\"><img decoding=\"async\" class=\"link-link-icon\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e962a257.png\" \/>https:\/\/www.bilibili.com\/video\/BV11Vbk6vE3Y\/?share_source&#061;copy_web&amp;vd_source&#061;91b967b41a17a5686913521545a8c3fb<\/span><\/span><\/p>\n<h3>\u4e00\u3001\u6574\u4f53\u5b9e\u73b0\u6d41\u7a0b<\/h3>\n<li>\u5fc3\u810f\u640f\u52a8\u9020\u6210\u624b\u6307\u672b\u68a2\u52a8\u8109\u8840\u6db2\u5bb9\u79ef\u5468\u671f\u6027\u53d8\u5316&#xff1b;<\/li>\n<li>MAX30102 \u5185\u90e8\u7ea2\u5149&#xff08;660nm&#xff09;\u3001\u7ea2\u5916\u5149&#xff08;880nm&#xff09;LED \u4ea4\u66ff\u7167\u5c04\u624b\u6307&#xff1b;<\/li>\n<li>\u5149\u7535\u4e8c\u6781\u7ba1\u63a5\u6536\u7ec4\u7ec7\u53cd\u5c04\u5149&#xff0c;\u8f6c\u5316\u4e3a\u5fae\u5f31\u7535\u6d41&#xff1b;<\/li>\n<li>\u7247\u5185\u6a21\u62df\u524d\u7aef\u6291\u5236\u73af\u5883\u5149\u5e72\u6270&#xff0c;18 \u4f4d ADC \u5c06\u5149\u4fe1\u53f7\u8f6c\u4e3a\u6570\u5b57\u91cf&#xff1b;<\/li>\n<li>\u7ea2\u5149\u3001\u7ea2\u5916\u6210\u5bf9\u6837\u672c\u5b58\u5165\u82af\u7247\u5185\u90e8 32 \u7ec4 FIFO \u7f13\u5b58&#xff1b;<\/li>\n<li>STM32 \u901a\u8fc7\u8f6f\u4ef6 I2C \u8f6e\u8be2\u8bfb\u53d6 FIFO \u539f\u59cb\u6570\u636e&#xff1b;<\/li>\n<li>\u8f6f\u4ef6\u53bb\u9664\u6ce2\u5f62\u76f4\u6d41\u57fa\u7ebf\u3001\u8bc6\u522b\u8109\u640f\u5cf0\u503c&#xff0c;\u901a\u8fc7\u53cc\u5149\u6bd4\u503c\u8ba1\u7b97\u8840\u6c27\u3001\u5cf0\u95f4\u9694\u8ba1\u7b97\u5fc3\u7387&#xff1b;<\/li>\n<li>\u5b9e\u65f6\u5728 OLED \u5c4f\u5e55\u6253\u5370\u7ea2\u5916\u539f\u59cb\u91c7\u6837\u503c\u3001\u5fc3\u7387\u3001\u8840\u6c27\u4ee5\u53ca\u8bbe\u5907\u5de5\u4f5c\u72b6\u6001\u3002\n<p class=\"img-center\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"398\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e967a36b.png\" width=\"728\" \/><\/p>\n<\/li>\n<h3>\u4e8c\u3001\u786c\u4ef6\u7535\u8def\u63a5\u7ebf\u8bf4\u660e<\/h3>\n<h4>2.1 \u5f15\u811a\u5bf9\u5e94\u8868<\/h4>\n<h5>MAX30102 \u4f20\u611f\u5668\u63a5\u7ebf<\/h5>\n<table>\n<tr>MAX30102 \u5f15\u811aSTM32F103 \u5f15\u811a\u529f\u80fd\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>SCL<\/td>\n<td>PB6<\/td>\n<td>\u4f20\u611f\u5668\u8f6f\u4ef6 I2C \u65f6\u949f<\/td>\n<\/tr>\n<tr>\n<td>SDA<\/td>\n<td>PB7<\/td>\n<td>\u4f20\u611f\u5668\u8f6f\u4ef6 I2C \u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>INT<\/td>\n<td>\u60ac\u7a7a<\/td>\n<td>\u5de5\u7a0b\u91c7\u7528\u8f6e\u8be2\u65b9\u5f0f\u8bfb\u53d6\u6570\u636e&#xff0c;\u672a\u4f7f\u7528\u4e2d\u65ad\u5f15\u811a<\/td>\n<\/tr>\n<tr>\n<td>VCC<\/td>\n<td>3.3V<\/td>\n<td>\u6a21\u5757\u4f9b\u7535&#xff0c;\u4e25\u7981 5V \u76f4\u4f9b<\/td>\n<\/tr>\n<tr>\n<td>GND<\/td>\n<td>GND<\/td>\n<td>\u4e3b\u63a7\u4e0e\u4f20\u611f\u5668\u5171\u5730&#xff0c;\u4fdd\u8bc1\u901a\u4fe1\u7a33\u5b9a<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"img-center\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"495\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e96949cb.jpg\" width=\"945\" \/><\/p>\n<h5>OLED \u663e\u793a\u5c4f\u63a5\u7ebf<\/h5>\n<table>\n<tr>OLED \u5f15\u811aSTM32F103 \u5f15\u811a\u529f\u80fd\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>SCL<\/td>\n<td>PB8<\/td>\n<td>\u5c4f\u5e55\u72ec\u7acb\u8f6f\u4ef6 I2C \u65f6\u949f<\/td>\n<\/tr>\n<tr>\n<td>SDA<\/td>\n<td>PB9<\/td>\n<td>\u5c4f\u5e55\u72ec\u7acb\u8f6f\u4ef6 I2C \u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>VCC<\/td>\n<td>3.3V<\/td>\n<td>\u663e\u793a\u5c4f\u4f9b\u7535<\/td>\n<\/tr>\n<tr>\n<td>GND<\/td>\n<td>GND<\/td>\n<td>\u5171\u5730\u5904\u7406<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>2.2 \u4e24\u8def\u72ec\u7acb\u8f6f\u4ef6 I2C \u8bbe\u8ba1\u4f18\u52bf<\/h4>\n<p>MAX30102 \u4e0e OLED \u90fd\u91c7\u7528 I2C \u901a\u4fe1&#xff0c;\u4f46\u5de5\u7a0b\u5206\u5f00\u4e24\u5957\u5f15\u811a\u505a\u72ec\u7acb\u8f6f\u4ef6 I2C&#xff1a;<\/p>\n<ul>\n<li>\u4f20\u611f\u5668&#xff1a;PB6 (SCL)\u3001PB7 (SDA)<\/li>\n<li>\u663e\u793a\u5c4f&#xff1a;PB8 (SCL)\u3001PB9 (SDA)<\/li>\n<\/ul>\n<p>\u4f18\u52bf&#xff1a;<\/p>\n<li>\u5237\u65b0 OLED \u5c4f\u5e55\u65f6\u4e0d\u4f1a\u5e72\u6270 MAX30102 \u4f20\u611f\u5668\u603b\u7ebf&#xff0c;\u907f\u514d\u91c7\u6837\u4e22\u6570&#xff1b;<\/li>\n<li>\u5355\u8bbe\u5907\u901a\u4fe1\u6545\u969c\u4e0d\u4f1a\u7275\u8fde\u53e6\u4e00\u8def\u603b\u7ebf&#xff0c;\u8c03\u8bd5\u6545\u969c\u66f4\u5bb9\u6613\u5b9a\u4f4d&#xff1b;<\/li>\n<li>\u6559\u5b66\u573a\u666f\u53ef\u4ee5\u5355\u72ec\u65ad\u5f00\u4e00\u8def\u8bbe\u5907&#xff0c;\u5206\u522b\u6d4b\u8bd5\u4f20\u611f\u5668\u4e0e\u5c4f\u5e55\u529f\u80fd\u3002<\/li>\n<h4>2.3 \u4f9b\u7535\u4e0e\u4e0a\u62c9\u7535\u963b\u6ce8\u610f\u4e8b\u9879<\/h4>\n<li>MAX30102 \u88f8\u7247\u5185\u90e8\u6570\u5b57\u7535\u8def\u5de5\u4f5c 1.8V&#xff0c;\u5e02\u9762\u4e0a\u6210\u54c1\u4e94\u9488\u6a21\u5757\u5df2\u7ecf\u96c6\u6210\u7a33\u538b\u7535\u8def&#xff0c;\u76f4\u63a5 3.3V \u4f9b\u7535\u5373\u53ef&#xff1b;<\/li>\n<li>\u82e5\u8d2d\u4e70\u65e0\u677f\u8f7d\u4e0a\u62c9\u7535\u963b\u7684\u88f8\u6a21\u5757&#xff0c;SCL\u3001SDA \u5f15\u811a\u9700\u8981\u5916\u63a5 4.7k\u03a9 \u7535\u963b\u4e0a\u62c9\u81f3 3.3V&#xff1b;<\/li>\n<li>\u7a0b\u5e8f\u5f00\u542f STM32 \u5bf9\u5e94 GPIO \u5185\u90e8\u4e0a\u62c9&#xff0c;\u8fdb\u4e00\u6b65\u63d0\u5347\u5b9e\u9a8c\u5ba4\u9762\u5305\u677f\u63a5\u7ebf\u7a33\u5b9a\u6027&#xff1b;<\/li>\n<li>\u6240\u6709\u5916\u8bbe\u5fc5\u987b\u4e0e\u4e3b\u63a7\u5171\u5730&#xff0c;\u5426\u5219\u4f1a\u51fa\u73b0 I2C \u8bfb\u5199\u51fa\u9519\u3001\u6570\u503c\u8df3\u53d8\u4e25\u91cd\u95ee\u9898&#xff1b;<\/li>\n<li>\u7981\u6b62\u7ed9\u6a21\u5757\u63a5\u5165 5V \u7535\u538b&#xff0c;\u4f1a\u76f4\u63a5\u70e7\u6bc1\u4f20\u611f\u5668\u82af\u7247\u3002<\/li>\n<h3>\u4e09\u3001MAX30102 \u5149\u5b66\u68c0\u6d4b\u6838\u5fc3\u539f\u7406<\/h3>\n<p>\u672c\u4f20\u611f\u5668\u91c7\u7528\u53cd\u5c04\u5f0f PPG \u5149\u7535\u5bb9\u79ef\u8109\u640f\u6ce2\u68c0\u6d4b\u6cd5&#xff0c;\u4f9d\u9760\u4e24\u79cd\u6ce2\u957f\u5149\u7ebf\u533a\u5206\u5fc3\u7387\u4e0e\u8840\u6c27\u3002<\/p>\n<h4>3.1 \u5fc3\u7387\u68c0\u6d4b\u539f\u7406<\/h4>\n<p>\u5fc3\u810f\u6536\u7f29\u65f6\u624b\u6307\u52a8\u8109\u8840\u6d41\u91cf\u53d8\u5927&#xff0c;\u8212\u5f20\u65f6\u8840\u6d41\u91cf\u51cf\u5c0f&#xff0c;\u8840\u6db2\u591a\u5c11\u4f1a\u6539\u53d8\u5149\u7ebf\u5438\u6536\u3001\u53cd\u5c04\u5f3a\u5ea6&#xff0c;\u5149\u7535\u4e8c\u6781\u7ba1\u8f93\u51fa\u6ce2\u5f62\u4f1a\u5e26\u6709\u548c\u5fc3\u8df3\u540c\u6b65\u7684\u5468\u671f\u6027\u6ce2\u52a8\u3002 \u6ce2\u5f62\u5206\u4e3a\u4e24\u90e8\u5206&#xff1a;<\/p>\n<li>DC \u76f4\u6d41\u5206\u91cf&#xff1a;\u76ae\u80a4\u3001\u808c\u8089\u3001\u9759\u8109\u8840\u5f62\u6210\u7684\u57fa\u7840\u57fa\u7ebf&#xff0c;\u53d8\u5316\u901f\u5ea6\u7f13\u6162&#xff1b;<\/li>\n<li>AC \u4ea4\u6d41\u5206\u91cf&#xff1a;\u5fc3\u8df3\u5e26\u6765\u7684\u8840\u6d41\u6ce2\u52a8&#xff0c;\u662f\u8ba1\u7b97\u5fc3\u7387\u7684\u6709\u6548\u4fe1\u53f7\u3002<\/li>\n<p>\u8f6f\u4ef6\u5148\u6ee4\u9664\u7f13\u6162\u53d8\u5316\u7684 DC \u57fa\u7ebf&#xff0c;\u518d\u8bc6\u522b\u6ce2\u5f62\u5cf0\u503c\u3002 \u672c\u5de5\u7a0b\u91c7\u6837\u7387\u56fa\u5b9a 100Hz&#xff0c;\u5fc3\u7387\u8ba1\u7b97\u516c\u5f0f&#xff1a; HR &#061; 6000 \/ N N \u4e3a\u76f8\u90bb\u8109\u640f\u5cf0\u4e4b\u95f4\u7684\u5e73\u5747\u91c7\u6837\u70b9\u6570&#xff0c;\u4e3e\u4f8b&#xff1a;\u5cf0\u95f4\u9694 80 \u4e2a\u91c7\u6837\u70b9&#xff0c;\u5fc3\u7387 &#061; 6000\/80&#061;75 \u6b21 \/ \u5206\u949f\u3002<\/p>\n<h4>3.2 \u8840\u6c27\u68c0\u6d4b\u539f\u7406<\/h4>\n<p>\u542b\u6c27\u8840\u7ea2\u86cb\u767d\u3001\u8131\u6c27\u8840\u7ea2\u86cb\u767d\u5bf9\u7ea2\u5149\u3001\u7ea2\u5916\u5149\u5438\u6536\u7cfb\u6570\u5dee\u5f02\u5de8\u5927&#xff0c;\u901a\u8fc7\u4e24\u8def\u5149\u6ce2\u5f62\u6bd4\u503c\u4f30\u7b97\u8840\u6c27\u9971\u548c\u5ea6\u3002<\/p>\n<li>\u5206\u522b\u63d0\u53d6\u7ea2\u5149\u3001\u7ea2\u5916\u6ce2\u5f62\u7684 AC \u4ea4\u6d41\u5206\u91cf\u3001DC \u76f4\u6d41\u57fa\u7ebf&#xff1b;<\/li>\n<li>\u8ba1\u7b97\u5f52\u4e00\u5316\u8109\u52a8\u6bd4\u503c R &#061; (\u7ea2\u5149 AC \/ \u7ea2\u5149 DC) \u00f7 (\u7ea2\u5916 AC \/ \u7ea2\u5916 DC)&#xff1b;<\/li>\n<li>\u91c7\u7528\u6559\u5b66\u9002\u7528\u7ecf\u9a8c\u516c\u5f0f\u4f30\u7b97\u8840\u6c27&#xff1a;SpO2 \u2248 -45.06\u00d7R\u00b2 &#043; 30.354\u00d7R &#043; 94.845&#xff1b;<\/li>\n<li>STM32 \u91c7\u7528\u5b9a\u70b9\u6574\u6570\u8fd0\u7b97\u5b9e\u73b0\u516c\u5f0f&#xff0c;\u89c4\u907f Cortex-M3 \u5185\u6838\u6d6e\u70b9\u5e93\u5360\u7528\u8d44\u6e90\u8fc7\u5927\u95ee\u9898\u3002<\/li>\n<h3>\u56db\u3001I2C \u901a\u4fe1\u3001\u5bc4\u5b58\u5668\u4e0e FIFO \u7f13\u5b58\u673a\u5236<\/h3>\n<h4>4.1 I2C \u8bbe\u5907\u5730\u5740<\/h4>\n<p>MAX30102 7 \u4f4d\u8bbe\u5907\u5730\u5740 0x57&#xff1b;\u5199\u64cd\u4f5c\u5730\u5740 0xAE&#xff0c;\u8bfb\u64cd\u4f5c\u5730\u5740 0xAF\u3002<\/p>\n<h4>4.2 \u5de5\u7a0b\u6838\u5fc3\u5bc4\u5b58\u5668\u914d\u7f6e\u8bf4\u660e<\/h4>\n<table>\n<tr>\u5bc4\u5b58\u5668\u5730\u5740\u5bc4\u5b58\u5668\u540d\u79f0\u5de5\u7a0b\u914d\u7f6e\u4e0e\u4f5c\u7528<\/tr>\n<tbody>\n<tr>\n<td>0x00<\/td>\n<td>INTR_STATUS_1<\/td>\n<td>\u8bfb\u53d6 PPG_RDY \u6807\u5fd7&#xff0c;\u5224\u65ad\u662f\u5426\u4ea7\u751f\u65b0\u91c7\u6837\u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>0x02<\/td>\n<td>INTR_ENABLE_1<\/td>\n<td>\u5199\u5165 0x40&#xff0c;\u5f00\u542f\u65b0\u6837\u672c\u5c31\u7eea\u72b6\u6001\u6807\u5fd7<\/td>\n<\/tr>\n<tr>\n<td>0x04<\/td>\n<td>FIFO_WR_PTR<\/td>\n<td>FIFO \u5199\u6307\u9488&#xff0c;\u8bb0\u5f55\u82af\u7247\u5b58\u5165\u6570\u636e\u4f4d\u7f6e<\/td>\n<\/tr>\n<tr>\n<td>0x05<\/td>\n<td>OVF_COUNTER<\/td>\n<td>FIFO \u6ea2\u51fa\u8ba1\u6570&#xff0c;\u9632\u6b62\u6570\u636e\u4e22\u5931<\/td>\n<\/tr>\n<tr>\n<td>0x06<\/td>\n<td>FIFO_RD_PTR<\/td>\n<td>FIFO \u8bfb\u6307\u9488&#xff0c;\u8bb0\u5f55 MCU \u8bfb\u53d6\u6570\u636e\u4f4d\u7f6e<\/td>\n<\/tr>\n<tr>\n<td>0x07<\/td>\n<td>FIFO_DATA<\/td>\n<td>\u8fde\u7eed\u8bfb\u53d6\u4e00\u7ec4\u7ea2\u5149 &#043; \u7ea2\u5916 18 \u4f4d\u91c7\u6837\u539f\u59cb\u503c<\/td>\n<\/tr>\n<tr>\n<td>0x08<\/td>\n<td>FIFO_CONFIG<\/td>\n<td>\u914d\u7f6e\u503c 0x0F&#xff0c;\u8bbe\u7f6e FIFO \u7f13\u5b58\u53c2\u6570<\/td>\n<\/tr>\n<tr>\n<td>0x09<\/td>\n<td>MODE_CONFIG<\/td>\n<td>\u914d\u7f6e\u503c 0x03&#xff0c;\u5f00\u542f\u8840\u6c27\u53cc\u5149\u68c0\u6d4b\u6a21\u5f0f<\/td>\n<\/tr>\n<tr>\n<td>0x0A<\/td>\n<td>SPO2_CONFIG<\/td>\n<td>\u914d\u7f6e\u503c 0x27&#xff0c;4096nA \u7535\u6d41\u3001100Hz \u91c7\u6837\u300118 \u4f4d\u91c7\u6837\u7cbe\u5ea6<\/td>\n<\/tr>\n<tr>\n<td>0x0C<\/td>\n<td>LED1_PA<\/td>\n<td>\u7ea2\u5149 LED \u9a71\u52a8\u7535\u6d41\u8bbe\u7f6e 0x24<\/td>\n<\/tr>\n<tr>\n<td>0x0D<\/td>\n<td>LED2_PA<\/td>\n<td>\u7ea2\u5916 LED \u9a71\u52a8\u7535\u6d41\u8bbe\u7f6e 0x24<\/td>\n<\/tr>\n<tr>\n<td>0xFF<\/td>\n<td>PART_ID<\/td>\n<td>\u8bfb\u53d6\u82af\u7247 ID 0x15&#xff0c;\u7528\u4e8e\u786c\u4ef6\u5728\u7ebf\u68c0\u6d4b<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>4.3 FIFO \u6570\u636e\u5b58\u50a8\u683c\u5f0f<\/h4>\n<p>\u8840\u6c27\u6a21\u5f0f\u4e0b&#xff0c;\u4e00\u7ec4\u5b8c\u6574\u91c7\u6837\u6570\u636e\u5360\u7528 6 \u5b57\u8282&#xff1a; \u5b57\u8282 0~2&#xff1a;\u7ea2\u5149 18 \u4f4d\u539f\u59cb\u6570\u636e \u5b57\u8282 3~5&#xff1a;\u7ea2\u5916\u5149 18 \u4f4d\u539f\u59cb\u6570\u636e \u6570\u636e\u63d0\u53d6\u65b9\u5f0f&#xff1a; RED &#061; ((B0 &lt;&lt; 16) | (B1 &lt;&lt; 8) | B2) &amp; 0x03FFFF IR &#061; ((B3 &lt;&lt; 16) | (B4 &lt;&lt; 8) | B5) &amp; 0x03FFFF 18 \u4f4d\u91c7\u6837\u6570\u503c\u8303\u56f4&#xff1a;0 ~ 262143&#xff1b;\u82af\u7247\u5185\u7f6e 32 \u7ec4 FIFO \u7f13\u5b58&#xff0c;MCU \u5237\u65b0\u5c4f\u5e55\u77ed\u6682\u963b\u585e\u65f6&#xff0c;\u4e0d\u4f1a\u4e22\u5931\u91c7\u6837\u6570\u636e\u3002<\/p>\n<h4>4.4 FIFO \u6570\u636e\u8bfb\u53d6\u903b\u8f91<\/h4>\n<p>\u7a0b\u5e8f\u540c\u65f6\u8bfb\u53d6 FIFO \u8bfb\u5199\u6307\u9488\u5dee\u503c\u4e0e PPG \u5c31\u7eea\u4e2d\u65ad\u6807\u5fd7&#xff1a; \u4ec5\u5bf9\u6bd4\u6307\u9488\u4f1a\u51fa\u73b0 \u201c\u7f13\u5b58\u5df2\u6ee1\u65f6\u8bfb\u5199\u6307\u9488\u91cd\u5408&#xff0c;\u8bef\u5224\u4e3a\u7a7a\u7f13\u5b58\u201d \u95ee\u9898&#xff1b;\u7ed3\u5408\u6ea2\u51fa\u8ba1\u6570\u3001\u5c31\u7eea\u6807\u5fd7\u53cc\u91cd\u5224\u65ad&#xff0c;\u6d88\u9664\u6570\u636e\u8bfb\u53d6\u6b67\u4e49\u3002<\/p>\n<h3 style=\"background-color:transparent\">\u4e94\u3001\u6570\u636e\u91c7\u6837\u4e0e\u7b97\u6cd5\u5b8c\u6574\u5904\u7406\u903b\u8f91<\/h3>\n<li>\u8f6e\u8be2\u8bfb\u53d6\u72b6\u6001\u5bc4\u5b58\u5668\u3001FIFO \u8bfb\u5199\u6307\u9488&#xff0c;\u5224\u65ad\u662f\u5426\u5b58\u5728\u672a\u8bfb\u53d6\u6837\u672c&#xff1b;<\/li>\n<li>\u5b58\u5728\u65b0\u6570\u636e\u5219\u8fde\u7eed\u8bfb\u53d6\u4e00\u7ec4\u7ea2\u5149\u3001\u7ea2\u5916\u539f\u59cb\u91c7\u6837\u503c&#xff1b;<\/li>\n<li>\u5224\u65ad\u7ea2\u5916\u6570\u503c\u662f\u5426\u8fbe\u5230\u624b\u6307\u68c0\u6d4b\u9608\u503c&#xff0c;\u6570\u503c\u8fc7\u4f4e\u5224\u5b9a\u65e0\u624b\u6307\u63a5\u89e6&#xff1b;<\/li>\n<li>\u6709\u6548\u91c7\u6837\u5b58\u5165 400 \u70b9\u6ed1\u52a8\u6ce2\u5f62\u7a97\u53e3&#xff08;\u5bf9\u5e94 4 \u79d2\u6ce2\u5f62\u6570\u636e&#xff09;&#xff1b;<\/li>\n<li>\u91c7\u96c6\u6ee1 400 \u70b9\u540e\u6267\u884c\u7b97\u6cd5&#xff1a;\u53bb\u9664\u57fa\u7ebf\u3001\u5cf0\u503c\u68c0\u6d4b\u3001\u8ba1\u7b97\u5fc3\u7387\u8840\u6c27&#xff1b;<\/li>\n<li>\u8ba1\u7b97\u5b8c\u6210\u540e\u4fdd\u7559\u6700\u8fd1 300 \u70b9\u6ce2\u5f62&#xff0c;\u540e\u7eed\u6bcf\u65b0\u589e 100 \u70b9&#xff08;1 \u79d2&#xff09;\u91cd\u65b0\u5237\u65b0\u4e00\u6b21\u6d4b\u91cf\u7ed3\u679c\u3002<\/li>\n<h4>\u5de5\u7a0b\u5173\u952e\u56fa\u5b9a\u53c2\u6570<\/h4>\n<table>\n<tr>\u53c2\u6570\u6570\u503c\u529f\u80fd<\/tr>\n<tbody>\n<tr>\n<td>\u91c7\u6837\u7387<\/td>\n<td>100Hz<\/td>\n<td>\u6bcf\u79d2\u8f93\u51fa 100 \u7ec4\u7ea2\u5149 &#043; \u7ea2\u5916\u91c7\u6837<\/td>\n<\/tr>\n<tr>\n<td>\u7b97\u6cd5\u6ce2\u5f62\u7a97\u53e3<\/td>\n<td>400 \u70b9<\/td>\n<td>\u5355\u6b21\u5b8c\u6574\u8ba1\u7b97\u4f9d\u9760 4 \u79d2\u6ce2\u5f62\u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>\u5237\u65b0\u6b65\u957f<\/td>\n<td>100 \u70b9<\/td>\n<td>\u57fa\u7840\u91c7\u6837\u5b8c\u6210\u540e\u6bcf\u79d2\u66f4\u65b0\u4e00\u6b21\u7ed3\u679c<\/td>\n<\/tr>\n<tr>\n<td>\u624b\u6307\u7ea2\u5916\u9608\u503c<\/td>\n<td>5000<\/td>\n<td>IR \u91c7\u6837\u503c\u4f4e\u4e8e\u8be5\u503c\u5224\u5b9a\u672a\u653e\u7f6e\u624b\u6307<\/td>\n<\/tr>\n<tr>\n<td>\u624b\u6307\u4e22\u5931\u8ba1\u6570<\/td>\n<td>20 \u70b9<\/td>\n<td>\u8fde\u7eed 0.2 \u79d2\u4f4e\u4fe1\u53f7\u6e05\u7a7a\u91c7\u6837\u7f13\u5b58<\/td>\n<\/tr>\n<tr>\n<td>\u6700\u5c0f\u8109\u640f\u5cf0\u95f4\u8ddd<\/td>\n<td>30 \u70b9<\/td>\n<td>\u8fc7\u6ee4\u566a\u58f0\u4f2a\u5cf0&#xff0c;\u6700\u5927\u8bc6\u522b\u5fc3\u7387 200 \u6b21 \/ \u5206<\/td>\n<\/tr>\n<tr>\n<td>\u5fc3\u7387\u6709\u6548\u533a\u95f4<\/td>\n<td>30~200BPM<\/td>\n<td>\u8d85\u51fa\u8303\u56f4\u5224\u5b9a\u7ed3\u679c\u65e0\u6548<\/td>\n<\/tr>\n<tr>\n<td>\u8840\u6c27\u6709\u6548\u533a\u95f4<\/td>\n<td>70~100%<\/td>\n<td>\u8d85\u51fa\u8303\u56f4\u4e0d\u5c55\u793a\u6d4b\u91cf\u6570\u503c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u516d\u3001OLED \u5c4f\u5e55\u663e\u793a\u4fe1\u606f\u8bf4\u660e<\/h3>\n<p>\u5c4f\u5e55\u5206\u591a\u79cd\u72b6\u6001\u6253\u5370\u5185\u5bb9&#xff0c;\u65b9\u4fbf\u8c03\u8bd5\u4e0e\u76f4\u89c2\u89c2\u5bdf&#xff1a;<\/p>\n<h4>6.1 \u6b63\u5e38\u6d4b\u91cf\u6210\u529f\u754c\u9762<\/h4>\n<p>IR:123456<br \/>\nHR:075 BPM<br \/>\nSpO2:098 %<br \/>\nMEASUREMENT OK<\/p>\n<p>\u5b57\u6bb5\u91ca\u4e49&#xff1a;<\/p>\n<li>IR&#xff1a;\u6700\u65b0\u4e00\u7ec4\u7ea2\u5916\u5149 18 \u4f4d\u539f\u59cb\u91c7\u6837\u6570\u503c&#xff1b;<\/li>\n<li>HR&#xff1a;\u8ba1\u7b97\u5f97\u5230\u5b9e\u65f6\u5fc3\u7387&#xff1b;<\/li>\n<li>SpO2&#xff1a;\u4f30\u7b97\u8840\u6c27\u9971\u548c\u5ea6&#xff1b;<\/li>\n<li>MEASUREMENT OK&#xff1a;\u6ce2\u5f62\u8d28\u91cf\u8fbe\u6807&#xff0c;\u6570\u503c\u6709\u6548\u3002<\/li>\n<h4>6.2 \u8c03\u8bd5\u4fe1\u606f\u754c\u9762&#xff08;\u65e0\u6709\u6548\u91c7\u6837\u65f6&#xff09;<\/h4>\n<p>W:00 R:00 S:000<\/p>\n<ul>\n<li>W&#xff1a;FIFO \u5199\u6307\u9488<\/li>\n<li>R&#xff1a;FIFO \u8bfb\u6307\u9488<\/li>\n<li>S&#xff1a;\u4e2d\u65ad\u72b6\u6001\u5bc4\u5b58\u5668\u5341\u8fdb\u5236\u503c&#xff0c;S&#061;64 \u4ee3\u8868\u65b0\u6837\u672c\u5c31\u7eea<\/li>\n<\/ul>\n<h4>6.3 \u5404\u7c7b\u5f02\u5e38\u63d0\u793a<\/h4>\n<li>WAIT FIFO DATA&#xff1a;\u4f20\u611f\u5668\u6682\u65e0\u91c7\u6837\u6570\u636e&#xff1b;<\/li>\n<li>FINGER \/ IR LOW&#xff1a;\u91c7\u6837\u5b58\u5728\u6570\u636e&#xff0c;\u4f46\u624b\u6307\u672a\u653e\u597d\u3001\u53cd\u5c04\u5149\u4e0d\u8db3&#xff1b;<\/li>\n<li>SAMPLING xxx%&#xff1a;\u6b63\u5728\u91c7\u96c6 400 \u70b9\u57fa\u7840\u6ce2\u5f62&#xff0c;\u663e\u793a\u91c7\u96c6\u8fdb\u5ea6&#xff1b;<\/li>\n<li>KEEP FINGER STILL&#xff1a;\u6ce2\u5f62\u566a\u58f0\u8fc7\u5927\u3001\u8fd0\u52a8\u5e72\u6270&#xff0c;\u7ed3\u679c\u65e0\u6548\u3002<\/li>\n<h3>\u4e03\u3001\u5b9e\u7269\u6f14\u793a\u6548\u679c\u7ae0\u8282<\/h3>\n<h4>7.1 \u5b9e\u7269\u786c\u4ef6\u6e05\u5355<\/h4>\n<li>STM32F103C8T6 \u6700\u5c0f\u7cfb\u7edf\u677f<\/li>\n<li>MAX30102 \u8840\u6c27\u5fc3\u7387\u4f20\u611f\u5668\u6a21\u5757<\/li>\n<li>0.96 \u5bf8 I2C OLED \u663e\u793a\u5c4f<\/li>\n<li>\u675c\u90a6\u7ebf\u82e5\u5e72\u3001\u9762\u5305\u677f<\/li>\n<li>3.3V \u76f4\u6d41\u4f9b\u7535\u7535\u6e90<\/li>\n<h4>7.2 \u5b9e\u7269\u63a5\u7ebf\u64cd\u4f5c\u6b65\u9aa4<\/h4>\n<li>\u5c06 MAX30102 VCC\u3001GND \u63a5\u5230\u6700\u5c0f\u7cfb\u7edf 3.3V \u4e0e GND&#xff0c;SCL \u63a5 PB6\u3001SDA \u63a5 PB7&#xff1b;<\/li>\n<li>OLED \u5c4f\u5e55 VCC\u3001GND \u5171\u5730\u4f9b\u7535&#xff0c;SCL \u63a5 PB8\u3001SDA \u63a5 PB9&#xff1b;<\/li>\n<li>\u6574\u4f53\u63a5\u7ebf\u5b8c\u6210\u540e\u68c0\u67e5\u65e0\u77ed\u8def\u3001\u865a\u63a5&#xff0c;\u63a5\u5165 USB \u4f9b\u7535&#xff1b;<\/li>\n<li>\u4e0a\u7535\u5c4f\u5e55\u5148\u6253\u5370 FIFO \u6307\u9488\u8c03\u8bd5\u4fe1\u606f&#xff0c;\u7b49\u5f85\u4f20\u611f\u5668\u521d\u59cb\u5316\u5b8c\u6210\u3002<\/li>\n<h4>7.3 \u6b63\u5e38\u6d4b\u91cf\u6f14\u793a<\/h4>\n<li>\u5c06\u6307\u8179\u5b8c\u6574\u8d34\u7d27 MAX30102 \u5149\u5b66\u7a97\u53e3&#xff0c;\u5b8c\u5168\u906e\u6321\u53d1\u5149\u7ba1&#xff1b;<\/li>\n<li>\u624b\u6307\u8f7b\u538b\u4f20\u611f\u5668&#xff0c;\u4e0d\u8981\u7528\u529b\u6324\u538b\u963b\u65ad\u8840\u6db2\u5faa\u73af&#xff0c;\u624b\u90e8\u4fdd\u6301\u9759\u6b62\u653e\u7f6e\u684c\u9762&#xff1b;<\/li>\n<li>\u5c4f\u5e55\u663e\u793a SAMPLING \u8fdb\u5ea6&#xff0c;\u7b49\u5f85\u8fdb\u5ea6 100%&#xff08;\u7ea6 4 \u79d2&#xff09;&#xff1b;<\/li>\n<li>\u8fdb\u5ea6\u5b8c\u6210\u540e\u81ea\u52a8\u8f93\u51fa\u5fc3\u7387\u3001\u8840\u6c27&#xff0c;\u7a33\u5b9a\u9759\u7f6e\u53ef\u89c2\u5bdf\u6570\u503c\u5c0f\u5e45\u6ce2\u52a8&#xff1b;<\/li>\n<li>\u79fb\u5f00\u624b\u6307&#xff0c;\u5c4f\u5e55\u7acb\u523b\u5207\u6362 FINGER \/ IR LOW \u63d0\u793a&#xff0c;IR \u6570\u503c\u5927\u5e45\u4e0b\u964d\u3002\n<p class=\"img-center\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1447\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e96bdbde.jpg\" width=\"1920\" \/><\/p>\n<\/li>\n<h3>\u516b\u3001\u6e90\u4ee3\u7801\u6a21\u5757&#xff08;\u53ef\u76f4\u63a5\u590d\u5236\u63d2\u5165\u533a\u57df&#xff09;<\/h3>\n<p>\u672c\u8282\u9884\u7559\u5b8c\u6574\u6e90\u7801\u63d2\u5165\u4f4d\u7f6e&#xff0c;\u5de5\u7a0b\u5206\u4e3a 3 \u4e2a\u6838\u5fc3\u6587\u4ef6&#xff1a;MAX30102 \u5e95\u5c42\u9a71\u52a8\u3001OLED \u8f6f\u4ef6 I2C \u9a71\u52a8\u3001\u4e3b\u51fd\u6570\u903b\u8f91<\/p>\n<h4>8.1 \u5de5\u7a0b\u6587\u4ef6\u7ed3\u6784<\/h4>\n<p>MAX30102.c  \/\/ \u4f20\u611f\u5668\u5e95\u5c42\u8bfb\u5199\u3001FIFO\u8bfb\u53d6\u3001\u91c7\u6837\u7f13\u5b58\u7ef4\u62a4<br \/>\noled.c          \/\/ \u72ec\u7acb\u8f6f\u4ef6I2C\u5c4f\u5e55\u9a71\u52a8<br \/>\nmain.c                   \/\/ \u4e3b\u5faa\u73af\u3001\u72b6\u6001\u5237\u65b0\u3001OLED\u6253\u5370\u663e\u793a<br \/>\nMAX30102\u7b97\u6cd5\u51fd\u6570              \/\/ \u53bb\u57fa\u7ebf\u3001\u5cf0\u503c\u68c0\u6d4b\u3001\u5fc3\u7387\u8840\u6c27\u8ba1\u7b97\u6a21\u5757<\/p>\n<h4>main.c\u4ee3\u7801<\/h4>\n<p>\/* MAX30102 heart-rate\/SpO2 teaching demonstration for STM32F103C8T6. *\/<br \/>\n#include &#034;delay.h&#034;<br \/>\n#include &#034;sys.h&#034;<br \/>\n#include &#034;oled.h&#034;<br \/>\n#include &#034;MAX30102.h&#034;<\/p>\n<p>#define LOOP_DELAY_MS        10U<br \/>\n#define DISPLAY_LOOP_COUNT   20U<\/p>\n<p>static void MAX30102_ShowData(const MAX30102_DataTypeDef *data);<br \/>\nstatic void MAX30102_ShowError(void);<\/p>\n<p>int main(void)<br \/>\n{<br \/>\nMAX30102_DataTypeDef sensor &#061; {0};<br \/>\nu8 display_count &#061; 0U;<br \/>\nu8 sensor_ok;<\/p>\n<p>delay_init();<br \/>\nNVIC_Configuration();<br \/>\nOLED_Init();<br \/>\nOLED_ColorTurn(0);<br \/>\nOLED_DisplayTurn(0);<br \/>\nOLED_Clear();<br \/>\nOLED_ShowString(0, 0, (u8 *)&#034;MAX30102 DEMO&#034;, 16);<br \/>\nOLED_ShowString(0, 24, (u8 *)&#034;INITIALIZING&#8230;&#034;, 12);<br \/>\nOLED_Refresh();<\/p>\n<p>sensor_ok &#061; MAX30102_Init();<br \/>\nif(sensor_ok &#061;&#061; 0U)<br \/>\n{<br \/>\nMAX30102_ShowError();<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nMAX30102_ShowData(&amp;sensor);<br \/>\n}<\/p>\n<p>while(1)<br \/>\n{<br \/>\nif(sensor_ok !&#061; 0U)<br \/>\n{<br \/>\nif(MAX30102_Update(&amp;sensor) &#061;&#061; 0U)<br \/>\n{<br \/>\nsensor_ok &#061; 0U;<br \/>\nMAX30102_ShowError();<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\ndisplay_count&#043;&#043;;<br \/>\nif(display_count &gt;&#061; DISPLAY_LOOP_COUNT)<br \/>\n{<br \/>\ndisplay_count &#061; 0U;<br \/>\nMAX30102_ShowData(&amp;sensor);<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\ndelay_ms(LOOP_DELAY_MS);<br \/>\n}<br \/>\n}<\/p>\n<p>static void MAX30102_ShowData(const MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\nOLED_Clear();<br \/>\nif(data-&gt;fifo_active !&#061; 0U)<br \/>\n{<br \/>\nOLED_ShowString(0, 0, (u8 *)&#034;IR:&#034;, 12);<br \/>\nOLED_ShowNum(18, 0, data-&gt;ir, 6, 12);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(0, 0, (u8 *)&#034;W:&#034;, 12);<br \/>\nOLED_ShowNum(12, 0, data-&gt;fifo_write_pointer, 2, 12);<br \/>\nOLED_ShowString(30, 0, (u8 *)&#034;R:&#034;, 12);<br \/>\nOLED_ShowNum(42, 0, data-&gt;fifo_read_pointer, 2, 12);<br \/>\nOLED_ShowString(60, 0, (u8 *)&#034;S:&#034;, 12);<br \/>\nOLED_ShowNum(72, 0, data-&gt;interrupt_status, 3, 12);<br \/>\n}<br \/>\nOLED_ShowString(0, 14, (u8 *)&#034;HR:&#034;, 16);<br \/>\nif(data-&gt;heart_rate_valid !&#061; 0U)<br \/>\n{<br \/>\nOLED_ShowNum(32, 14, data-&gt;heart_rate, 3, 16);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(32, 14, (u8 *)&#034;&#8212;&#034;, 16);<br \/>\n}<br \/>\nOLED_ShowString(64, 14, (u8 *)&#034;BPM&#034;, 16);<\/p>\n<p>OLED_ShowString(0, 32, (u8 *)&#034;SpO2:&#034;, 16);<br \/>\nif(data-&gt;spo2_valid !&#061; 0U)<br \/>\n{<br \/>\nOLED_ShowNum(48, 32, data-&gt;spo2, 3, 16);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(48, 32, (u8 *)&#034;&#8212;&#034;, 16);<br \/>\n}<br \/>\nOLED_ShowString(80, 32, (u8 *)&#034;%&#034;, 16);<\/p>\n<p>if(data-&gt;fifo_active &#061;&#061; 0U)<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;WAIT FIFO DATA&#034;, 12);<br \/>\n}<br \/>\nelse if(data-&gt;finger_detected &#061;&#061; 0U)<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;FINGER \/ IR LOW&#034;, 12);<br \/>\n}<br \/>\nelse if(data-&gt;progress &lt; 100U)<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;SAMPLING&#034;, 12);<br \/>\nOLED_ShowNum(60, 52, data-&gt;progress, 3, 12);<br \/>\nOLED_ShowString(78, 52, (u8 *)&#034;%&#034;, 12);<br \/>\n}<br \/>\nelse if((data-&gt;heart_rate_valid &#061;&#061; 0U) || (data-&gt;spo2_valid &#061;&#061; 0U))<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;KEEP FINGER STILL&#034;, 12);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;MEASUREMENT OK&#034;, 12);<br \/>\n}<br \/>\nOLED_Refresh();<br \/>\n}<\/p>\n<p>static void MAX30102_ShowError(void)<br \/>\n{<br \/>\nu8 error;<\/p>\n<p>error &#061; MAX30102_GetLastError();<br \/>\nOLED_Clear();<br \/>\nOLED_ShowString(0, 0, (u8 *)&#034;MAX30102 ERROR&#034;, 16);<br \/>\nif(error &#061;&#061; MAX30102_ERROR_I2C)<br \/>\n{<br \/>\nOLED_ShowString(0, 20, (u8 *)&#034;I2C NO ACK&#034;, 12);<br \/>\n}<br \/>\nelse if(error &#061;&#061; MAX30102_ERROR_PART_ID)<br \/>\n{<br \/>\nOLED_ShowString(0, 20, (u8 *)&#034;PART ID:&#034;, 12);<br \/>\nOLED_ShowNum(54, 20, MAX30102_GetPartID(), 3, 12);<br \/>\n}<br \/>\nelse if(error &#061;&#061; MAX30102_ERROR_RESET)<br \/>\n{<br \/>\nOLED_ShowString(0, 20, (u8 *)&#034;RESET FAILED&#034;, 12);<br \/>\n}<br \/>\nelse if(error &#061;&#061; MAX30102_ERROR_CONFIG)<br \/>\n{<br \/>\nOLED_ShowString(0, 20, (u8 *)&#034;CONFIG FAILED&#034;, 12);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(0, 20, (u8 *)&#034;FIFO I2C ERROR&#034;, 12);<br \/>\n}<br \/>\nOLED_ShowString(0, 36, (u8 *)&#034;SCL:PB6 SDA:PB7&#034;, 12);<br \/>\nif(error &#061;&#061; MAX30102_ERROR_PART_ID)<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;EXPECT:021 (0x15)&#034;, 12);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nOLED_ShowString(0, 52, (u8 *)&#034;CHECK I2C PULL-UP&#034;, 12);<br \/>\n}<br \/>\nOLED_Refresh();<br \/>\n}<\/p>\n<h4>MAX30102.c\u4ee3\u7801<\/h4>\n<p>#include &#034;MAX30102.h&#034;<br \/>\n#include &#034;delay.h&#034;<\/p>\n<p>\/**<br \/>\n * &#064;file MAX30102.c<br \/>\n * &#064;brief MAX30102 \u8f6f\u4ef6 I2C\u3001FIFO \u91c7\u6837\u53ca\u5fc3\u7387\u8840\u6c27\u8ba1\u7b97\u5b9e\u73b0\u3002<br \/>\n * &#064;note \u6587\u4ef6\u7f16\u7801\u4e3a UTF-8&#xff1b;\u6d4b\u91cf\u7ed3\u679c\u4ec5\u7528\u4e8e\u6559\u5b66\u6f14\u793a&#xff0c;\u4e0d\u7528\u4e8e\u533b\u7597\u8bca\u65ad\u3002<br \/>\n *\/<\/p>\n<p>\/* MAX30102 \u7684 7 \u4f4d I2C \u5730\u5740\u4e3a 0x57&#xff0c;\u53d1\u9001\u65f6\u9700\u8981\u5de6\u79fb\u4e00\u4f4d\u3002 *\/<br \/>\n#define MAX30102_ADDR_WRITE       0xAEU<br \/>\n#define MAX30102_ADDR_READ        0xAFU<\/p>\n<p>\/* MAX30102 \u5bc4\u5b58\u5668\u5730\u5740\u8868\u3002 *\/<br \/>\n#define REG_INTR_STATUS_1         0x00U<br \/>\n#define REG_INTR_STATUS_2         0x01U<br \/>\n#define REG_INTR_ENABLE_1         0x02U<br \/>\n#define REG_INTR_ENABLE_2         0x03U<br \/>\n#define REG_FIFO_WR_PTR           0x04U<br \/>\n#define REG_OVF_COUNTER           0x05U<br \/>\n#define REG_FIFO_RD_PTR           0x06U<br \/>\n#define REG_FIFO_DATA             0x07U<br \/>\n#define REG_FIFO_CONFIG           0x08U<br \/>\n#define REG_MODE_CONFIG           0x09U<br \/>\n#define REG_SPO2_CONFIG           0x0AU<br \/>\n#define REG_LED1_PA               0x0CU<br \/>\n#define REG_LED2_PA               0x0DU<br \/>\n#define REG_PILOT_PA              0x10U<br \/>\n#define REG_REV_ID                0xFEU<br \/>\n#define REG_PART_ID               0xFFU<\/p>\n<p>#define MAX30102_FIFO_DEPTH       32U       \/* \u786c\u4ef6 FIFO \u53ef\u4fdd\u5b58\u7684\u6837\u672c\u7ec4\u6570 *\/<br \/>\n#define MAX30102_WINDOW_SAMPLES   400U      \/* \u7b97\u6cd5\u7a97\u53e3&#xff1a;100 Hz \u4e0b\u7ea6 4 \u79d2 *\/<br \/>\n#define MAX30102_WINDOW_STEP      100U      \/* \u6bcf\u6536\u5230 100 \u4e2a\u65b0\u6837\u672c\u91cd\u65b0\u8ba1\u7b97 *\/<br \/>\n#define MAX30102_FINGER_IR_MIN    5000UL    \/* \u5224\u65ad\u624b\u6307\u5b58\u5728\u7684\u6700\u4f4e\u7ea2\u5916\u539f\u59cb\u503c *\/<br \/>\n#define MAX30102_FINGER_LOST      20U       \/* \u8fde\u7eed\u4f4e\u4fe1\u53f7\u8fbe\u5230\u6b64\u503c\u624d\u5224\u5b9a\u624b\u6307\u79bb\u5f00 *\/<br \/>\n#define MAX30102_MIN_AC_LEVEL     80UL      \/* \u6709\u6548\u8109\u640f\u4ea4\u6d41\u5206\u91cf\u7684\u6700\u4f4e\u5e45\u5ea6 *\/<br \/>\n#define MAX30102_MIN_PEAK_GAP     30U       \/* \u76f8\u90bb\u8109\u640f\u5cf0\u6700\u5c0f\u95f4\u9694&#xff0c;\u5bf9\u5e94\u6700\u9ad8\u7ea6 200 BPM *\/<br \/>\n#define MAX30102_MAX_PEAKS        16U       \/* \u5355\u4e2a\u7b97\u6cd5\u7a97\u53e3\u5141\u8bb8\u4fdd\u5b58\u7684\u6700\u5927\u5cf0\u503c\u6570\u91cf *\/<\/p>\n<p>#define MAX30102_SCL_HIGH() GPIO_SetBits(GPIOB, MAX30102_I2C_SCL_PIN)<br \/>\n#define MAX30102_SCL_LOW()  GPIO_ResetBits(GPIOB, MAX30102_I2C_SCL_PIN)<br \/>\n#define MAX30102_SDA_HIGH() GPIO_SetBits(GPIOB, MAX30102_I2C_SDA_PIN)<br \/>\n#define MAX30102_SDA_LOW()  GPIO_ResetBits(GPIOB, MAX30102_I2C_SDA_PIN)<br \/>\n#define MAX30102_SDA_READ() GPIO_ReadInputDataBit(GPIOB, MAX30102_I2C_SDA_PIN)<\/p>\n<p>\/* \u5fc3\u7387\u8840\u6c27\u7b97\u6cd5\u4f7f\u7528\u7684\u6ed1\u52a8\u91c7\u6837\u7a97\u53e3\u53ca\u8fd0\u884c\u72b6\u6001\u3002 *\/<br \/>\nstatic u32 max30102_red_buffer[MAX30102_WINDOW_SAMPLES];<br \/>\nstatic u32 max30102_ir_buffer[MAX30102_WINDOW_SAMPLES];<br \/>\nstatic s32 max30102_filtered[MAX30102_WINDOW_SAMPLES];<br \/>\nstatic u16 max30102_sample_count;<br \/>\nstatic u8 max30102_no_finger_count;<br \/>\nstatic u8 max30102_measurement_ready;<br \/>\nstatic u8 max30102_last_error;<br \/>\nstatic u8 max30102_part_id;<\/p>\n<p>\/* \u9a71\u52a8\u5185\u90e8\u51fd\u6570\u58f0\u660e\u3002 *\/<br \/>\nstatic void MAX30102_I2C_Delay(void);<br \/>\nstatic void MAX30102_SDA_Output(void);<br \/>\nstatic void MAX30102_SDA_Input(void);<br \/>\nstatic void MAX30102_I2C_Start(void);<br \/>\nstatic void MAX30102_I2C_Stop(void);<br \/>\nstatic u8 MAX30102_I2C_WriteByte(u8 value);<br \/>\nstatic u8 MAX30102_I2C_ReadByte(u8 acknowledge);<br \/>\nstatic void MAX30102_I2C_BusRecovery(void);<br \/>\nstatic u8 MAX30102_ReadBytes(u8 reg, u8 *buffer, u8 length);<br \/>\nstatic void MAX30102_ClearResult(MAX30102_DataTypeDef *data);<br \/>\nstatic void MAX30102_ResetMeasurement(MAX30102_DataTypeDef *data);<br \/>\nstatic void MAX30102_AddSample(u32 red, u32 ir, MAX30102_DataTypeDef *data);<br \/>\nstatic void MAX30102_Calculate(MAX30102_DataTypeDef *data);<br \/>\nstatic u32 MAX30102_IntegerSqrt(uint64_t value);<\/p>\n<p>\/** &#064;brief \u8f6f\u4ef6 I2C \u534a\u5468\u671f\u5ef6\u65f6\u3002 *\/<br \/>\nstatic void MAX30102_I2C_Delay(void)<br \/>\n{<br \/>\ndelay_us(4);<br \/>\n}<\/p>\n<p>\/*<br \/>\n * \u6bcf\u6b21\u53d1\u9001\u3001\u5e94\u7b54\u548c\u8bfb\u53d6\u65f6\u90fd\u663e\u5f0f\u5207\u6362 SDA \u65b9\u5411\u3002<br \/>\n * \u8f93\u5165\u4e0a\u62c9\u6a21\u5f0f\u53ef\u5728\u6a21\u5757\u4e0a\u62c9\u7535\u963b\u8f83\u5f31\u65f6\u4fdd\u6301 SDA \u7535\u5e73\u7a33\u5b9a\u3002<br \/>\n *\/<br \/>\nstatic void MAX30102_SDA_Output(void)<br \/>\n{<br \/>\nGPIO_InitTypeDef gpio;<\/p>\n<p>gpio.GPIO_Pin &#061; MAX30102_I2C_SDA_PIN;<br \/>\ngpio.GPIO_Speed &#061; GPIO_Speed_50MHz;<br \/>\ngpio.GPIO_Mode &#061; GPIO_Mode_Out_OD;<br \/>\nGPIO_Init(GPIOB, &amp;gpio);<br \/>\n}<\/p>\n<p>static void MAX30102_SDA_Input(void)<br \/>\n{<br \/>\nGPIO_InitTypeDef gpio;<\/p>\n<p>GPIO_SetBits(GPIOB, MAX30102_I2C_SDA_PIN);<br \/>\ngpio.GPIO_Pin &#061; MAX30102_I2C_SDA_PIN;<br \/>\ngpio.GPIO_Speed &#061; GPIO_Speed_50MHz;<br \/>\ngpio.GPIO_Mode &#061; GPIO_Mode_IPU;<br \/>\nGPIO_Init(GPIOB, &amp;gpio);<br \/>\n}<\/p>\n<p>\/** &#064;brief \u4ea7\u751f I2C \u8d77\u59cb\u4fe1\u53f7&#xff1a;SCL \u4e3a\u9ad8\u7535\u5e73\u65f6 SDA \u7531\u9ad8\u53d8\u4f4e\u3002 *\/<br \/>\nstatic void MAX30102_I2C_Start(void)<br \/>\n{<br \/>\nMAX30102_SDA_Output();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SDA_LOW();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_LOW();<br \/>\n}<\/p>\n<p>\/** &#064;brief \u4ea7\u751f I2C \u505c\u6b62\u4fe1\u53f7&#xff1a;SCL \u4e3a\u9ad8\u7535\u5e73\u65f6 SDA \u7531\u4f4e\u53d8\u9ad8\u3002 *\/<br \/>\nstatic void MAX30102_I2C_Stop(void)<br \/>\n{<br \/>\nMAX30102_SDA_Output();<br \/>\nMAX30102_SCL_LOW();<br \/>\nMAX30102_SDA_LOW();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u901a\u8fc7\u8f6f\u4ef6 I2C \u53d1\u9001\u4e00\u4e2a\u5b57\u8282\u5e76\u7b49\u5f85\u4ece\u673a\u5e94\u7b54\u3002<br \/>\n * &#064;return \u6536\u5230\u5e94\u7b54\u8fd4\u56de 1&#xff0c;\u7b49\u5f85\u5e94\u7b54\u8d85\u65f6\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nstatic u8 MAX30102_I2C_WriteByte(u8 value)<br \/>\n{<br \/>\nu8 i;<br \/>\nu16 timeout;<\/p>\n<p>MAX30102_SDA_Output();<br \/>\nMAX30102_SCL_LOW();<br \/>\nfor(i &#061; 0U; i &lt; 8U; i&#043;&#043;)<br \/>\n{<br \/>\nMAX30102_SCL_LOW();<br \/>\nif((value &amp; 0x80U) !&#061; 0U)<br \/>\n{<br \/>\nMAX30102_SDA_HIGH();<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nMAX30102_SDA_LOW();<br \/>\n}<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\nvalue &lt;&lt;&#061; 1;<br \/>\n}<\/p>\n<p>MAX30102_SCL_LOW();<br \/>\nMAX30102_SDA_Input();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<\/p>\n<p>timeout &#061; 200U;<br \/>\nwhile((MAX30102_SDA_READ() !&#061; Bit_RESET) &amp;&amp; (timeout &gt; 0U))<br \/>\n{<br \/>\ntimeout&#8211;;<br \/>\ndelay_us(1);<br \/>\n}<br \/>\nMAX30102_SCL_LOW();<br \/>\nMAX30102_SDA_Output();<br \/>\nreturn (timeout &gt; 0U) ? 1U : 0U;<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u901a\u8fc7\u8f6f\u4ef6 I2C \u8bfb\u53d6\u4e00\u4e2a\u5b57\u8282\u3002<br \/>\n * &#064;param acknowledge \u975e 0 \u8868\u793a\u8bfb\u5b8c\u540e\u53d1\u9001 ACK&#xff0c;0 \u8868\u793a\u53d1\u9001 NACK\u3002<br \/>\n *\/<br \/>\nstatic u8 MAX30102_I2C_ReadByte(u8 acknowledge)<br \/>\n{<br \/>\nu8 i;<br \/>\nu8 value &#061; 0U;<\/p>\n<p>MAX30102_SDA_Input();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nfor(i &#061; 0U; i &lt; 8U; i&#043;&#043;)<br \/>\n{<br \/>\nMAX30102_SCL_LOW();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nvalue &lt;&lt;&#061; 1;<br \/>\nif(MAX30102_SDA_READ() !&#061; Bit_RESET)<br \/>\n{<br \/>\nvalue |&#061; 0x01U;<br \/>\n}<br \/>\nMAX30102_I2C_Delay();<br \/>\n}<\/p>\n<p>MAX30102_SCL_LOW();<br \/>\nMAX30102_SDA_Output();<br \/>\nif(acknowledge !&#061; 0U)<br \/>\n{<br \/>\nMAX30102_SDA_LOW();<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nMAX30102_SDA_HIGH();<br \/>\n}<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_LOW();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nreturn value;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u8f93\u51fa 9 \u4e2a\u65f6\u949f\u5e76\u53d1\u9001\u505c\u6b62\u4fe1\u53f7&#xff0c;\u7528\u4e8e\u91ca\u653e\u5f02\u5e38\u5360\u7528\u7684 I2C \u603b\u7ebf\u3002 *\/<br \/>\nstatic void MAX30102_I2C_BusRecovery(void)<br \/>\n{<br \/>\nu8 i;<\/p>\n<p>MAX30102_SDA_Output();<br \/>\nMAX30102_SDA_HIGH();<br \/>\nfor(i &#061; 0U; i &lt; 9U; i&#043;&#043;)<br \/>\n{<br \/>\nMAX30102_SCL_LOW();<br \/>\nMAX30102_I2C_Delay();<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_I2C_Delay();<br \/>\n}<br \/>\nMAX30102_I2C_Stop();<br \/>\n}<\/p>\n<p>\/** &#064;brief \u5411\u6307\u5b9a\u5bc4\u5b58\u5668\u5199\u5165\u4e00\u4e2a\u5b57\u8282\u3002 *\/<br \/>\nu8 MAX30102_WriteRegister(u8 reg, u8 value)<br \/>\n{<br \/>\nMAX30102_I2C_Start();<br \/>\nif((MAX30102_I2C_WriteByte(MAX30102_ADDR_WRITE) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_I2C_WriteByte(reg) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_I2C_WriteByte(value) &#061;&#061; 0U))<br \/>\n{<br \/>\nMAX30102_I2C_Stop();<br \/>\nreturn 0U;<br \/>\n}<br \/>\nMAX30102_I2C_Stop();<br \/>\nreturn 1U;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u4ece\u6307\u5b9a\u5bc4\u5b58\u5668\u5f00\u59cb\u8fde\u7eed\u8bfb\u53d6\u591a\u4e2a\u5b57\u8282\u3002 *\/<br \/>\nstatic u8 MAX30102_ReadBytes(u8 reg, u8 *buffer, u8 length)<br \/>\n{<br \/>\nu8 i;<\/p>\n<p>if((buffer &#061;&#061; 0) || (length &#061;&#061; 0U))<br \/>\n{<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>MAX30102_I2C_Start();<br \/>\nif((MAX30102_I2C_WriteByte(MAX30102_ADDR_WRITE) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_I2C_WriteByte(reg) &#061;&#061; 0U))<br \/>\n{<br \/>\nMAX30102_I2C_Stop();<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>MAX30102_I2C_Start();<br \/>\nif(MAX30102_I2C_WriteByte(MAX30102_ADDR_READ) &#061;&#061; 0U)<br \/>\n{<br \/>\nMAX30102_I2C_Stop();<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>for(i &#061; 0U; i &lt; length; i&#043;&#043;)<br \/>\n{<br \/>\nbuffer[i] &#061; MAX30102_I2C_ReadByte((i &#043; 1U &lt; length) ? 1U : 0U);<br \/>\n}<br \/>\nMAX30102_I2C_Stop();<br \/>\nreturn 1U;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u4ece\u6307\u5b9a\u5bc4\u5b58\u5668\u8bfb\u53d6\u4e00\u4e2a\u5b57\u8282\u3002 *\/<br \/>\nu8 MAX30102_ReadRegister(u8 reg, u8 *value)<br \/>\n{<br \/>\nreturn MAX30102_ReadBytes(reg, value, 1U);<br \/>\n}<\/p>\n<p>\/** &#064;brief \u4ece FIFO \u8bfb\u53d6\u7ea2\u5149\u548c\u7ea2\u5916\u5149\u5404\u4e00\u4e2a 18 \u4f4d\u539f\u59cb\u6837\u672c\u3002 *\/<br \/>\nu8 MAX30102_ReadFIFO(u32 *red, u32 *ir)<br \/>\n{<br \/>\nu8 raw[6];<\/p>\n<p>if((red &#061;&#061; 0) || (ir &#061;&#061; 0))<br \/>\n{<br \/>\nreturn 0U;<br \/>\n}<br \/>\nif(MAX30102_ReadBytes(REG_FIFO_DATA, raw, 6U) &#061;&#061; 0U)<br \/>\n{<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>*red &#061; (((u32)raw[0] &lt;&lt; 16) | ((u32)raw[1] &lt;&lt; 8) | raw[2]) &amp; 0x03FFFFUL;<br \/>\n*ir  &#061; (((u32)raw[3] &lt;&lt; 16) | ((u32)raw[4] &lt;&lt; 8) | raw[5]) &amp; 0x03FFFFUL;<br \/>\nreturn 1U;<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u521d\u59cb\u5316 MAX30102\u3002<br \/>\n * &#064;details<br \/>\n * \u4f9d\u6b21\u5b8c\u6210 GPIO \u914d\u7f6e\u3001I2C \u603b\u7ebf\u6062\u590d\u3001\u82af\u7247\u578b\u53f7\u68c0\u6d4b\u3001\u8f6f\u4ef6\u590d\u4f4d\u3001<br \/>\n * FIFO \u6e05\u7a7a\u4ee5\u53ca SpO2 \u6a21\u5f0f\u914d\u7f6e\u3002\u4efb\u4e00\u6b65\u9aa4\u5931\u8d25\u90fd\u4f1a\u8bb0\u5f55\u5bf9\u5e94\u9519\u8bef\u7801\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_Init(void)<br \/>\n{<br \/>\nGPIO_InitTypeDef gpio;<br \/>\nu8 value;<br \/>\nu8 timeout;<br \/>\nu8 attempt;<\/p>\n<p>max30102_last_error &#061; MAX30102_ERROR_NONE;<br \/>\nmax30102_part_id &#061; 0U;<br \/>\nRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);<br \/>\nGPIO_SetBits(GPIOB, MAX30102_I2C_SCL_PIN | MAX30102_I2C_SDA_PIN);<br \/>\ngpio.GPIO_Pin &#061; MAX30102_I2C_SCL_PIN | MAX30102_I2C_SDA_PIN;<br \/>\ngpio.GPIO_Speed &#061; GPIO_Speed_50MHz;<br \/>\ngpio.GPIO_Mode &#061; GPIO_Mode_Out_OD;<br \/>\nGPIO_Init(GPIOB, &amp;gpio);<br \/>\nMAX30102_SCL_HIGH();<br \/>\nMAX30102_SDA_HIGH();<br \/>\ndelay_ms(10);<br \/>\nMAX30102_I2C_BusRecovery();<\/p>\n<p>for(attempt &#061; 0U; attempt &lt; 3U; attempt&#043;&#043;)<br \/>\n{<br \/>\nif(MAX30102_ReadRegister(REG_PART_ID, &amp;value) !&#061; 0U)<br \/>\n{<br \/>\nbreak;<br \/>\n}<br \/>\nMAX30102_I2C_BusRecovery();<br \/>\ndelay_ms(2);<br \/>\n}<br \/>\nif(attempt &gt;&#061; 3U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_I2C;<br \/>\nreturn 0U;<br \/>\n}<br \/>\nmax30102_part_id &#061; value;<br \/>\nif(value !&#061; MAX30102_EXPECTED_PART_ID)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_PART_ID;<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>if(MAX30102_WriteRegister(REG_MODE_CONFIG, 0x40U) &#061;&#061; 0U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_RESET;<br \/>\nreturn 0U;<br \/>\n}<br \/>\ntimeout &#061; 100U;<br \/>\ndo<br \/>\n{<br \/>\ndelay_ms(1);<br \/>\nif(MAX30102_ReadRegister(REG_MODE_CONFIG, &amp;value) &#061;&#061; 0U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_RESET;<br \/>\nreturn 0U;<br \/>\n}<br \/>\ntimeout&#8211;;<br \/>\n} while(((value &amp; 0x40U) !&#061; 0U) &amp;&amp; (timeout &gt; 0U));<br \/>\nif((value &amp; 0x40U) !&#061; 0U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_RESET;<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>\/* \u6309\u5df2\u9a8c\u8bc1\u7684\u4e94\u9488\u6a21\u5757\u9a71\u52a8\u987a\u5e8f\u914d\u7f6e\u5de5\u4f5c\u5bc4\u5b58\u5668\u3002 *\/<br \/>\nif((MAX30102_WriteRegister(REG_INTR_ENABLE_1, 0x40U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_INTR_ENABLE_2, 0x00U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_FIFO_WR_PTR, 0x00U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_OVF_COUNTER, 0x00U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_FIFO_RD_PTR, 0x00U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_FIFO_CONFIG, 0x0FU) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_MODE_CONFIG, 0x03U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_SPO2_CONFIG, 0x27U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_LED1_PA, 0x24U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_LED2_PA, 0x24U) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_WriteRegister(REG_PILOT_PA, 0x7FU) &#061;&#061; 0U))<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_CONFIG;<br \/>\nreturn 0U;<br \/>\n}<br \/>\ndelay_ms(10);<br \/>\nif((MAX30102_ReadRegister(REG_MODE_CONFIG, &amp;value) &#061;&#061; 0U) ||<br \/>\n   ((value &amp; 0x07U) !&#061; 0x03U))<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_CONFIG;<br \/>\nreturn 0U;<br \/>\n}<\/p>\n<p>\/* \u8bfb\u53d6\u4e24\u4e2a\u72b6\u6001\u5bc4\u5b58\u5668&#xff0c;\u6e05\u9664\u4e0a\u7535\u6216\u914d\u7f6e\u8fc7\u7a0b\u4e2d\u9057\u7559\u7684\u4e2d\u65ad\u6807\u5fd7\u3002 *\/<br \/>\nif((MAX30102_ReadRegister(REG_INTR_STATUS_1, &amp;value) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_ReadRegister(REG_INTR_STATUS_2, &amp;value) &#061;&#061; 0U))<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_CONFIG;<br \/>\nreturn 0U;<br \/>\n}<br \/>\nmax30102_sample_count &#061; 0U;<br \/>\nmax30102_no_finger_count &#061; 0U;<br \/>\nmax30102_measurement_ready &#061; 0U;<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_NONE;<br \/>\nreturn 1U;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u8fd4\u56de\u6700\u8fd1\u4e00\u6b21\u521d\u59cb\u5316\u6216 FIFO \u901a\u4fe1\u9519\u8bef\u7801\u3002 *\/<br \/>\nu8 MAX30102_GetLastError(void)<br \/>\n{<br \/>\nreturn max30102_last_error;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u8fd4\u56de\u521d\u59cb\u5316\u9636\u6bb5\u8bfb\u53d6\u5230\u7684\u82af\u7247\u578b\u53f7\u6807\u8bc6\u3002 *\/<br \/>\nu8 MAX30102_GetPartID(void)<br \/>\n{<br \/>\nreturn max30102_part_id;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u6e05\u9664\u5fc3\u7387\u3001\u8840\u6c27\u6570\u503c\u53ca\u5176\u6709\u6548\u6807\u5fd7\u3002 *\/<br \/>\nstatic void MAX30102_ClearResult(MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\ndata-&gt;heart_rate &#061; 0U;<br \/>\ndata-&gt;spo2 &#061; 0U;<br \/>\ndata-&gt;heart_rate_valid &#061; 0U;<br \/>\ndata-&gt;spo2_valid &#061; 0U;<br \/>\n}<\/p>\n<p>\/** &#064;brief \u6e05\u7a7a\u5f53\u524d\u91c7\u6837\u8fdb\u5ea6&#xff0c;\u5728\u624b\u6307\u79bb\u5f00\u6216 FIFO \u5f02\u5e38\u540e\u91cd\u65b0\u6d4b\u91cf\u3002 *\/<br \/>\nstatic void MAX30102_ResetMeasurement(MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\nmax30102_sample_count &#061; 0U;<br \/>\nmax30102_measurement_ready &#061; 0U;<br \/>\ndata-&gt;progress &#061; 0U;<br \/>\ndata-&gt;finger_detected &#061; 0U;<br \/>\nMAX30102_ClearResult(data);<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u8ba1\u7b97 64 \u4f4d\u65e0\u7b26\u53f7\u6574\u6570\u7684\u5e73\u65b9\u6839\u3002<br \/>\n * &#064;note \u4f7f\u7528\u9010\u4f4d\u7b97\u6cd5&#xff0c;\u907f\u514d\u5728 Cortex-M3 \u4e0a\u5f15\u5165\u6d6e\u70b9\u8fd0\u7b97\u5e93\u3002<br \/>\n *\/<br \/>\nstatic u32 MAX30102_IntegerSqrt(uint64_t value)<br \/>\n{<br \/>\nuint64_t bit;<br \/>\nuint64_t result;<\/p>\n<p>result &#061; 0U;<br \/>\nbit &#061; ((uint64_t)1U &lt;&lt; 62);<br \/>\nwhile(bit &gt; value)<br \/>\n{<br \/>\nbit &gt;&gt;&#061; 2;<br \/>\n}<br \/>\nwhile(bit !&#061; 0U)<br \/>\n{<br \/>\nif(value &gt;&#061; result &#043; bit)<br \/>\n{<br \/>\nvalue -&#061; result &#043; bit;<br \/>\nresult &#061; (result &gt;&gt; 1) &#043; bit;<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nresult &gt;&gt;&#061; 1;<br \/>\n}<br \/>\nbit &gt;&gt;&#061; 2;<br \/>\n}<br \/>\nreturn (u32)result;<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u6839\u636e 4 \u79d2\u7ea2\u5149\u548c\u7ea2\u5916\u5149\u91c7\u6837\u7a97\u53e3\u8ba1\u7b97\u5fc3\u7387\u4e0e\u8840\u6c27\u3002<br \/>\n * &#064;details<br \/>\n * \u8840\u6c27\u4f7f\u7528\u7ea2\u5149\/\u7ea2\u5916\u5149\u4ea4\u6d41\u5206\u91cf\u4e0e\u76f4\u6d41\u5206\u91cf\u7684\u6bd4\u503c\u4f30\u7b97&#xff1b;\u5fc3\u7387\u5148\u53bb\u9664<br \/>\n * \u7f13\u6162\u53d8\u5316\u7684\u76f4\u6d41\u57fa\u7ebf&#xff0c;\u518d\u68c0\u6d4b\u6709\u6548\u8109\u640f\u5cf0\u5e76\u6839\u636e\u5e73\u5747\u5cf0\u95f4\u8ddd\u6362\u7b97 BPM\u3002<br \/>\n *\/<br \/>\nstatic void MAX30102_Calculate(MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\nu16 i;<br \/>\nu16 start;<br \/>\nu16 end;<br \/>\nu16 peak_count;<br \/>\nu16 peak_locations[MAX30102_MAX_PEAKS];<br \/>\nu32 ir_sum;<br \/>\nu32 red_sum;<br \/>\nu32 ir_mean;<br \/>\nu32 red_mean;<br \/>\nu32 ir_ac;<br \/>\nu32 red_ac;<br \/>\nu32 interval_sum;<br \/>\nu32 average_interval;<br \/>\nu32 valid_interval_sum;<br \/>\nu16 valid_intervals;<br \/>\ns32 baseline;<br \/>\ns32 difference;<br \/>\ns32 positive_peak;<br \/>\ns32 negative_peak;<br \/>\ns32 threshold;<br \/>\ns32 polarity;<br \/>\nuint64_t ir_square_sum;<br \/>\nuint64_t red_square_sum;<br \/>\nuint64_t denominator;<br \/>\nuint64_t ratio_x100;<br \/>\ns32 spo2_x100;<\/p>\n<p>ir_sum &#061; 0U;<br \/>\nred_sum &#061; 0U;<br \/>\nMAX30102_ClearResult(data);<br \/>\nfor(i &#061; 0U; i &lt; MAX30102_WINDOW_SAMPLES; i&#043;&#043;)<br \/>\n{<br \/>\nir_sum &#043;&#061; max30102_ir_buffer[i];<br \/>\nred_sum &#043;&#061; max30102_red_buffer[i];<br \/>\n}<br \/>\nir_mean &#061; ir_sum \/ MAX30102_WINDOW_SAMPLES;<br \/>\nred_mean &#061; red_sum \/ MAX30102_WINDOW_SAMPLES;<br \/>\nif((ir_mean &lt; MAX30102_FINGER_IR_MIN) || (red_mean &#061;&#061; 0U))<br \/>\n{<br \/>\nMAX30102_ClearResult(data);<br \/>\nreturn;<br \/>\n}<\/p>\n<p>\/* \u901a\u8fc7\u7ea2\u5149\u548c\u7ea2\u5916\u5149\u7684\u4ea4\u6d41\/\u76f4\u6d41\u53cc\u6bd4\u503c\u4f30\u7b97\u6559\u5b66\u7528\u8840\u6c27\u503c\u3002 *\/<br \/>\nir_square_sum &#061; 0U;<br \/>\nred_square_sum &#061; 0U;<br \/>\nfor(i &#061; 0U; i &lt; MAX30102_WINDOW_SAMPLES; i&#043;&#043;)<br \/>\n{<br \/>\ndifference &#061; (s32)max30102_ir_buffer[i] &#8211; (s32)ir_mean;<br \/>\nir_square_sum &#043;&#061; (uint64_t)((int64_t)difference * difference);<br \/>\ndifference &#061; (s32)max30102_red_buffer[i] &#8211; (s32)red_mean;<br \/>\nred_square_sum &#043;&#061; (uint64_t)((int64_t)difference * difference);<br \/>\n}<br \/>\nir_ac &#061; MAX30102_IntegerSqrt(ir_square_sum \/ MAX30102_WINDOW_SAMPLES);<br \/>\nred_ac &#061; MAX30102_IntegerSqrt(red_square_sum \/ MAX30102_WINDOW_SAMPLES);<br \/>\nif((ir_ac &gt;&#061; MAX30102_MIN_AC_LEVEL) &amp;&amp; (red_ac &gt;&#061; MAX30102_MIN_AC_LEVEL))<br \/>\n{<br \/>\ndenominator &#061; (uint64_t)ir_ac * red_mean;<br \/>\nratio_x100 &#061; ((uint64_t)red_ac * ir_mean * 100U &#043; denominator \/ 2U) \/<br \/>\n             denominator;<br \/>\nif((ratio_x100 &gt;&#061; 30U) &amp;&amp; (ratio_x100 &lt;&#061; 170U))<br \/>\n{<br \/>\nspo2_x100 &#061; 9485L;<br \/>\nspo2_x100 &#043;&#061; (s32)((30354ULL * ratio_x100 &#043; 500ULL) \/ 1000ULL);<br \/>\nspo2_x100 -&#061; (s32)((4506ULL * ratio_x100 * ratio_x100 &#043; 5000ULL) \/ 10000ULL);<br \/>\nif(spo2_x100 &gt; 10000L)<br \/>\n{<br \/>\nspo2_x100 &#061; 10000L;<br \/>\n}<br \/>\nif(spo2_x100 &gt;&#061; 7000L)<br \/>\n{<br \/>\ndata-&gt;spo2 &#061; (u16)((spo2_x100 &#043; 50L) \/ 100L);<br \/>\ndata-&gt;spo2_valid &#061; 1U;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>\/* \u53bb\u9664\u7f13\u6162\u53d8\u5316\u7684\u76f4\u6d41\u57fa\u7ebf&#xff0c;\u518d\u5728\u4ea4\u6d41\u6ce2\u5f62\u4e2d\u5bfb\u627e\u8109\u640f\u5cf0\u3002 *\/<br \/>\nbaseline &#061; (s32)max30102_ir_buffer[0];<br \/>\npositive_peak &#061; 0;<br \/>\nnegative_peak &#061; 0;<br \/>\nfor(i &#061; 0U; i &lt; MAX30102_WINDOW_SAMPLES; i&#043;&#043;)<br \/>\n{<br \/>\nbaseline &#043;&#061; ((s32)max30102_ir_buffer[i] &#8211; baseline) \/ 16;<br \/>\nmax30102_filtered[i] &#061; (s32)max30102_ir_buffer[i] &#8211; baseline;<br \/>\nif(max30102_filtered[i] &gt; positive_peak)<br \/>\n{<br \/>\npositive_peak &#061; max30102_filtered[i];<br \/>\n}<br \/>\nif(max30102_filtered[i] &lt; negative_peak)<br \/>\n{<br \/>\nnegative_peak &#061; max30102_filtered[i];<br \/>\n}<br \/>\n}<br \/>\npolarity &#061; (positive_peak &gt;&#061; -negative_peak) ? 1 : -1;<br \/>\nthreshold &#061; ((polarity &gt; 0) ? positive_peak : -negative_peak) * 35L \/ 100L;<br \/>\nif(threshold &lt; (s32)MAX30102_MIN_AC_LEVEL)<br \/>\n{<br \/>\ndata-&gt;heart_rate_valid &#061; 0U;<br \/>\nreturn;<br \/>\n}<\/p>\n<p>peak_count &#061; 0U;<br \/>\nfor(i &#061; 2U; i &lt; (MAX30102_WINDOW_SAMPLES &#8211; 2U); i&#043;&#043;)<br \/>\n{<br \/>\ns32 current;<br \/>\ns32 previous;<br \/>\ns32 next;<\/p>\n<p>current &#061; max30102_filtered[i] * polarity;<br \/>\nprevious &#061; max30102_filtered[i &#8211; 1U] * polarity;<br \/>\nnext &#061; max30102_filtered[i &#043; 1U] * polarity;<br \/>\nif((current &gt;&#061; threshold) &amp;&amp; (current &gt;&#061; previous) &amp;&amp; (current &gt; next))<br \/>\n{<br \/>\nif(peak_count &#061;&#061; 0U)<br \/>\n{<br \/>\npeak_locations[peak_count&#043;&#043;] &#061; i;<br \/>\n}<br \/>\nelse if((i &#8211; peak_locations[peak_count &#8211; 1U]) &lt; MAX30102_MIN_PEAK_GAP)<br \/>\n{<br \/>\nif(current &gt; max30102_filtered[peak_locations[peak_count &#8211; 1U]] * polarity)<br \/>\n{<br \/>\npeak_locations[peak_count &#8211; 1U] &#061; i;<br \/>\n}<br \/>\n}<br \/>\nelse if(peak_count &lt; MAX30102_MAX_PEAKS)<br \/>\n{<br \/>\npeak_locations[peak_count&#043;&#043;] &#061; i;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>if(peak_count &lt; 3U)<br \/>\n{<br \/>\ndata-&gt;heart_rate_valid &#061; 0U;<br \/>\nreturn;<br \/>\n}<br \/>\ninterval_sum &#061; 0U;<br \/>\nfor(i &#061; 1U; i &lt; peak_count; i&#043;&#043;)<br \/>\n{<br \/>\ninterval_sum &#043;&#061; peak_locations[i] &#8211; peak_locations[i &#8211; 1U];<br \/>\n}<br \/>\naverage_interval &#061; interval_sum \/ (peak_count &#8211; 1U);<\/p>\n<p>\/* \u5254\u9664\u4e0e\u5e73\u5747\u5cf0\u95f4\u8ddd\u504f\u5dee\u8fc7\u5927\u7684\u8fd0\u52a8\u4f2a\u5cf0\u3002 *\/<br \/>\nvalid_interval_sum &#061; 0U;<br \/>\nvalid_intervals &#061; 0U;<br \/>\nstart &#061; (u16)(average_interval * 60U \/ 100U);<br \/>\nend &#061; (u16)(average_interval * 140U \/ 100U);<br \/>\nfor(i &#061; 1U; i &lt; peak_count; i&#043;&#043;)<br \/>\n{<br \/>\nu16 interval;<br \/>\ninterval &#061; peak_locations[i] &#8211; peak_locations[i &#8211; 1U];<br \/>\nif((interval &gt;&#061; start) &amp;&amp; (interval &lt;&#061; end))<br \/>\n{<br \/>\nvalid_interval_sum &#043;&#061; interval;<br \/>\nvalid_intervals&#043;&#043;;<br \/>\n}<br \/>\n}<br \/>\nif(valid_intervals &gt;&#061; 2U)<br \/>\n{<br \/>\naverage_interval &#061; valid_interval_sum \/ valid_intervals;<br \/>\nif(average_interval !&#061; 0U)<br \/>\n{<br \/>\ndata-&gt;heart_rate &#061; (u16)((MAX30102_SAMPLE_RATE_HZ * 60U &#043;<br \/>\n                                  average_interval \/ 2U) \/ average_interval);<br \/>\nif((data-&gt;heart_rate &gt;&#061; 30U) &amp;&amp; (data-&gt;heart_rate &lt;&#061; 200U))<br \/>\n{<br \/>\ndata-&gt;heart_rate_valid &#061; 1U;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u5904\u7406\u4e00\u7ec4\u65b0\u6837\u672c\u5e76\u52a0\u5165\u7b97\u6cd5\u7a97\u53e3\u3002<br \/>\n * &#064;details \u7ea2\u5916\u503c\u8fc7\u4f4e\u65f6\u7d2f\u8ba1\u624b\u6307\u4e22\u5931\u6b21\u6570&#xff1b;\u7a97\u53e3\u586b\u6ee1\u540e\u6bcf\u65b0\u589e 100 \u4e2a\u6837\u672c<br \/>\n * \u91cd\u65b0\u8ba1\u7b97\u4e00\u6b21&#xff0c;\u5e76\u4fdd\u7559\u6700\u8fd1 3 \u79d2\u6570\u636e\u5f62\u6210\u6ed1\u52a8\u7a97\u53e3\u3002<br \/>\n *\/<br \/>\nstatic void MAX30102_AddSample(u32 red, u32 ir, MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\nu16 i;<\/p>\n<p>data-&gt;red &#061; red;<br \/>\ndata-&gt;ir &#061; ir;<br \/>\ndata-&gt;sample_ready &#061; 1U;<br \/>\ndata-&gt;fifo_active &#061; 1U;<br \/>\nif(ir &lt; MAX30102_FINGER_IR_MIN)<br \/>\n{<br \/>\nif(max30102_no_finger_count &lt; MAX30102_FINGER_LOST)<br \/>\n{<br \/>\nmax30102_no_finger_count&#043;&#043;;<br \/>\n}<br \/>\nif(max30102_no_finger_count &gt;&#061; MAX30102_FINGER_LOST)<br \/>\n{<br \/>\nMAX30102_ResetMeasurement(data);<br \/>\n}<br \/>\nreturn;<br \/>\n}<\/p>\n<p>max30102_no_finger_count &#061; 0U;<br \/>\ndata-&gt;finger_detected &#061; 1U;<br \/>\nif(max30102_sample_count &lt; MAX30102_WINDOW_SAMPLES)<br \/>\n{<br \/>\nmax30102_red_buffer[max30102_sample_count] &#061; red;<br \/>\nmax30102_ir_buffer[max30102_sample_count] &#061; ir;<br \/>\nmax30102_sample_count&#043;&#043;;<br \/>\n}<br \/>\nif(max30102_measurement_ready !&#061; 0U)<br \/>\n{<br \/>\ndata-&gt;progress &#061; 100U;<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\ndata-&gt;progress &#061; (u8)(((u32)max30102_sample_count * 100U) \/<br \/>\n                      MAX30102_WINDOW_SAMPLES);<br \/>\n}<\/p>\n<p>if(max30102_sample_count &gt;&#061; MAX30102_WINDOW_SAMPLES)<br \/>\n{<br \/>\nMAX30102_Calculate(data);<br \/>\nmax30102_measurement_ready &#061; 1U;<br \/>\nfor(i &#061; 0U; i &lt; (MAX30102_WINDOW_SAMPLES &#8211; MAX30102_WINDOW_STEP); i&#043;&#043;)<br \/>\n{<br \/>\nmax30102_red_buffer[i] &#061; max30102_red_buffer[i &#043; MAX30102_WINDOW_STEP];<br \/>\nmax30102_ir_buffer[i] &#061; max30102_ir_buffer[i &#043; MAX30102_WINDOW_STEP];<br \/>\n}<br \/>\nmax30102_sample_count &#061; MAX30102_WINDOW_SAMPLES &#8211; MAX30102_WINDOW_STEP;<br \/>\ndata-&gt;progress &#061; 100U;<br \/>\n}<br \/>\n}<\/p>\n<p>\/**<br \/>\n * &#064;brief \u8f6e\u8be2\u4e2d\u65ad\u72b6\u6001\u548c FIFO \u6307\u9488&#xff0c;\u8bfb\u53d6\u5f53\u524d\u5168\u90e8\u53ef\u7528\u6837\u672c\u3002<br \/>\n * &#064;details \u540c\u65f6\u5229\u7528 PPG_RDY \u72b6\u6001\u4f4d\u89e3\u51b3 FIFO \u6ee1\u65f6\u8bfb\u5199\u6307\u9488\u76f8\u7b49\u7684\u6b67\u4e49\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_Update(MAX30102_DataTypeDef *data)<br \/>\n{<br \/>\nu8 interrupt_status;<br \/>\nu8 write_pointer;<br \/>\nu8 read_pointer;<br \/>\nu8 overflow;<br \/>\nu8 available;<br \/>\nu8 i;<br \/>\nu32 red;<br \/>\nu32 ir;<\/p>\n<p>if(data &#061;&#061; 0)<br \/>\n{<br \/>\nreturn 0U;<br \/>\n}<br \/>\ndata-&gt;sample_ready &#061; 0U;<br \/>\nif((MAX30102_ReadRegister(REG_INTR_STATUS_1, &amp;interrupt_status) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_ReadRegister(REG_FIFO_WR_PTR, &amp;write_pointer) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_ReadRegister(REG_OVF_COUNTER, &amp;overflow) &#061;&#061; 0U) ||<br \/>\n   (MAX30102_ReadRegister(REG_FIFO_RD_PTR, &amp;read_pointer) &#061;&#061; 0U))<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_FIFO;<br \/>\nreturn 0U;<br \/>\n}<br \/>\nwrite_pointer &amp;&#061; 0x1FU;<br \/>\nread_pointer &amp;&#061; 0x1FU;<br \/>\ndata-&gt;interrupt_status &#061; interrupt_status;<br \/>\ndata-&gt;fifo_write_pointer &#061; write_pointer;<br \/>\ndata-&gt;fifo_read_pointer &#061; read_pointer;<\/p>\n<p>available &#061; (write_pointer &#8211; read_pointer) &amp; (MAX30102_FIFO_DEPTH &#8211; 1U);<br \/>\nif((overflow &amp; 0x1FU) !&#061; 0U)<br \/>\n{<br \/>\n\/* \u53d1\u751f\u6ea2\u51fa\u540e\u6307\u9488\u76f8\u7b49\u8868\u793a FIFO \u5df2\u6ee1&#xff0c;\u800c\u4e0d\u662f FIFO \u4e3a\u7a7a\u3002 *\/<br \/>\nif(available &#061;&#061; 0U)<br \/>\n{<br \/>\navailable &#061; MAX30102_FIFO_DEPTH;<br \/>\n}<br \/>\n}<br \/>\nelse if((available &#061;&#061; 0U) &amp;&amp; ((interrupt_status &amp; 0x40U) !&#061; 0U))<br \/>\n{<br \/>\n\/* PPG_RDY \u7f6e\u4f4d\u65f6\u81f3\u5c11\u6709\u4e00\u4e2a\u65b0\u6837\u672c&#xff0c;\u53ef\u6d88\u9664\u6307\u9488\u76f8\u7b49\u7684\u6b67\u4e49\u3002 *\/<br \/>\navailable &#061; 1U;<br \/>\n}<br \/>\nfor(i &#061; 0U; i &lt; available; i&#043;&#043;)<br \/>\n{<br \/>\nif(MAX30102_ReadFIFO(&amp;red, &amp;ir) &#061;&#061; 0U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_FIFO;<br \/>\nreturn 0U;<br \/>\n}<br \/>\nMAX30102_AddSample(red, ir, data);<br \/>\n}<br \/>\nif((overflow &amp; 0x1FU) !&#061; 0U)<br \/>\n{<br \/>\nif(MAX30102_WriteRegister(REG_OVF_COUNTER, 0U) &#061;&#061; 0U)<br \/>\n{<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_FIFO;<br \/>\nreturn 0U;<br \/>\n}<br \/>\n}<br \/>\nmax30102_last_error &#061; MAX30102_ERROR_NONE;<br \/>\nreturn 1U;<br \/>\n}<\/p>\n<h4>MAX30102.h\u4ee3\u7801<\/h4>\n<p>#ifndef __MAX30102_H<br \/>\n#define __MAX30102_H<\/p>\n<p>#include &#034;sys.h&#034;<\/p>\n<p>\/**<br \/>\n * &#064;file MAX30102.h<br \/>\n * &#064;brief MAX30102 \u5fc3\u7387\u8840\u6c27\u4f20\u611f\u5668\u9a71\u52a8\u63a5\u53e3\u3002<br \/>\n * &#064;note \u6587\u4ef6\u7f16\u7801\u4e3a UTF-8&#xff0c;\u9002\u7528\u4e8e STM32F103C8T6 \u6559\u5b66\u6f14\u793a\u5de5\u7a0b\u3002<br \/>\n *\/<\/p>\n<p>\/*<br \/>\n * MAX30102 \u63a5\u7ebf&#xff1a;<br \/>\n *   SCL -&gt; PB6<br \/>\n *   SDA -&gt; PB7<br \/>\n *<br \/>\n * PB6\/PB7 \u7ec4\u6210 MAX30102 \u72ec\u7acb\u8f6f\u4ef6 I2C \u603b\u7ebf&#xff1b;OLED \u4f7f\u7528 PB8\/PB9&#xff0c;<br \/>\n * \u4e24\u6761\u603b\u7ebf\u76f8\u4e92\u72ec\u7acb&#xff0c;\u5237\u65b0 OLED \u65f6\u4e0d\u4f1a\u6539\u53d8\u4f20\u611f\u5668\u7684\u603b\u7ebf\u72b6\u6001\u3002<br \/>\n *\/<br \/>\n#define MAX30102_I2C_SCL_PIN       GPIO_Pin_6<br \/>\n#define MAX30102_I2C_SDA_PIN       GPIO_Pin_7<br \/>\n#define MAX30102_EXPECTED_PART_ID  0x15U    \/* MAX30102 \u82af\u7247\u578b\u53f7\u6807\u8bc6 *\/<br \/>\n#define MAX30102_SAMPLE_RATE_HZ    100U     \/* \u91c7\u6837\u7387&#xff1a;100 \u4e2a\u6837\u672c\/\u79d2 *\/<\/p>\n<p>\/* \u9a71\u52a8\u9519\u8bef\u7801&#xff0c;\u53ef\u901a\u8fc7 MAX30102_GetLastError() \u8bfb\u53d6\u3002 *\/<br \/>\n#define MAX30102_ERROR_NONE        0U       \/* \u65e0\u9519\u8bef *\/<br \/>\n#define MAX30102_ERROR_I2C         1U       \/* I2C \u5730\u5740\u9636\u6bb5\u672a\u6536\u5230\u5e94\u7b54 *\/<br \/>\n#define MAX30102_ERROR_PART_ID     2U       \/* \u82af\u7247\u578b\u53f7\u6807\u8bc6\u4e0d\u662f 0x15 *\/<br \/>\n#define MAX30102_ERROR_RESET       3U       \/* \u82af\u7247\u590d\u4f4d\u5931\u8d25\u6216\u8d85\u65f6 *\/<br \/>\n#define MAX30102_ERROR_CONFIG      4U       \/* \u5de5\u4f5c\u5bc4\u5b58\u5668\u914d\u7f6e\u5931\u8d25 *\/<br \/>\n#define MAX30102_ERROR_FIFO        5U       \/* FIFO \u8f6e\u8be2\u6216\u8bfb\u53d6\u5931\u8d25 *\/<\/p>\n<p>\/** MAX30102 \u6d4b\u91cf\u6570\u636e\u53ca\u8fd0\u884c\u72b6\u6001\u3002 *\/<br \/>\ntypedef struct<br \/>\n{<br \/>\nu16 heart_rate;          \/* \u5fc3\u7387&#xff0c;\u5355\u4f4d&#xff1a;\u6b21\/\u5206\u949f&#xff08;BPM&#xff09; *\/<br \/>\nu16 spo2;                \/* \u8840\u6c27\u9971\u548c\u5ea6&#xff0c;\u5355\u4f4d&#xff1a;\u767e\u5206\u6bd4&#xff08;%&#xff09; *\/<br \/>\nu8  heart_rate_valid;    \/* \u5fc3\u7387\u6709\u6548\u6807\u5fd7&#xff1a;1 \u6709\u6548&#xff0c;0 \u65e0\u6548 *\/<br \/>\nu8  spo2_valid;          \/* \u8840\u6c27\u6709\u6548\u6807\u5fd7&#xff1a;1 \u6709\u6548&#xff0c;0 \u65e0\u6548 *\/<br \/>\nu8  finger_detected;     \/* \u624b\u6307\u68c0\u6d4b\u6807\u5fd7&#xff1a;1 \u5df2\u68c0\u6d4b\u5230&#xff0c;0 \u672a\u68c0\u6d4b\u5230 *\/<br \/>\nu8  sample_ready;        \/* \u672c\u6b21\u66f4\u65b0\u81f3\u5c11\u8bfb\u53d6\u5230\u4e00\u4e2a\u65b0\u6837\u672c\u65f6\u7f6e 1 *\/<br \/>\nu8  fifo_active;         \/* \u6210\u529f\u8bfb\u53d6\u8fc7 FIFO \u6837\u672c\u540e\u4fdd\u6301\u4e3a 1 *\/<br \/>\nu8  progress;            \/* \u9996\u6b21\u6d4b\u91cf\u91c7\u96c6\u8fdb\u5ea6&#xff0c;\u8303\u56f4 0&#xff5e;100 *\/<br \/>\nu8  fifo_write_pointer;  \/* FIFO \u5199\u6307\u9488&#xff0c;\u7528\u4e8e\u901a\u4fe1\u72b6\u6001\u8bca\u65ad *\/<br \/>\nu8  fifo_read_pointer;   \/* FIFO \u8bfb\u6307\u9488&#xff0c;\u7528\u4e8e\u901a\u4fe1\u72b6\u6001\u8bca\u65ad *\/<br \/>\nu8  interrupt_status;    \/* \u4e2d\u65ad\u72b6\u6001\u5bc4\u5b58\u5668 1 \u7684\u6700\u8fd1\u8bfb\u53d6\u503c *\/<br \/>\nu32 red;                 \/* \u6700\u8fd1\u4e00\u6b21\u7ea2\u5149\u539f\u59cb\u91c7\u6837\u503c&#xff0c;18 \u4f4d\u6709\u6548 *\/<br \/>\nu32 ir;                  \/* \u6700\u8fd1\u4e00\u6b21\u7ea2\u5916\u5149\u539f\u59cb\u91c7\u6837\u503c&#xff0c;18 \u4f4d\u6709\u6548 *\/<br \/>\n} MAX30102_DataTypeDef;<\/p>\n<p>\/**<br \/>\n * &#064;brief \u521d\u59cb\u5316 GPIO\u3001\u8f6f\u4ef6 I2C \u548c MAX30102 \u5de5\u4f5c\u5bc4\u5b58\u5668\u3002<br \/>\n * &#064;return \u521d\u59cb\u5316\u6210\u529f\u8fd4\u56de 1&#xff0c;\u5931\u8d25\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_Init(void);<\/p>\n<p>\/**<br \/>\n * &#064;brief \u8f6e\u8be2 FIFO\u3001\u8bfb\u53d6\u65b0\u6837\u672c\u5e76\u66f4\u65b0\u5fc3\u7387\u548c\u8840\u6c27\u8ba1\u7b97\u7ed3\u679c\u3002<br \/>\n * &#064;param data \u7528\u4e8e\u4fdd\u5b58\u6d4b\u91cf\u7ed3\u679c\u548c\u8fd0\u884c\u72b6\u6001\u7684\u7ed3\u6784\u4f53\u5730\u5740\u3002<br \/>\n * &#064;return \u901a\u4fe1\u6b63\u5e38\u8fd4\u56de 1&#xff0c;I2C \u6216 FIFO \u64cd\u4f5c\u5931\u8d25\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_Update(MAX30102_DataTypeDef *data);<\/p>\n<p>\/** &#064;brief \u8bfb\u53d6\u6700\u8fd1\u4e00\u6b21\u9a71\u52a8\u9519\u8bef\u7801\u3002 *\/<br \/>\nu8 MAX30102_GetLastError(void);<\/p>\n<p>\/** &#064;brief \u8bfb\u53d6\u521d\u59cb\u5316\u9636\u6bb5\u68c0\u6d4b\u5230\u7684\u82af\u7247\u578b\u53f7\u6807\u8bc6\u3002 *\/<br \/>\nu8 MAX30102_GetPartID(void);<\/p>\n<p>\/* \u4ee5\u4e0b\u5e95\u5c42\u63a5\u53e3\u53ef\u7528\u4e8e\u8bfe\u5802\u4e0a\u7684\u5bc4\u5b58\u5668\u8bfb\u5199\u548c\u539f\u59cb\u6570\u636e\u5b9e\u9a8c\u3002 *\/<\/p>\n<p>\/**<br \/>\n * &#064;brief \u5411 MAX30102 \u6307\u5b9a\u5bc4\u5b58\u5668\u5199\u5165\u4e00\u4e2a\u5b57\u8282\u3002<br \/>\n * &#064;return \u5199\u5165\u6210\u529f\u8fd4\u56de 1&#xff0c;\u901a\u4fe1\u5931\u8d25\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_WriteRegister(u8 reg, u8 value);<\/p>\n<p>\/**<br \/>\n * &#064;brief \u4ece MAX30102 \u6307\u5b9a\u5bc4\u5b58\u5668\u8bfb\u53d6\u4e00\u4e2a\u5b57\u8282\u3002<br \/>\n * &#064;return \u8bfb\u53d6\u6210\u529f\u8fd4\u56de 1&#xff0c;\u901a\u4fe1\u5931\u8d25\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_ReadRegister(u8 reg, u8 *value);<\/p>\n<p>\/**<br \/>\n * &#064;brief \u4ece FIFO \u8bfb\u53d6\u4e00\u7ec4\u7ea2\u5149\u548c\u7ea2\u5916\u5149\u539f\u59cb\u6837\u672c\u3002<br \/>\n * &#064;return \u8bfb\u53d6\u6210\u529f\u8fd4\u56de 1&#xff0c;\u901a\u4fe1\u5931\u8d25\u8fd4\u56de 0\u3002<br \/>\n *\/<br \/>\nu8 MAX30102_ReadFIFO(u32 *red, u32 *ir);<\/p>\n<p>#endif<\/p>\n<h4>8.2 \u5404\u6587\u4ef6\u6838\u5fc3\u51fd\u6570\u529f\u80fd\u8bf4\u660e<\/h4>\n<li>MAX30102_Init ()&#xff1a;\u521d\u59cb\u5316 GPIO\u3001\u8bfb\u53d6\u82af\u7247 ID \u6821\u9a8c\u3001\u914d\u7f6e\u5168\u90e8\u4f20\u611f\u5668\u5bc4\u5b58\u5668&#xff1b;<\/li>\n<li>MAX30102_ReadFIFO ()&#xff1a;I2C \u8bfb\u53d6\u4e00\u7ec4 6 \u5b57\u8282\u7ea2\u5149\u7ea2\u5916\u539f\u59cb\u91c7\u6837&#xff1b;<\/li>\n<li>MAX30102_Update ()&#xff1a;\u8f6e\u8be2 FIFO \u7f13\u5b58&#xff0c;\u4e00\u6b21\u6027\u8bfb\u53d6\u6240\u6709\u672a\u5904\u7406\u6837\u672c&#xff1b;<\/li>\n<li>MAX30102_AddSample ()&#xff1a;\u624b\u6307\u9608\u503c\u5224\u65ad\u3001\u7ef4\u62a4 400 \u70b9\u6ed1\u52a8\u6ce2\u5f62\u7a97\u53e3&#xff1b;<\/li>\n<li>MAX30102_Calculate ()&#xff1a;\u6ce2\u5f62\u6ee4\u6ce2\u3001\u5cf0\u503c\u8bc6\u522b\u3001\u5fc3\u7387\u8840\u6c27\u6570\u503c\u8ba1\u7b97&#xff1b;<\/li>\n<li>MAX30102_ShowData ()&#xff1a;\u8c03\u7528 OLED \u9a71\u52a8&#xff0c;\u6253\u5370\u5168\u90e8\u72b6\u6001\u4e0e\u6d4b\u91cf\u7ed3\u679c\u3002<\/li>\n<h4>8.3 \u6e90\u7801\u4f7f\u7528\u8bf4\u660e<\/h4>\n<li>\u6e90\u7801\u57fa\u4e8e\u6807\u51c6\u5e93 STM32F10x \u5f00\u53d1&#xff0c;\u4e0d\u4f9d\u8d56 HAL \u5e93&#xff0c;\u9002\u914d\u521d\u5b66\u8bfe\u7a0b\u8bbe\u8ba1&#xff1b;<\/li>\n<li>\u6240\u6709\u5b8f\u5b9a\u4e49\u96c6\u4e2d\u5728\u5934\u6587\u4ef6&#xff0c;\u53ef\u76f4\u63a5\u4fee\u6539 LED \u7535\u6d41\u3001\u624b\u6307\u9608\u503c\u3001\u91c7\u6837\u7a97\u53e3\u5927\u5c0f&#xff1b;<\/li>\n<li>\u4ee3\u7801\u5185\u90e8\u6ce8\u91ca\u5b8c\u6574&#xff0c;\u6bcf\u4e00\u6b65\u5bc4\u5b58\u5668\u64cd\u4f5c\u3001\u7b97\u6cd5\u5904\u7406\u5747\u6807\u6ce8\u8bf4\u660e&#xff1b;<\/li>\n<li>\u4e0b\u8f7d\u7a0b\u5e8f\u540e\u65e0\u9700\u989d\u5916\u4fee\u6539\u53c2\u6570\u5373\u53ef\u76f4\u63a5\u4e0a\u7535\u6d4b\u8bd5&#xff0c;\u51fa\u73b0\u6570\u503c\u9971\u548c\u3001\u7075\u654f\u5ea6\u4e0d\u8db3\u518d\u5fae\u8c03 LED \u7535\u6d41\u5bc4\u5b58\u5668\u503c\u3002<\/li>\n<h3>\u4e5d\u3001\u6d4b\u91cf\u8bef\u5dee\u4e0e\u73af\u5883\u5f71\u54cd\u4f18\u5316\u65b9\u6848<\/h3>\n<h4>9.1 \u5f71\u54cd\u6d4b\u91cf\u7cbe\u5ea6\u7684\u5e38\u89c1\u56e0\u7d20<\/h4>\n<li>\u80a2\u4f53\u6643\u52a8&#xff1a;\u8fd0\u52a8\u4f2a\u5dee\u5e45\u503c\u8fdc\u5927\u4e8e\u8109\u640f\u4fe1\u53f7&#xff0c;\u662f\u6570\u503c\u8df3\u53d8\u6700\u4e3b\u8981\u539f\u56e0&#xff1b;<\/li>\n<li>\u6f0f\u5149&#xff1a;\u624b\u6307\u672a\u5b8c\u5168\u76d6\u4f4f\u5149\u5b66\u7a97\u53e3&#xff0c;\u73af\u5883\u5149\u6df7\u5165\u5149\u7535\u4e8c\u6781\u7ba1&#xff1b;<\/li>\n<li>\u6309\u538b\u529b\u5ea6&#xff1a;\u8fc7\u8f7b\u4fe1\u53f7\u4e0d\u7a33&#xff0c;\u8fc7\u91cd\u538b\u8feb\u8840\u7ba1\u524a\u5f31\u8109\u640f\u6ce2\u52a8&#xff1b;<\/li>\n<li>\u672b\u68a2\u5faa\u73af&#xff1a;\u4f4e\u6e29\u624b\u6307\u8840\u6d41\u5f31&#xff0c;\u4ea4\u6d41\u8109\u640f\u5206\u91cf\u6781\u5c0f&#xff1b;<\/li>\n<li>\u5916\u90e8\u5149\u8def&#xff1a;\u6df1\u8272\u6307\u7532\u6cb9\u3001\u539a\u76ae\u80a4\u3001\u4f20\u611f\u5668\u4e0e\u76ae\u80a4\u95f4\u8ddd\u90fd\u4f1a\u6539\u53d8\u5149\u7ebf\u53cd\u5c04\u91cf&#xff1b;<\/li>\n<li>\u786c\u4ef6\u901a\u4fe1&#xff1a;I2C \u865a\u63a5\u3001\u7f3a\u5c11\u4e0a\u62c9\u7535\u963b\u3001\u7535\u6e90\u7eb9\u6ce2\u9020\u6210\u91c7\u6837\u6570\u636e\u9519\u4e71\u3002<\/li>\n<h4>9.2 \u4f18\u5316\u8c03\u8bd5\u65b9\u6cd5<\/h4>\n<li>\u51fa\u73b0 IR \u6570\u503c\u9971\u548c&#xff08;\u63a5\u8fd1 262143&#xff09;&#xff1a;\u964d\u4f4e LED1_PA\u3001LED2_PA \u5bc4\u5b58\u5668\u7535\u6d41\u503c&#xff1b;<\/li>\n<li>\u7ecf\u5e38\u63d0\u793a IR LOW\u3001\u65e0\u6709\u6548\u91c7\u6837&#xff1a;\u9002\u5f53\u63d0\u9ad8 LED \u9a71\u52a8\u7535\u6d41&#xff0c;\u6216\u964d\u4f4e\u624b\u6307\u9608\u503c\u5b8f&#xff1b;<\/li>\n<li>\u6570\u503c\u9891\u7e41\u8df3\u53d8&#xff1a;\u589e\u5927\u6700\u5c0f\u5cf0\u95f4\u8ddd\u53c2\u6570&#xff0c;\u5ef6\u957f\u6ce2\u5f62\u91c7\u6837\u7a97\u53e3\u957f\u5ea6&#xff1b;<\/li>\n<li>I2C \u8bfb\u53d6\u4e0d\u7a33\u5b9a&#xff1a;\u589e\u52a0 4.7k \u5916\u90e8\u4e0a\u62c9\u7535\u963b&#xff0c;\u91cd\u65b0\u68c0\u67e5\u5171\u5730\u63a5\u7ebf\u3002<\/li>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00<br \/>\n\u672c\u7bc7\u57fa\u4e8e STM32F103C8T6 \u4e3b\u63a7\u642d\u914d MAX30102 \u5149\u7535\u8840\u6c27\u5fc3\u7387\u4f20\u611f\u5668\u30010.96 \u5bf8 I2C OLED \u663e\u793a\u5c4f\u5b8c\u6210\u6574\u5957\u8109\u640f\u8840\u6c27\u91c7\u96c6\u5de5\u7a0b&#xff0c;\u5168\u7a0b\u4f7f\u7528\u8f6f\u4ef6 I2C \u901a\u4fe1&#xff0c;\u5206\u5f00\u4e24\u8def I2C \u603b\u7ebf\u5206\u522b\u9a71\u52a8\u4f20\u611f\u5668\u4e0e\u5c4f\u5e55&#xff0c;\u89c4\u907f\u603b\u7ebf\u51b2\u7a81\u95ee\u9898\u3002\u6587\u7ae0\u5b8c\u6574\u62c6\u89e3\u786c\u4ef6\u63a5\u7ebf\u3001\u5149\u5b66\u68c0\u6d4b\u539f\u7406\u3001\u5bc4\u5b58\u5668\u914d\u7f6e\u3001FIFO \u6570\u636e\u8bfb\u53d6\u3001\u5fc3\u7387\u8840\u6c27\u7b97\u6cd5\u3001\u5b9e\u7269\u8c03\u8bd5\u3001\u5b8c\u6574\u6e90\u7801\u6a21\u5757&#xff0c;\u9002\u5408\u5d4c\u5165\u5f0f\u521d\u5b66\u8005\u3001\u8bfe\u7a0b\u8bbe\u8ba1\u3001\u7535\u5b50\u7ade\u8d5b\u76f4\u63a5\u53c2\u8003\u3002 \u91cd\u8981\u8bf4\u660e&amp;#xff1a<\/p>\n","protected":false},"author":2,"featured_media":94906,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[10187,10885,10886,217,270,269],"topic":[],"class_list":["post-94910","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-codingplan","tag-max30102","tag-10886","tag-stm32","tag-270","tag-269"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/94910.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u524d\u8a00 \u672c\u7bc7\u57fa\u4e8e STM32F103C8T6 \u4e3b\u63a7\u642d\u914d MAX30102 \u5149\u7535\u8840\u6c27\u5fc3\u7387\u4f20\u611f\u5668\u30010.96 \u5bf8 I2C OLED \u663e\u793a\u5c4f\u5b8c\u6210\u6574\u5957\u8109\u640f\u8840\u6c27\u91c7\u96c6\u5de5\u7a0b&#xff0c;\u5168\u7a0b\u4f7f\u7528\u8f6f\u4ef6 I2C \u901a\u4fe1&#xff0c;\u5206\u5f00\u4e24\u8def I2C \u603b\u7ebf\u5206\u522b\u9a71\u52a8\u4f20\u611f\u5668\u4e0e\u5c4f\u5e55&#xff0c;\u89c4\u907f\u603b\u7ebf\u51b2\u7a81\u95ee\u9898\u3002\u6587\u7ae0\u5b8c\u6574\u62c6\u89e3\u786c\u4ef6\u63a5\u7ebf\u3001\u5149\u5b66\u68c0\u6d4b\u539f\u7406\u3001\u5bc4\u5b58\u5668\u914d\u7f6e\u3001FIFO \u6570\u636e\u8bfb\u53d6\u3001\u5fc3\u7387\u8840\u6c27\u7b97\u6cd5\u3001\u5b9e\u7269\u8c03\u8bd5\u3001\u5b8c\u6574\u6e90\u7801\u6a21\u5757&#xff0c;\u9002\u5408\u5d4c\u5165\u5f0f\u521d\u5b66\u8005\u3001\u8bfe\u7a0b\u8bbe\u8ba1\u3001\u7535\u5b50\u7ade\u8d5b\u76f4\u63a5\u53c2\u8003\u3002 \u91cd\u8981\u8bf4\u660e&amp;#xff1a\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/94910.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-15T10:25:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e962a257.png\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/94910.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/94910.html\",\"name\":\"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-08-15T10:25:28+00:00\",\"dateModified\":\"2026-08-15T10:25:28+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/94910.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/94910.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/94910.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/94910.html","og_locale":"zh_CN","og_type":"article","og_title":"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u524d\u8a00 \u672c\u7bc7\u57fa\u4e8e STM32F103C8T6 \u4e3b\u63a7\u642d\u914d MAX30102 \u5149\u7535\u8840\u6c27\u5fc3\u7387\u4f20\u611f\u5668\u30010.96 \u5bf8 I2C OLED \u663e\u793a\u5c4f\u5b8c\u6210\u6574\u5957\u8109\u640f\u8840\u6c27\u91c7\u96c6\u5de5\u7a0b&#xff0c;\u5168\u7a0b\u4f7f\u7528\u8f6f\u4ef6 I2C \u901a\u4fe1&#xff0c;\u5206\u5f00\u4e24\u8def I2C \u603b\u7ebf\u5206\u522b\u9a71\u52a8\u4f20\u611f\u5668\u4e0e\u5c4f\u5e55&#xff0c;\u89c4\u907f\u603b\u7ebf\u51b2\u7a81\u95ee\u9898\u3002\u6587\u7ae0\u5b8c\u6574\u62c6\u89e3\u786c\u4ef6\u63a5\u7ebf\u3001\u5149\u5b66\u68c0\u6d4b\u539f\u7406\u3001\u5bc4\u5b58\u5668\u914d\u7f6e\u3001FIFO \u6570\u636e\u8bfb\u53d6\u3001\u5fc3\u7387\u8840\u6c27\u7b97\u6cd5\u3001\u5b9e\u7269\u8c03\u8bd5\u3001\u5b8c\u6574\u6e90\u7801\u6a21\u5757&#xff0c;\u9002\u5408\u5d4c\u5165\u5f0f\u521d\u5b66\u8005\u3001\u8bfe\u7a0b\u8bbe\u8ba1\u3001\u7535\u5b50\u7ade\u8d5b\u76f4\u63a5\u53c2\u8003\u3002 \u91cd\u8981\u8bf4\u660e&amp;#xff1a","og_url":"https:\/\/www.wsisp.com\/helps\/94910.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-08-15T10:25:28+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/08\/20260815102526-6a803e962a257.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"20 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/94910.html","url":"https:\/\/www.wsisp.com\/helps\/94910.html","name":"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-08-15T10:25:28+00:00","dateModified":"2026-08-15T10:25:28+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/94910.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/94910.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/94910.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"STM32F103\u9a71\u52a8MAX30102\u8840\u6c27\u5fc3\u7387\u68c0\u6d4b\u5b8c\u6574\u6559\u7a0b\uff08\u542bOLED\u663e\u793a\u3001\u8f6f\u4ef6I2C\u6e90\u7801\uff09"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/94910","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=94910"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/94910\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/94906"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=94910"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=94910"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=94910"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=94910"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}