最近需要使用磁传感器,之前使用的是HMC5883,不过这次买的是LSM303D,记录一下。使用的单片机是STM32F407,模拟iic,正点原子的库。
数据手册参考的是:https://item.szlcsc.com/2776949.html
代码参考的是:https://blog.youkuaiyun.com/cp1300/article/details/75644988
修改的代码如下
#include "lsm303.h"
#include "delay.h"
#include "usart.h"
#include "myiic.h"
//参考手册25页
// 磁传感器那部分地址是写是0x3c, 读是0x3d. 加速度的应该是0x30跟0x31或者0x32和0x33
#define SlaveAddr_A 0x32
#define SlaveAddr_M 0x3C
// 传感器初始化
u8 LSM303DLH_Init()
{
u8 temp;
u8 retry = 0;
IIC_Init();//iic引脚初始化.直接使用正点原子的库,修改相对应的引脚即可.
for(retry = 0;retry < 3;retry ++)
{
LSM303DLH_WriteOneReg(LSM303_CTRL_REG1_A_0x20, 0x27); //正常模式,50Hz速度
delay_ms(3); //延时3ms
temp = LSM303DLH_ReadOneReg(LSM303_CTRL_REG1_A_0x20); //读取0x20寄存器,默认值为0x07
if(temp != 0x27) //值不对
{
printf("初始化失败,LSM303_CTRL_REG1_A_0x20默认值错误:0x%02X\r\n", temp);
delay_ms(10);
}
else break;
}
if(temp != 0x27) //值不对
{
return FALSE;
}
delay_ms(1); //延时1ms
for(retry = 0;retry < 3;retry ++)
{
LSM303DLH_WriteOneReg(LSM303_CRA_REG_M_0x00, 0x30); //磁场传感器30Hz,正常测量
delay_ms(1); //延时1ms
LSM303DLH_WriteOneReg(LSM303_CRB_REG_M_0x01, 0xE0); //磁场传感器量程 +-8Gs
delay_ms(1); //延时1ms
LSM303DLH_WriteOneReg(LSM303_MR_REG_M_0x02, 0x00); //磁场传感器连续转换模式
delay_ms(1); //延时1ms
temp = LSM303DLH_ReadOneReg(LSM303_MR_REG_M_0x02);
if(temp != 0) //值不对
{
printf("初始化失败,LSM303_MR_REG_M_0x02值错误:0x%02X\r\n", temp);
delay_ms(10);
}
else break;
}
return TRUE;
}
// 读一个字节
u8 LSM303DLH_ReadOneReg(LSM303DLH_REG_TYPE RegAddr)
{
u8 data;
u8 SlaveAddr = (RegAddr>0x19)?SlaveAddr_A:SlaveAddr_M; //大于0x19的寄存器是加速度传感器
IIC_Start(); //产生IIC起始信号
IIC_Send_Byte(SlaveAddr); //发送设备地址+写信号
IIC_Wait_Ack();
IIC_Send_Byte(RegAddr); //发送寄存器地址
IIC_Wait_Ack();
IIC_Start(); //产生IIC起始信号
IIC_Send_Byte(SlaveAddr+1); //发送设备地址+读信号
IIC_Wait_Ack();
data = IIC_Read_Byte(0); //读取一个字节,不发送ack
IIC_Stop(); //产生IIC停止信号
return data;
}
// 读取多个寄存器
void LSM303DLH_ReadMultReg(LSM303DLH_REG_TYPE RegAddr, u8 RegNum, u8 DataBuff[])
{
u8 i;
u8 SlaveAddr = (RegAddr>0x19)?SlaveAddr_A:SlaveAddr_M; //大于0x19的寄存器是加速度传感器
IIC_Start();
IIC_Send_Byte(SlaveAddr); //发送设备地址+写信号
IIC_Wait_Ack();
IIC_Send_Byte(RegAddr); //发送寄存器地址,地址最高位为1意味着连续读取
IIC_Wait_Ack();
IIC_Start(); //产生IIC起始信号
IIC_Send_Byte(SlaveAddr+1); //发送设备地址+读信号
IIC_Wait_Ack();
for(i = 0;i < RegNum;i ++)
{
if(i == (RegNum-1)) //最后一字节不响应ACK
{
DataBuff[i] = IIC_Read_Byte(FALSE); //SIIC读取一个字节-NAK
}
else
{
DataBuff[i] = IIC_Read_Byte(TRUE); //SIIC读取一个字节-ACK
}
}
IIC_Stop(); //产生IIC停止信号
}
// 写一个寄存器
void LSM303DLH_WriteOneReg(LSM303DLH_REG_TYPE RegAddr,u8 data)
{
u8 SlaveAddr = (RegAddr>0x19)?SlaveAddr_A:SlaveAddr_M; //大于0x19的寄存器是加速度传感器
IIC_Start();
IIC_Send_Byte(SlaveAddr); //发送设备地址+写信号
IIC_Wait_Ack();
IIC_Send_Byte(RegAddr); //发送寄存器地址
IIC_Wait_Ack();
IIC_Send_Byte(data); //发送要写入的数据
IIC_Wait_Ack();
IIC_Stop(); //产生IIC停止信号
}
// 读磁场强度
u8 LSM303DLH_ReadMagnetic(M_Data *p_lsm303d)
{
u8 buff[6];
s16 temp;
LSM303DLH_ReadMultReg(LSM303_OUT_X_H_M_0x03, 6, buff); //读取数据
temp = buff[0];
temp<<=8;
temp|= buff[1];
p_lsm303d->x_m = temp; //X轴
temp = buff[2];
temp<<=8;
temp|= buff[3];
p_lsm303d->z_m = temp; //Z轴 在这里读取的是Y轴,但是写入z轴
//
// 虽然数据手册上写的是0x05,0x06是Y轴, 0x07,0x08是Y轴,
// 但是实际测试, 感觉应该是相反的.所以在使用的时候, 修改了一下.
// (读取的时候交换y和z轴)
//
temp = buff[4];
temp<<=8;
temp|= buff[5];
p_lsm303d->y_m = temp; //Y轴 在这里读取的是z轴,但是写入Y轴
printf("x = %f, y = %f, z = %f\r\n", p_lsm303d->x_m, p_lsm303d->y_m, p_lsm303d->z_m);
return TRUE;
}
#ifndef __LSM303_H
#define __LSM303_H
#include "sys.h"
typedef enum
{
//罗盘
LSM303_CRA_REG_M_0x00 = 0x00, //RW
LSM303_CRB_REG_M_0x01 = 0x01, //RW
LSM303_MR_REG_M_0x02 = 0x02, //RW
LSM303_OUT_X_H_M_0x03 = 0x03, //R
LSM303_OUT_X_L_M_0x04 = 0x04, //R
LSM303_OUT_Y_H_M_0x05 = 0x05, //R
LSM303_OUT_Y_L_M_0x06 = 0x06, //R
LSM303_OUT_Z_H_M_0x07 = 0x07, //R
LSM303_OUT_Z_L_M_0x08 = 0x08, //R
LSM303_SR_REG_Mg_0x09 = 0x09, //R
LSM303_IRA_REG_M_0x0A = 0x0A, //R
LSM303_IRB_REG_M_0x0B = 0x0B, //R
LSM303_IRC_REG_M_0x0C = 0x0C, //R
//加速度
LSM303_CTRL_REG1_A_0x20 = 0x20, //RW
LSM303_CTRL_REG2_A_0x21 = 0x21, //RW
LSM303_CTRL_REG3_A_0x22 = 0x22, //RW
LSM303_CTRL_REG4_A_0x23 = 0x23, //RW
LSM303_CTRL_REG5_A_0x24 = 0x24, //RW
LSM303_HP_FILTER_RESET_A_0x25 = 0x25, //R
LSM303_REFERENCE_A_0x26 = 0x26, //RW
LSM303_STATUS_REG_A_0x27 = 0x27, //R
LSM303_OUT_X_L_A_0x28 = 0x28, //R
LSM303_OUT_X_H_A_0x29 = 0x29, //R
LSM303_OUT_Y_L_A_0x2A = 0x2A, //R
LSM303_OUT_Y_H_A_0x2B = 0x2B, //R
LSM303_OUT_Z_L_A_0x2C = 0x2C, //R
LSM303_OUT_Z_H_A_0x2D = 0x2D, //R
LSM303_INT1_CFG_A_0x30 = 0x30, //RW
LSM303_INT1_SOURCE_A_0x31 = 0x31, //R
LSM303_INT1_THS_A_0x32 = 0x32, //RW
LSM303_INT1_DURATION_A_0x33 = 0x33, //RW
LSM303_INT2_CFG_A_0x34 = 0x34, //RW
LSM303_INT2_SOURCE_A_0x35 = 0x35, //R
LSM303_INT2_THS_A_0x36 = 0x36, //RW
LSM303_INT2_DURATION_A_0x37 = 0x37, //RW
}LSM303DLH_REG_TYPE;
//磁场信息结构体
typedef struct
{
s16 x_m, y_m, z_m; //原始数据
float x_gs, y_gs, z_gs; //转化为Gs单位
}M_Data;
u8 LSM303DLH_Init(void); //LSM303DLH初始化
u8 LSM303DLH_ReadMagnetic(M_Data *p_lsm303d); //LSM303DLH 读取磁场强度值
#endif