> For the complete documentation index, see [llms.txt](https://libooogo.gitbook.io/esplane/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://libooogo.gitbook.io/esplane/developer-guide/11esp32+-san-zhou-ci-luo-pan-hmc5883l-yi-zhi-yu-tiao-shi.md).

# 09 Magnetic Compass HMC5883l Driver

## 一、开发笔记

1. 常用的地磁传感器主要有FreeScale(飞思卡尔)的MAG 系列和 Honeywell(霍尼韦尔)的HMC 系列.
2. HMC5883 的工作电压在2.16V\~3.6V 之间,典型为3.3V.可通过VDDIO 口来指定IO的工作电压(1.71v-VDD).
3. 设备默认地址0x3C for write operations, or 0x3D for read operations.
4. 磁场范围广(+/-8Oe),测量误差1-2度,最大输出频率可达160Hz ,默认15hz
5. HMC5883L仅有13个寄存器,其中03-08为数据输出寄存器(只读),09为状态寄存器(只读),标示是否有新数据等.00-02为配置和模式选择寄存器(读写).10-12为识别寄存器,对应的ASCII字符分别是‘H’,‘4’,‘3’(见下表寄存器列表)
6. 支持自动地址指针:例如访问过最后一个数据输出寄存器08后,地址指针自动指向03,不必再写入03地址,可以再次进行数据读取.

```
If (address pointer = 08) then address pointer = 03
Else if (address pointer >= 12) then address pointer = 0
Else (address pointer) = (address pointer) + 1
```

## 二、初始化与工作流程

### 1. 设置测量模式

默认为单次测量模式,可以通过更改02模式选择寄存器切换成连续测量模式

```
通电时间后传送三个字节:0x3C 0x02 0x00
```

### 2. 设置采样率(默认15Hz)

修改00-配置寄存器,配置数据输出寄存器的写入频率,和每次写入的采样次数.以下展示一种防止出错的写法:

```
#define HMC5883L_RA_CONFIG_A        0x00    //配置寄存器A 地址00


#define HMC5883L_AVERAGING_1        0x00   //4种采样次数宏定义,CRA6-CRA5
#define HMC5883L_AVERAGING_2        0x01
#define HMC5883L_AVERAGING_4        0x02
#define HMC5883L_AVERAGING_8        0x03

#define HMC5883L_RATE_0P75          0x00  //7种采样频率的宏定义 CRA4-CRA2
#define HMC5883L_RATE_1P5           0x01
#define HMC5883L_RATE_3             0x02
#define HMC5883L_RATE_7P5           0x03
#define HMC5883L_RATE_15            0x04
#define HMC5883L_RATE_30            0x05
#define HMC5883L_RATE_75            0x06

#define HMC5883L_BIAS_NORMAL        0x00  //校准选项  CRA1-CRA0
#define HMC5883L_BIAS_POSITIVE      0x01
#define HMC5883L_BIAS_NEGATIVE      0x02
```

寄存器拼接:将以上宏定义设置的位,移动到对应的位置

```
#define HMC5883L_CRA_AVERAGE_BIT    6
#define HMC5883L_CRA_AVERAGE_LENGTH 2
#define HMC5883L_CRA_RATE_BIT       4
#define HMC5883L_CRA_RATE_LENGTH    3
#define HMC5883L_CRA_BIAS_BIT       1
#define HMC5883L_CRA_BIAS_LENGTH    2

      (HMC5883L_AVERAGING_8 << (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
      (HMC5883L_RATE_15 << (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
      (HMC5883L_BIAS_NORMAL << (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1))
      //配置信息:采样率15hz,每次结果来自8次采样,不进行校准
```

解读:采样次数选择为HMC5883L\_AVERAGING\_8,需要尾部对齐到 CRA5,已知头部的位置为CRA6(HMC5883L\_CRA\_AVERAGE\_BIT),该选项暂居2bit(HMC5883L\_CRA\_AVERAGE\_LENGTH)空间,可以推导出需要尾部移动6+1-2位 (HMC5883L\_CRA\_AVERAGE\_BIT - HMC5883L\_CRA\_AVERAGE\_LENGTH + 1)

### 3. 设置测量范围

默认增益1090,范围+-1.3Ga.无人机项目选择增益为660,测量范围为+-2.5Ga

### 4. 校准

应用层校准,保存初始值.

### 5. 开始测量

如果是连续测量模式,直接读取寄存器03-08值即可,需要进行拼接操作.如果选择单次模式,读取之后,需要将模式寄存器再次置位.

```
  i2cdevReadReg8(I2Cx, devAddr, HMC5883L_RA_DATAX_H, 6, buffer);
  if (mode == HMC5883L_MODE_SINGLE) i2cdevWriteByte(I2Cx, devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
  *x = (((int16_t)buffer[0]) << 8) | buffer[1];
  *y = (((int16_t)buffer[4]) << 8) | buffer[5];
  *z = (((int16_t)buffer[2]) << 8) | buffer[3];
```

### 6. 自测试操作(可选)

1. 保存配置寄存器参数
2. 设置增益为440 (HMC5883L\_GAIN\_440  // Gain value during self-test)
3. 设置寄存器A,进行正向测试 HMC5883L\_BIAS\_POSITIVE
4. 设置单次模式,读取正向测量值
5. 设置寄存器B,进行负向测试 HMC5883L\_BIAS\_NEGATIVE
6. 设置单次模式,读取反向测量值
7. 依次比较正向和负方向测量值是否在正常范围内

```
#define HMC5883L_ST_GAIN            HMC5883L_GAIN_440  // Gain value during self-test
#define HMC5883L_ST_GAIN_NBR        440
#define HMC5883L_ST_ERROR           0.2                // Max error
#define HMC5883L_ST_DELAY_MS        250                // delay in millisec during self test */
#define HMC5883L_ST_X_NORM          (int32_t)(1.16 * HMC5883L_ST_GAIN_NBR)
#define HMC5883L_ST_X_MIN           (int32_t)(HMC5883L_ST_X_NORM - (HMC5883L_ST_X_NORM * HMC5883L_ST_ERROR))
#define HMC5883L_ST_X_MAX           (int32_t)(HMC5883L_ST_X_NORM + (HMC5883L_ST_X_NORM * HMC5883L_ST_ERROR))
#define HMC5883L_ST_Y_NORM          (int32_t)(1.16 * HMC5883L_ST_GAIN_NBR)
#define HMC5883L_ST_Y_MIN           (int32_t)(HMC5883L_ST_Y_NORM - (HMC5883L_ST_Y_NORM * HMC5883L_ST_ERROR))
#define HMC5883L_ST_Y_MAX           (int32_t)(HMC5883L_ST_Y_NORM + (HMC5883L_ST_Y_NORM * HMC5883L_ST_ERROR))
#define HMC5883L_ST_Z_NORM          (int32_t)(1.08 * HMC5883L_ST_GAIN_NBR)
#define HMC5883L_ST_Z_MIN           (int32_t)(HMC5883L_ST_Z_NORM - (HMC5883L_ST_Z_NORM * HMC5883L_ST_ERROR))
#define HMC5883L_ST_Z_MAX           (int32_t)(HMC5883L_ST_Z_NORM + (HMC5883L_ST_Z_NORM * HMC5883L_ST_ERROR))
```

## 三、寄存器表

|  地址 |  HMC5883L寄存器名称 | 访问权限 |
| :-: | :------------: | :--: |
|  00 |     配置寄存器 A    |  读/写 |
|  01 |     配置寄存器 B    |  读/写 |
|  02 |      模式寄存器     |  读/写 |
|  03 | 数据输出 X MSB 寄存器 |   读  |
|  04 | 数据输出 X LSB 寄存器 |   读  |
|  05 |  数据输出 Z MSB寄存器 |   读  |
|  06 | 数据输出 Z LSB 寄存器 |   读  |
|  07 | 数据输出 Y MSB 寄存器 |   读  |
|  08 | 数据输出 Y LSB 寄存器 |   读  |
|  09 |      状态寄存器     |   读  |
|  10 |     识别寄存器A     |   读  |
|  11 |     识别寄存器B     |   读  |
|  12 |     识别寄存器C     |   读  |

### 1. 00-配置寄存器A

主要用于配置数据输出速率,每次输出结果的采样数.

![配置寄存器A](https://img-blog.csdnimg.cn/2019082912190137.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

![数据输出速率](https://img-blog.csdnimg.cn/20190829122013475.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

### 2. 01-配置寄存器B

用于配置传感器增益(灵敏度和测量范围) ![配置寄存器B](https://img-blog.csdnimg.cn/20190829122546694.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

![增益设置](https://img-blog.csdnimg.cn/20190829122606999.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

### 3. 02-模式寄存器

配置不同的工作模式:连续测量模式、单一测量模式、闲置模式.

![模式寄存器](https://img-blog.csdnimg.cn/20190829132156895.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

![操作模式](https://img-blog.csdnimg.cn/20190829132220762.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

### 4. 09-状态寄存器

LOCK:放置输出寄存器读取期间写入数据,在数据读取期间置位,数据不会在更新,读取完成后自动解锁. RDY:Ready Bit,与DRDY引脚电平绑定,当数据写入数据寄存器完成,该位置位.开始写入时状态清零并保持250us.

![状态寄存器](https://img-blog.csdnimg.cn/20190829132409951.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIwNTE1NDYx,size_16,color_FFFFFF,t_70)

### 5. 10-12 Identification Register A/B/C

1. 三个寄存器为只读寄存器
2. 三个寄存器的数值,对应成ASCII码分别是‘H’ ‘4’ ‘3’

### 6. 03-08 Data Output Register

1. 每个通道的输出对应两个8位寄存器A和B,大数端存放.
2. 寄存器A存储MSB(高位数据),寄存器B存储LSB(低位数据).
3. 两个寄存器保存数据为补码形式,范围0xF800–0x07FF(-2048–2047 )&#x20;
