- #include <reg52.h>
- #include <intrins.h>
- #include <stdio.h>
- #define uint unsigned int
- #define uchar unsigned char
- // 定義心率引腳
- sbit SCL = P3^3;
- sbit SDA = P3^4;
- sbit INT = P3^2;
- // 定義MAX30102的I2C地址
- #define MAX30102_ADDR 0xAE
- // 定義 MAX30102 寄存器地址
- #define REG_INTR_STATUS_1 0x00
- #define REG_INTR_STATUS_2 0x01
- #define REG_INTR_ENABLE_1 0x02
- #define REG_INTR_ENABLE_2 0x03
- #define REG_FIFO_WR_PTR 0x04
- #define REG_OVF_COUNTER 0x05
- #define REG_FIFO_RD_PTR 0x06
- #define REG_FIFO_DATA 0x07
- #define REG_FIFO_CONFIG 0x08
- #define REG_MODE_CONFIG 0x09
- #define REG_SPO2_CONFIG 0x0A
- #define REG_LED1_PA 0x0C
- #define REG_LED2_PA 0x0D
- #define REG_PILOT_PA 0x10
- #define REG_MULTI_LED_CTRL1 0x11
- #define REG_MULTI_LED_CTRL2 0x12
- #define REG_TEMP_INTR 0x1F
- #define REG_TEMP_FRAC 0x20
- #define REG_TEMP_CONFIG 0x21
- #define REG_PROX_INT_THRESH 0x30
- #define REG_REV_ID 0xFE
- #define REG_PART_ID 0xFF
- // 全局變量用于心率計算
- unsigned int pulse_count = 0;
- unsigned int prev_pulse_count = 0;
- unsigned int heart_rate = 0;
- uint count; // 計數
- bit flag_1s = 0;
- unsigned int one_second_count = 0;
- // 微秒級延時函數
- void delay(uint t) // @12T 1us
- {
- while (t--);
- }
- // I2C起始信號
- void I2C_Start() {
- SDA = 1;
- SCL = 1;
- delay(1);
- SDA = 0;
- delay(1);
- SCL = 0;
- }
- // I2C停止信號
- void I2C_Stop() {
- SDA = 0;
- SCL = 1;
- delay(1);
- SDA = 1;
- delay(1);
- }
- // I2C發送一個字節
- void I2C_SendByte(unsigned char dat) {
- unsigned char i;
- for (i = 0; i < 8; i++) {
- SDA = (dat & 0x80) >> 7;
- dat <<= 1;
- SCL = 1;
- delay(1);
- SCL = 0;
- delay(1);
- }
- }
- // I2C接收一個字節
- unsigned char I2C_ReceiveByte() {
- unsigned char i, dat = 0;
- SDA = 1;
- for (i = 0; i < 8; i++) {
- SCL = 1;
- dat <<= 1;
- if (SDA) dat |= 0x01;
- SCL = 0;
- delay(1);
- }
- return dat;
- }
- // I2C發送應答信號
- void I2C_SendAck(bit ack) {
- SDA = ack;
- SCL = 1;
- delay(1);
- SCL = 0;
- delay(1);
- }
- // I2C接收應答信號
- bit I2C_ReceiveAck() {
- bit ack;
- SDA = 1;
- SCL = 1;
- ack = SDA;
- SCL = 0;
- delay(1);
- return ack;
- }
- // 向MAX30102寫一個字節數據
- bit MAX30102_WriteByte(unsigned char reg, unsigned char dat) {
- I2C_Start();
- I2C_SendByte(MAX30102_ADDR & 0xFE); // 寫地址
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- I2C_SendByte(reg);
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- I2C_SendByte(dat);
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- I2C_Stop();
- return 1;
- }
- // 從MAX30102讀一個字節數據
- bit MAX30102_ReadByte(unsigned char reg, unsigned char *dat) {
- I2C_Start();
- I2C_SendByte(MAX30102_ADDR & 0xFE); // 寫地址
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- I2C_SendByte(reg);
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- I2C_Start();
- I2C_SendByte(MAX30102_ADDR | 0x01); // 讀地址
- if (I2C_ReceiveAck()) {
- I2C_Stop();
- return 0;
- }
- *dat = I2C_ReceiveByte();
- I2C_SendAck(1); // 非應答
- I2C_Stop();
- return 1;
- }
- // 初始化MAX30102
- bit MAX30102_Init() {
- unsigned char reg_val;
- if (!MAX30102_WriteByte(REG_MODE_CONFIG, 0x40)) return 0; // 復位 MAX30102
- do {
- if (!MAX30102_ReadByte(REG_MODE_CONFIG, ®_val)) return 0;
- } while (reg_val & 0x40);
- if (!MAX30102_WriteByte(REG_FIFO_CONFIG, 0x00)) return 0; // 設置 FIFO 配置
- if (!MAX30102_WriteByte(REG_MODE_CONFIG, 0x02)) return 0; // 設置模式配置為心率模式
- if (!MAX30102_WriteByte(REG_SPO2_CONFIG, 0x27)) return 0; // 設置 SpO2 配置
- if (!MAX30102_WriteByte(REG_LED1_PA, 0x2F)) return 0; // 設置 LED 強度
- if (!MAX30102_WriteByte(REG_LED2_PA, 0x2F)) return 0;
- return 1;
- }
- // 讀取 FIFO 數據
- bit MAX30102_ReadFIFO(unsigned long *data) {
- unsigned char byte1, byte2, byte3;
- if (!MAX30102_ReadByte(REG_FIFO_DATA, &byte1)) return 0;
- if (!MAX30102_ReadByte(REG_FIFO_DATA, &byte2)) return 0;
- if (!MAX30102_ReadByte(REG_FIFO_DATA, &byte3)) return 0;
- *data = ((unsigned long)byte1 << 16) | ((unsigned long)byte2 << 8) | (unsigned long)byte3;
- return 1;
- }
- // 簡單的心率計算
- int calculateHeartRate(unsigned long *data, int size) {
- int peaks = 0;
- int i;
- for (i = 1; i < size - 1; i++) {
- if (data[i] > data[i - 1] && data[i] > data[i + 1]) {
- peaks++;
- }
- }
- // 簡單估算心率,假設采樣率為 100Hz
- int heartRate = peaks * 60 / (size / 100);
- return heartRate;
- }
- // 定時器0初始化函數
- void InitTimer0(void)
- {
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x18;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- // 外部中斷 0 服務函數,用于檢測心率脈沖
- void External0_ISR() interrupt 0
- {
- static uint last_time = 0;
- uint current_time = count;
- if (current_time - last_time > 20) // 消抖處理,20ms
- {
- pulse_count++;
- last_time = current_time;
- }
- }
- // 定時器0中斷服務函數
- void Timer0Interrupt() interrupt 1
- {
- static uint i;
- TH0 = 0xFC;
- TL0 = 0x18;
- count++;
- i++;
- one_second_count++;
- if (one_second_count >= 1000) // 1秒
- {
- one_second_count = 0;
- flag_1s = 1;
- }
- }
- // 主程序
- unsigned long fifoData[1000]; // 定義為全局變量以減小 main 函數自動段大小
- void main()
- {
- int i;
- // 初始化定時器0
- InitTimer0();
- // 初始化外部中斷 0
- IT0 = 1; // 下降沿觸發
- EX0 = 1; // 使能外部中斷 0
- EA = 1; // 使能全局中斷
- IE0 = 0; // INT0中斷請求標志清0
- // 初始化MAX30102
- if (!MAX30102_Init()) {
- while (1);
- }
- // 讀取FIFO數據
- for (i = 0; i < 1000; i++) {
- if (!MAX30102_ReadFIFO(&fifoData[i])) {
- while (1);
- }
- }
- // 計算初始心率
- heart_rate = calculateHeartRate(fifoData, 1000);
- while (1)
- {
- if (flag_1s) // 1秒
- {
- flag_1s = 0;
- heart_rate = pulse_count * 60; // 計算心率
- pulse_count = 0; // 清零脈沖計數
- }
復制代碼
編譯能過,心率沒有數據
|