Implemented more I2C functions and started to write the driver for the QMC5883L magnetometer

This commit is contained in:
anschrammh 2022-12-14 08:20:17 +01:00
parent b90d14fb79
commit 5fb5c57495
4 changed files with 161 additions and 5 deletions

View File

@ -0,0 +1,59 @@
#include "i2c.h"
#include "QMC5883L.h"
bool QMC5883L_init(void)
{
return i2c_write_reg(QMC5883L_I2C_ADDR, QMC5883L_SETRES_REG, 0x01);
}
float QMC5883L_get_temperature(void)
{
uint8_t data;
int16_t raw_temp;
i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_MSB_REG, &data);
raw_temp = data << 8;
i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_LSB_REG, &data);
raw_temp |= data;
return (float) raw_temp / 100.0;
}
bool QMC5883L_is_data_available(void)
{
uint8_t data;
i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_STATUS_REG, &data);
return data & QMC5883L_DRDY_BIT ? true : false;
}
QMC5883L_MData_t QMC5883L_get_MFields(void)
{
uint8_t data[6];
QMC5883L_MData_t Mdata = {.MFieldX = -1, .MFieldY = -1, .MFieldZ = -1};
if(i2c_read(QMC5883L_I2C_ADDR, QMC5883L_DATA_X_LSB_REG, data, sizeof data))
{
Mdata.MFieldX = (data[1] << 8) | data[0];
Mdata.MFieldY = (data[3] << 8) | data[2];
Mdata.MFieldZ = (data[5] << 8) | data[4];
}
return Mdata;
}
bool QMC5883L_set_power_mode(QMC5883L_Mode_Control_e MC)
{
uint8_t data;
if(!i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_CTRL1_REG, &data))return false;
data &= 0xFC;
data |= MC;
return i2c_write_reg(QMC5883L_I2C_ADDR, QMC5883L_CTRL1_REG, data);
}

View File

@ -0,0 +1,78 @@
#ifndef QMC5883L_H
#define QMC5883L_H
/* Device i2c address */
#define QMC5883L_I2C_ADDR 0x0D
/* Device registers list */
#define QMC5883L_DATA_X_LSB_REG 0x00
#define QMC5883L_STATUS_REG 0x06
#define QMC5883L_TEMP_LSB_REG 0x07
#define QMC5883L_TEMP_MSB_REG 0x08
#define QMC5883L_CTRL1_REG 0x09
#define QMC5883L_CTRL2_REG 0x0A
#define QMC5883L_SETRES_REG 0x0B
/* Field masks */
#define QMC5883L_DRDY_BIT 0x01
#define QMC5883L_OVL_BIT 0x02
#define QMC5883L_DOR_BIT 0x04
/* Configuration enumerations */
typedef enum
{
Standby = 0,
Continuous = 1,
} QMC5883L_Mode_Control_e;
typedef enum
{
ODR_10HZ = 0,
ODR_50HZ = 1,
ODR_100HZ = 2,
ODR_200HZ = 3,
} QMC5883L_Output_Data_Rate_e;
typedef enum
{
FS_2G = 0,
FS_8G = 1,
} QMC5883L_Full_Scale_e;
typedef enum
{
OSR_512 = 0,
OSR_256 = 1,
OSR_128 = 2,
OSR_64 = 3,
} QMC5883L_Over_Sample_Ratio_e;
typedef struct
{
int16_t MFieldX;
int16_t MFieldY;
int16_t MFieldZ;
} QMC5883L_MData_t;
/* QMC5883L Driver API */
bool QMC5883L_init(void);
bool QMC5883L_software_reset(void);
float QMC5883L_get_temperature(void);
bool QMC5883L_is_data_available(void);
QMC5883L_MData_t QMC5883L_get_MFields(void);
bool QMC5883L_configure_1(QMC5883L_Output_Data_Rate_e ODR, QMC5883L_Full_Scale_e RNG, QMC5883L_Over_Sample_Ratio_e OSR);
bool QMC5883L_configure_2(bool rolling_ptr, bool data_ready_int);
bool QMC5883L_set_power_mode(QMC5883L_Mode_Control_e MC);
#endif //QMC5883L_H

View File

@ -31,16 +31,31 @@ bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data)
return true; return true;
} }
bool i2c_read(uint8_t address, const uint8_t *data, size_t length, bool sendStop) bool i2c_read(uint8_t address, uint8_t reg, uint8_t * const data, size_t length)
{ {
if(!data)return false; if(!data)return false;
//First we send the address followed by the register from where we want to start reading:
tls_i2c_write_byte(address << 1, true);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
tls_i2c_write_byte(reg, false);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
tls_i2c_write_byte((address << 1) | 1, true);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
for(size_t i = 0; i < length - 1; i++ )
{
data[i] = tls_i2c_read_byte(true, false);
}
data[length - 1] = tls_i2c_read_byte(false, true);
return true; return true;
} }
bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data) bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data)
{ {
if(!data) return false;
//First we send the address followed by the register we want to read from: //First we send the address followed by the register we want to read from:
tls_i2c_write_byte(address << 1, true); tls_i2c_write_byte(address << 1, true);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false; if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
@ -49,7 +64,9 @@ bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data)
tls_i2c_write_byte((address << 1) | 1, true); tls_i2c_write_byte((address << 1) | 1, true);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false; if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
*data = tls_i2c_read_byte(false, true);
uint8_t val = tls_i2c_read_byte(false, true);
if(data) *data = val;
return true; return true;
} }

View File

@ -1,16 +1,18 @@
#ifndef I2C_H #ifndef I2C_H
#define I2C_H #define I2C_H
#include <stdint.h>
#include <stddef.h>
#include "wm_type_def.h" #include "wm_type_def.h"
#include "wm_io.h" #include "wm_io.h"
void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency); void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency);
bool i2c_write(uint8_t address, const uint8_t *data, size_t length, bool sendStop); //bool i2c_write(uint8_t address, const uint8_t *data, size_t length);
bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data); bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data);
bool i2c_read(uint8_t address, const uint8_t *data, size_t length, bool sendStop); bool i2c_read(uint8_t address, uint8_t reg, uint8_t * const data, size_t length);
bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data); bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data);