This post was last edited by hehung on 2019-8-3 17:35
The LIS2MDL is a magnetic field sensor.
Here is the schematic:
The schematic diagram shows that the address of IIC is 0x3C.
The first step is to look at the data sheet:
Register Summary:
Some of the more important registers are:
WHO_AM_I Register , Identity Register: 0x40:
Configuration register CFG_REG_A : If temperature compensation is required, bit 7 needs to be set to 1, otherwise the value read from the temperature register is always 0.
If continuous reading is required, bits MD1 and MD0 need to be set to 0. The default is 1. Otherwise, it is in idle mode and the data will not be updated.
XYZ output data register, just read the register value directly.
Note: Because the data is signed and 16 bits long, the returned data type must be set to short, not int, otherwise it will not be a negative number. Short is a 16-bit type and can directly display a negative sign.
The temperature register, for some reason, always displays a temperature very different from the actual temperature. It says it is the internal temperature, but I don't know what temperature value it is.
Code:
initialization:
//初始化传感器LIS2MDL
if(0 == Set_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_A, 0x80))
{
send_str((unsigned char *)"IF_CTRL set successful\r\n");
}
else
{
send_str((unsigned char *)"IF_CTRL set fail\r\n");
}
if(0 == Set_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_C, 0x10))
{
send_str((unsigned char *)"IF_CTRL set successful\r\n");
}
else
{
send_str((unsigned char *)"IF_CTRL set fail\r\n");
}
Data acquisition and serial port display::
//LIS2MDL写
static int IIC_WrDat_LIS2MDL(uint8_t IIC_Add, uint8_t IIC_Reg, uint8_t IIC_Data)
{
uint8_t ret_suc = 1;
IIC_Start();
IIC_Send_Byte(IIC_Add & 0xfe);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Send_Byte(IIC_Reg); //write data
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Send_Byte(IIC_Data);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Stop();
return 0;
}
//LIS2MDL读
static int IIC_Read_LIS2MDL(uint8_t IIC_Add, uint8_t IIC_Reg)
{
int ret;
uint8_t ret_suc = 1;
IIC_Start();
IIC_Send_Byte(IIC_Add & 0xfe);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Send_Byte(IIC_Reg);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Start();
IIC_Send_Byte(IIC_Add | 0x01);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
ret=IIC_Read_Byte(0);
IIC_Stop();
return ret;
}
//LIS2MDL读2个寄存器
static int IIC_Read2_LIS2MDL(uint8_t IIC_Add, uint8_t IIC_Reg)
{
int ret;
uint8_t ret_suc = 1;
IIC_Start();
IIC_Send_Byte(IIC_Add & 0xfe);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Send_Byte(IIC_Reg);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
IIC_Start();
IIC_Send_Byte(IIC_Add | 0x01);
ret_suc = IIC_Wait_Ack();
if(ret_suc == 1) {IIC_Stop();return -1;}
ret=IIC_Read_Byte(1);
ret=(IIC_Read_Byte(0)<<8)|ret;
IIC_Stop();
return ret;
}
//设置寄存器
int Set_Reg_LIS2MDL(uint8_t add, uint8_t reg, uint8_t dat)
{
int ret_succ = -1;
uint8_t i = 20u; //失败之后尝试的次数
do{
if(0 == IIC_WrDat_LIS2MDL(add, reg, dat))
{
ret_succ = 0; //设置成功
break;
}
else
{
i--; //获取失败,再次尝试
}
}while(i>0u);
return ret_succ;
}
//读取寄存器
int Get_Reg_LIS2MDL(uint8_t add, uint8_t reg)
{
uint8_t i = 20u;
int ret_get = -1;
do{
ret_get = IIC_Read_LIS2MDL(add, reg);
if(-1 != ret_get)
{
break; //获取数据成功
}
else
{
i--; //获取失败,再次尝试
}
}while(i>0u);
return ret_get;
}
//读取我是谁
int Get_WHO_AM_I_LIS2MDL(void)
{
return Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_REG_WHO_AM_I);
}
//获取状态寄存器
int Get_Status_LIS2MDL(void)
{
return Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_STATUS);
}
short GET_X_LIS2MDL(void)
{
return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTX_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTX_L));
}
short GET_Y_LIS2MDL(void)
{
return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTY_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTY_L));
}
short GET_Z_LIS2MDL(void)
{
return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTZ_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTZ_L));
}
short Get_Temp_LIS2MDL(void)
{
return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_TEMP_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_TEMP_L));
}
//发送数据到串口
void Send_Uart_LIS2MDL(void)
{
char str[35] = {0};
send_str((uint8_t *)"<-----------START--------->\r\n");
sprintf(str,"X:%d | Y:%d | Z:%d\r\n", GET_X_LIS2MDL(),GET_Y_LIS2MDL(),GET_Z_LIS2MDL());
send_str((uint8_t *)str);
sprintf(str,"Temp:%d\r\n", Get_Temp_LIS2MDL());
send_str((uint8_t *)str);
sprintf(str,"Status:0x%X\r\n", Get_Status_LIS2MDL());
send_str((uint8_t *)str);
sprintf(str,"Who_am_i:%X\r\n",Get_WHO_AM_I_LIS2MDL());
send_str((uint8_t *)str);
send_str((uint8_t *)"<------------END---------->\r\n\n");
}
Macro definition:
/*register address*/
#define LIS2MDL_OFFSET_X_REG_L (0x45U)
#define LIS2MDL_OFFSET_X_REG_H (0x46U)
#define LIS2MDL_OFFSET_Y_REG_L (0x47U)
#define LIS2MDL_OFFSET_Y_REG_H (0x48U)
#define LIS2MDL_OFFSET_Z_REG_L (0x49U)
#define LIS2MDL_OFFSET_Z_REG_H (0x4AU)
#define LIS2MDL_REG_WHO_AM_I (0x4FU)
#define LIS2MDL_CFG_A (0x60U)
#define LIS2MDL_CFG_B (0x61U)
#define LIS2MDL_CFG_C (0x62U)
#define LIS2MDL_CFG_INT_CTRL (0x63U)
#define LIS2MDL_CFG_SOURCE (0x64U)
#define LIS2MDL_CFG_THS_L (0x65U)
#define LIS2MDL_CFG_THS_H (0x66U)
#define LIS2MDL_CFG_STATUS (0x67U)
#define LIS2MDL_OUTX_L (0x68U)
#define LIS2MDL_OUTX_H (0x69U)
#define LIS2MDL_OUTY_L (0x6AU)
#define LIS2MDL_OUTY_H (0x6BU)
#define LIS2MDL_OUTZ_L (0x6CU)
#define LIS2MDL_OUTZ_H (0x6DU)
#define LIS2MDL_TEMP_L (0x6EU)
#define LIS2MDL_TEMP_H (0x6FU)
/*IIC slave address write and read*/
/*SD0 connect to power supply*/
#define LIS2MDL_ADDR_W_1 0x3CU
#define LIS2MDL_ADDR_R_1 0x3DU
Display the results. Turn the board to different states and positions to display different numbers:
|