From 752c2a7ea2707736b8b67c74252ed3a26ddba734 Mon Sep 17 00:00:00 2001 From: yelvlab Date: Wed, 9 Oct 2024 22:39:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9mlx90614=EF=BC=8C=E6=9C=AA?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mlx90614.c | 260 ++++++++++++++----------------------------------- 1 file changed, 75 insertions(+), 185 deletions(-) diff --git a/src/mlx90614.c b/src/mlx90614.c index 9f2061b..b823886 100644 --- a/src/mlx90614.c +++ b/src/mlx90614.c @@ -7,7 +7,8 @@ #include "systick.h" #include -void i2c_config(void) { +void i2c_config(void) +{ rcu_periph_clock_enable(RCU_IR_GPIO); rcu_periph_clock_enable(RCU_I2C); @@ -27,192 +28,81 @@ void i2c_config(void) { i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); } -uint32_t read_ir_mlx90614(void) { - uint8_t Data[5]; +uint32_t read_ir_mlx90614(void) +{ + uint8_t Data[3] = {0}; uint32_t inttemp_ir = 0; - uint32_t TIMEOUT = 0; - - uint8_t state = I2C_START; - uint8_t read_cycle = 0; uint16_t timeout = 0; - uint8_t i2c_timeout_flag = 0; - i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); - while (!(i2c_timeout_flag)) - { - switch (state) - { - case I2C_START: - if(RESET == read_cycle) - { - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(IR_I2C, I2C_FLAG_I2CBSY) && (timeout < i2c_timeout_flag)) - { - timeout ++; - } - if(timeout < I2C_TIME_OUT) - { - /* whether to send ACK or not for the next byte */ - if(2 == RegisterLen) { - i2c_ackpos_config(IR_I2C, I2C_ACKPOS_NEXT); - } - } else { - i2c_bus_reset(); - timeout = 0; - state = I2C_START; - printf("i2c bus is busy in READ!\n"); - } - } - /* send the start signal */ - i2c_start_on_bus(IR_I2C); - timeout = 0; - state = I2C_SEND_ADDR; - break; - - case I2C_SEND_ADDR: - /* i2c master sends START signal successfully */ - while((!i2c_flag_get(IR_I2C, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) - { - timeout++; - } - if(timeout < I2C_TIME_OUT) - { - if(RESET == read_cycle) - { - i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_TRANSMITTER); - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_RECEIVER); - if(RegisterLen < 3) { - /* disable acknowledge */ - i2c_ack_config(IR_I2C, I2C_ACK_DISABLE); - } - state = I2C_CLEAR_ADDRESS_FLAG; - } - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master sends start signal timeout in READ!\n"); - } - break; - - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while((!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) - { - timeout++; - } - if(timeout < I2C_TIME_OUT) - { - i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); - if((SET == read_cycle) && (1 == RegisterLen)) { - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(IR_I2C); - } - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master clears address flag timeout in READ!\n"); - } - break; - - case I2C_TRANSMIT_DATA: - if(RESET == read_cycle) { - /* wait until the transmit data buffer is empty */ - while((!i2c_flag_get(IR_I2C, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if(timeout < I2C_TIME_OUT) { - /* send the EEPROM's internal address to write to : only one byte address */ - i2c_data_transmit(IR_I2C, RegisterAddr); - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master wait data buffer is empty timeout in READ!\n"); - } - /* wait until BTC bit is set */ - while((!i2c_flag_get(IR_I2C, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if(timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_START; - read_cycle++; - } else { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master sends i2c_master_read_register1 internal address timeout in READ!\n"); - } - } else { - while(RegisterLen) { - timeout++; - if(3 == RegisterLen) { - /* wait until BTC bit is set */ - while(!i2c_flag_get(IR_I2C, I2C_FLAG_BTC)); - /* disable acknowledge */ - i2c_ack_config(IR_I2C, I2C_ACK_DISABLE); - } - if(2 == RegisterLen) { - /* wait until BTC bit is set */ - while(!i2c_flag_get(IR_I2C, I2C_FLAG_BTC)); - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(IR_I2C); - } - /* wait until RBNE bit is set */ - if(i2c_flag_get(IR_I2C, I2C_FLAG_RBNE)) { - /* read a byte from the EEPROM */ - *RegisterValue = i2c_data_receive(IR_I2C); - /* point to the next location where the byte read will be saved */ - RegisterValue++; - /* decrement the read bytes counter */ - RegisterLen--; - timeout = 0; - } - if(timeout > I2C_TIME_OUT) { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master sends data timeout in READ!\n"); - } - } - timeout = 0; - state = I2C_STOP; - } - break; - - case I2C_STOP: - /* i2c master sends STOP signal successfully */ - while((I2C_CTL0(IR_I2C) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if(timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - i2c_timeout_flag = I2C_OK; - } else { - timeout = 0; - state = I2C_START; - read_cycle = 0; - printf("i2c master sends stop signal timeout in READ!\n"); - } - break; - - default: - state = I2C_START; - read_cycle = 0; - i2c_timeout_flag = I2C_OK; - timeout = 0; - printf("i2c master sends start signal in READ.\n"); - break; - } + // 发送起始信号 + i2c_start_on_bus(IR_I2C); + while(i2c_flag_get(IR_I2C, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; } - return IIC_SUCCESS; + if (timeout >= I2C_TIME_OUT) { + return -41001; // 超时返回错误 + } + + // 发送从机地址和写操作位 + i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_TRANSMITTER); + while(!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + return -41002; // 超时返回错误 + } + i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); + + // 发送寄存器地址 + i2c_data_transmit(IR_I2C, REG_ADDR_OBJ_TEMP); + while(!i2c_flag_get(IR_I2C, I2C_FLAG_TBE) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + return -41003; // 超时返回错误 + } + + // 重复起始信号 + i2c_start_on_bus(IR_I2C); + while(i2c_flag_get(IR_I2C, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + return -41004; // 超时返回错误 + } + + // 发送从机地址和读操作位 + i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_RECEIVER); + while(!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + return -41005; // 超时返回错误 + } + i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); + + // 读取数据 + for (int i = 0; i < 3; i++) { + while(!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + return -41006; // 超时返回错误 + } + Data[i] = i2c_data_receive(IR_I2C); + if (i < 2) { + i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); + } else { + i2c_ack_config(IR_I2C, I2C_ACK_DISABLE); + } + timeout = 0; + } + + // 发送停止信号 + i2c_stop_on_bus(IR_I2C); + + // 计算温度 + inttemp_ir = ((uint16_t)(Data[1] << 8) | Data[0]) * 2 -27315; + + return inttemp_ir; // 返回温度值 }