HMC5983地磁传感器驱动程序

传感器特性

HMC5983是Honeywell公司生产的三轴数字磁力计,相比HMC5883L性能更优:

  • 最高输出频率:220Hz(HMC5883L为75Hz)
  • 温度补偿:内置温度传感器,可自动补偿温漂
  • 分辨率:最高13位(0.73mG/LSB)
  • 测量范围:±8 Gauss(可配置)
  • 接口:I2C(默认地址0x1E)和SPI
  • 工作电压:2.16V-3.6V

硬件连接

I2C接口连接(推荐)

HMC5983 ──── 微控制器
  VCC ────── 3.3V
  GND ────── GND
  SCL ────── I2C时钟线
  SDA ────── I2C数据线
  DRDY ───── 数据就绪中断(可选)

引脚定义

HMC5983引脚 功能 说明
VCC 电源 2.16-3.6V
GND
SCL I2C时钟
SDA I2C数据
DRDY 数据就绪 低电平有效,数据可用时拉低
SDO/SA0 I2C地址选择 接地:0x1E,接VCC:0x1F

寄存器定义

/************************************************************
 * HMC5983寄存器地址定义
 ************************************************************/
#define HMC5983_I2C_ADDR         0x1E    // 7位I2C地址

// 配置寄存器
#define HMC5983_REG_CONFIG_A     0x00    // 配置寄存器A
#define HMC5983_REG_CONFIG_B     0x01    // 配置寄存器B
#define HMC5983_REG_MODE         0x02    // 模式寄存器

// 数据寄存器
#define HMC5983_REG_DATA_X_MSB   0x03    // X轴数据高字节
#define HMC5983_REG_DATA_X_LSB   0x04    // X轴数据低字节
#define HMC5983_REG_DATA_Z_MSB   0x05    // Z轴数据高字节
#define HMC5983_REG_DATA_Z_LSB   0x06    // Z轴数据低字节
#define HMC5983_REG_DATA_Y_MSB   0x07    // Y轴数据高字节
#define HMC5983_REG_DATA_Y_LSB   0x08    // Y轴数据低字节

// 状态寄存器
#define HMC5983_REG_STATUS       0x09    // 状态寄存器
#define HMC5983_REG_ID_A         0x0A    // 识别寄存器A
#define HMC5983_REG_ID_B         0x0B    // 识别寄存器B
#define HMC5983_REG_ID_C         0x0C    // 识别寄存器C

/************************************************************
 * 配置寄存器A(0x00)位定义
 ************************************************************/
// 温度补偿使能
#define HMC5983_TEMP_ENABLE      0x80    // 温度补偿使能
#define HMC5983_TEMP_DISABLE     0x00    // 温度补偿禁用

// 采样平均次数
#define HMC5983_AVERAGE_1        0x00    // 1次采样
#define HMC5983_AVERAGE_2        0x20    // 2次采样平均
#define HMC5983_AVERAGE_4        0x40    // 4次采样平均
#define HMC5983_AVERAGE_8        0x60    // 8次采样平均

// 数据输出速率
#define HMC5983_RATE_0_75HZ      0x00    // 0.75Hz
#define HMC5983_RATE_1_5HZ       0x04    // 1.5Hz
#define HMC5983_RATE_3HZ         0x08    // 3Hz
#define HMC5983_RATE_7_5HZ       0x0C    // 7.5Hz
#define HMC5983_RATE_15HZ        0x10    // 15Hz(默认)
#define HMC5983_RATE_30HZ        0x14    // 30Hz
#define HMC5983_RATE_75HZ        0x18    // 75Hz
#define HMC5983_RATE_220HZ       0x1C    // 220Hz

// 测量模式
#define HMC5983_MEAS_NORMAL      0x00    // 正常测量模式
#define HMC5983_MEAS_POSITIVE    0x01    // 正偏置自测试
#define HMC5983_MEAS_NEGATIVE    0x02    // 负偏置自测试
#define HMC5983_MEAS_TEMP_ONLY   0x03    // 仅温度测量

/************************************************************
 * 配置寄存器B(0x01)位定义 - 增益设置
 ************************************************************/
#define HMC5983_GAIN_0_88GA      0x00    // ±0.88Ga,增益=1370,分辨率=0.73mG/LSB
#define HMC5983_GAIN_1_3GA       0x20    // ±1.3Ga,增益=1090,分辨率=0.92mG/LSB
#define HMC5983_GAIN_1_9GA       0x40    // ±1.9Ga,增益=820,分辨率=1.22mG/LSB
#define HMC5983_GAIN_2_5GA       0x60    // ±2.5Ga,增益=660,分辨率=1.52mG/LSB
#define HMC5983_GAIN_4_0GA       0x80    // ±4.0Ga,增益=440,分辨率=2.27mG/LSB
#define HMC5983_GAIN_4_7GA       0xA0    // ±4.7Ga,增益=390,分辨率=2.56mG/LSB(默认)
#define HMC5983_GAIN_5_6GA       0xC0    // ±5.6Ga,增益=330,分辨率=3.03mG/LSB
#define HMC5983_GAIN_8_1GA       0xE0    // ±8.1Ga,增益=230,分辨率=4.35mG/LSB

/************************************************************
 * 模式寄存器(0x02)位定义
 ************************************************************/
// 测量模式
#define HMC5983_MODE_CONTINUOUS  0x00    // 连续测量模式
#define HMC5983_MODE_SINGLE      0x01    // 单次测量模式
#define HMC5983_MODE_IDLE        0x02    // 空闲模式
#define HMC5983_MODE_SLEEP       0x03    // 睡眠模式

// I2C模式
#define HMC5983_I2C_NORMAL       0x00    // 正常I2C模式
#define HMC5983_I2C_FAST         0x80    // 快速I2C模式(3400kHz)

/************************************************************
 * 状态寄存器(0x09)位定义
 ************************************************************/
#define HMC5983_STATUS_RDY       0x01    // 数据就绪
#define HMC5983_STATUS_LOCK      0x02    // 数据锁定(读取期间新数据到达)

C语言驱动程序

/************************************************************
 * HMC5983地磁传感器驱动程序
 * 文件:hmc5983.c / hmc5983.h
 * 作者:AI助手
 * 功能:完整的HMC5983驱动,支持I2C接口
 * 编译:适用于STM32、ESP32、Arduino等平台
 ************************************************************/

#ifndef __HMC5983_H__
#define __HMC5983_H__

#include <stdint.h>
#include <stdbool.h>

// 磁力计数据结构
typedef struct {
    int16_t x;      // X轴磁场强度
    int16_t y;      // Y轴磁场强度  
    int16_t z;      // Z轴磁场强度
    float heading;  // 航向角(度)
} HMC5983_Data_t;

// 传感器配置结构
typedef struct {
    uint8_t i2c_addr;       // I2C地址
    uint8_t config_a;       // 配置寄存器A值
    uint8_t config_b;       // 配置寄存器B值(增益)
    uint8_t mode;           // 工作模式
    float declination_angle; // 磁偏角(度)
} HMC5983_Config_t;

// 默认配置
#define HMC5983_DEFAULT_CONFIG { \
    .i2c_addr = HMC5983_I2C_ADDR, \
    .config_a = HMC5983_TEMP_ENABLE | HMC5983_AVERAGE_8 | HMC5983_RATE_15HZ | HMC5983_MEAS_NORMAL, \
    .config_b = HMC5983_GAIN_4_7GA, \
    .mode = HMC5983_MODE_CONTINUOUS, \
    .declination_angle = 0.0f \
}

// 函数声明
bool HMC5983_Init(HMC5983_Config_t *config);
bool HMC5983_ReadRaw(HMC5983_Data_t *data);
bool HMC5983_ReadCalibrated(HMC5983_Data_t *data);
float HMC5983_CalculateHeading(HMC5983_Data_t *data);
bool HMC5983_SelfTest(void);
bool HMC5983_SetMode(uint8_t mode);
bool HMC5983_SetGain(uint8_t gain);
bool HMC5983_SetRate(uint8_t rate);
uint8_t HMC5983_ReadStatus(void);
bool HMC5983_IsDataReady(void);

// 用户需要实现的底层I2C函数
bool I2C_WriteByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data);
bool I2C_ReadBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t *buffer, uint8_t len);
void Delay_ms(uint32_t ms);

#endif /* __HMC5983_H__ */
/************************************************************
 * HMC5983驱动程序实现
 ************************************************************/
#include "hmc5983.h"

// 全局配置
static HMC5983_Config_t g_config;

// 增益对应的灵敏度(mG/LSB)
static const float gain_sensitivity[] = {
    0.73f,   // GAIN_0_88GA
    0.92f,   // GAIN_1_3GA
    1.22f,   // GAIN_1_9GA
    1.52f,   // GAIN_2_5GA
    2.27f,   // GAIN_4_0GA
    2.56f,   // GAIN_4_7GA(默认)
    3.03f,   // GAIN_5_6GA
    4.35f    // GAIN_8_1GA
};

// 校准参数(需要用户校准后设置)
static float cal_offset_x = 0.0f;
static float cal_offset_y = 0.0f;
static float cal_offset_z = 0.0f;
static float cal_scale_x = 1.0f;
static float cal_scale_y = 1.0f;
static float cal_scale_z = 1.0f;

/************************************************************
 * 函数:HMC5983_Init
 * 功能:初始化HMC5983传感器
 * 参数:config - 配置参数,NULL使用默认配置
 * 返回:true-成功,false-失败
 ************************************************************/
bool HMC5983_Init(HMC5983_Config_t *config) {
    uint8_t id[3] = {0};
    
    // 使用默认配置或用户配置
    if (config == NULL) {
        g_config = (HMC5983_Config_t)HMC5983_DEFAULT_CONFIG;
    } else {
        g_config = *config;
    }
    
    // 读取设备ID验证连接
    if (!I2C_ReadBytes(g_config.i2c_addr, HMC5983_REG_ID_A, id, 3)) {
        return false;
    }
    
    // 检查设备ID:HMC5983的ID应为'H'、'4'、'3'
    if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
        return false;
    }
    
    // 配置寄存器A
    if (!I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, g_config.config_a)) {
        return false;
    }
    
    // 配置寄存器B(增益)
    if (!I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_B, g_config.config_b)) {
        return false;
    }
    
    // 设置工作模式
    if (!HMC5983_SetMode(g_config.mode)) {
        return false;
    }
    
    // 等待传感器稳定
    Delay_ms(10);
    
    return true;
}

/************************************************************
 * 函数:HMC5983_ReadRaw
 * 功能:读取原始磁场数据(未经校准)
 * 参数:data - 存储读取的数据
 * 返回:true-成功,false-失败
 * 注意:数据顺序为X、Z、Y,不是X、Y、Z
 ************************************************************/
bool HMC5983_ReadRaw(HMC5983_Data_t *data) {
    uint8_t buffer[6] = {0};
    
    // 检查数据是否就绪(可选)
    // if (!HMC5983_IsDataReady()) {
    //     return false;
    // }
    
    // 读取6个数据寄存器(X、Z、Y各2字节)
    if (!I2C_ReadBytes(g_config.i2c_addr, HMC5983_REG_DATA_X_MSB, buffer, 6)) {
        return false;
    }
    
    // 组合数据(注意:X、Z、Y顺序)
    data->x = (int16_t)((buffer[0] << 8) | buffer[1]);
    data->z = (int16_t)((buffer[2] << 8) | buffer[3]);
    data->y = (int16_t)((buffer[4] << 8) | buffer[5]);
    
    // 计算航向角
    data->heading = HMC5983_CalculateHeading(data);
    
    return true;
}

/************************************************************
 * 函数:HMC5983_ReadCalibrated
 * 功能:读取校准后的磁场数据
 * 参数:data - 存储读取的数据
 * 返回:true-成功,false-失败
 ************************************************************/
bool HMC5983_ReadCalibrated(HMC5983_Data_t *data) {
    if (!HMC5983_ReadRaw(data)) {
        return false;
    }
    
    // 应用校准参数
    float x_cal = ((float)data->x - cal_offset_x) * cal_scale_x;
    float y_cal = ((float)data->y - cal_offset_y) * cal_scale_y;
    float z_cal = ((float)data->z - cal_offset_z) * cal_scale_z;
    
    data->x = (int16_t)x_cal;
    data->y = (int16_t)y_cal;
    data->z = (int16_t)z_cal;
    
    // 重新计算航向角
    data->heading = HMC5983_CalculateHeading(data);
    
    return true;
}

/************************************************************
 * 函数:HMC5983_CalculateHeading
 * 功能:计算航向角(相对于磁北)
 * 参数:data - 磁场数据
 * 返回:航向角(0-359.9度)
 * 公式:heading = atan2(Y, X) * 180/π
 ************************************************************/
float HMC5983_CalculateHeading(HMC5983_Data_t *data) {
    float heading_rad, heading_deg;
    
    // 避免除零错误
    if (data->x == 0) {
        if (data->y > 0) {
            heading_rad = M_PI_2;      // 90度
        } else if (data->y < 0) {
            heading_rad = -M_PI_2;     // -90度
        } else {
            return 0.0f;               // 无有效数据
        }
    } else {
        // 计算反正切
        heading_rad = atan2((float)data->y, (float)data->x);
    }
    
    // 转换为角度
    heading_deg = heading_rad * 180.0f / M_PI;
    
    // 调整到0-360度范围
    if (heading_deg < 0) {
        heading_deg += 360.0f;
    }
    
    // 应用磁偏角校正(转换为真北)
    heading_deg += g_config.declination_angle;
    
    // 保持0-360度范围
    if (heading_deg >= 360.0f) {
        heading_deg -= 360.0f;
    } else if (heading_deg < 0) {
        heading_deg += 360.0f;
    }
    
    return heading_deg;
}

/************************************************************
 * 函数:HMC5983_SetMode
 * 功能:设置工作模式
 * 参数:mode - 工作模式
 * 返回:true-成功,false-失败
 ************************************************************/
bool HMC5983_SetMode(uint8_t mode) {
    uint8_t mode_reg = 0;
    
    // 设置I2C模式(保持原有设置)
    mode_reg = HMC5983_I2C_NORMAL;
    
    // 设置测量模式
    if (mode == HMC5983_MODE_CONTINUOUS) {
        mode_reg |= HMC5983_MODE_CONTINUOUS;
    } else if (mode == HMC5983_MODE_SINGLE) {
        mode_reg |= HMC5983_MODE_SINGLE;
    } else if (mode == HMC5983_MODE_IDLE) {
        mode_reg |= HMC5983_MODE_IDLE;
    } else {
        mode_reg |= HMC5983_MODE_SLEEP;
    }
    
    g_config.mode = mode;
    
    return I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_MODE, mode_reg);
}

/************************************************************
 * 函数:HMC5983_SetGain
 * 功能:设置传感器增益
 * 参数:gain - 增益值
 * 返回:true-成功,false-失败
 ************************************************************/
bool HMC5983_SetGain(uint8_t gain) {
    g_config.config_b = gain;
    return I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_B, gain);
}

/************************************************************
 * 函数:HMC5983_SetRate
 * 功能:设置数据输出速率
 * 参数:rate - 输出速率
 * 返回:true-成功,false-失败
 ************************************************************/
bool HMC5983_SetRate(uint8_t rate) {
    // 保持其他位不变,只修改速率位
    uint8_t config_a = g_config.config_a & 0xE3;  // 清空速率位
    config_a |= rate;
    
    g_config.config_a = config_a;
    
    return I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, config_a);
}

/************************************************************
 * 函数:HMC5983_SelfTest
 * 功能:执行自测试
 * 返回:true-测试通过,false-测试失败
 ************************************************************/
bool HMC5983_SelfTest(void) {
    HMC5983_Data_t data_normal, data_positive, data_negative;
    
    // 保存当前配置
    uint8_t original_config_a = g_config.config_a;
    
    // 1. 正常模式测量
    g_config.config_a = (g_config.config_a & 0xFC) | HMC5983_MEAS_NORMAL;
    I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, g_config.config_a);
    Delay_ms(100);
    HMC5983_ReadRaw(&data_normal);
    
    // 2. 正偏置自测试
    g_config.config_a = (g_config.config_a & 0xFC) | HMC5983_MEAS_POSITIVE;
    I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, g_config.config_a);
    Delay_ms(100);
    HMC5983_ReadRaw(&data_positive);
    
    // 3. 负偏置自测试
    g_config.config_a = (g_config.config_a & 0xFC) | HMC5983_MEAS_NEGATIVE;
    I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, g_config.config_a);
    Delay_ms(100);
    HMC5983_ReadRaw(&data_negative);
    
    // 恢复原始配置
    g_config.config_a = original_config_a;
    I2C_WriteByte(g_config.i2c_addr, HMC5983_REG_CONFIG_A, original_config_a);
    
    // 计算测试结果
    // 正偏置时读数应增加,负偏置时读数应减少
    float pos_diff_x = fabs(data_positive.x - data_normal.x);
    float neg_diff_x = fabs(data_negative.x - data_normal.x);
    
    // 根据数据手册,自测试模式下读数应有明显变化
    // 典型值:正偏置增加~1.16Ga,负偏置减少~1.16Ga
    float expected_change = 1.16f * 1000.0f / gain_sensitivity[(g_config.config_b >> 5) & 0x07];
    
    if (pos_diff_x > expected_change * 0.5f && neg_diff_x > expected_change * 0.5f) {
        return true;
    }
    
    return false;
}

/************************************************************
 * 函数:HMC5983_ReadStatus
 * 功能:读取状态寄存器
 * 返回:状态寄存器值
 ************************************************************/
uint8_t HMC5983_ReadStatus(void) {
    uint8_t status = 0;
    I2C_ReadBytes(g_config.i2c_addr, HMC5983_REG_STATUS, &status, 1);
    return status;
}

/************************************************************
 * 函数:HMC5983_IsDataReady
 * 功能:检查数据是否就绪
 * 返回:true-数据就绪,false-数据未就绪
 ************************************************************/
bool HMC5983_IsDataReady(void) {
    uint8_t status = HMC5983_ReadStatus();
    return (status & HMC5983_STATUS_RDY) != 0;
}

/************************************************************
 * 函数:HMC5983_Calibrate
 * 功能:校准磁力计(需要用户执行)
 * 说明:用户需要旋转传感器360度,采集各轴最大最小值
 ************************************************************/
void HMC5983_Calibrate(void) {
    HMC5983_Data_t data;
    int16_t x_min = 32767, x_max = -32768;
    int16_t y_min = 32767, y_max = -32768;
    int16_t z_min = 32767, z_max = -32768;
    uint32_t sample_count = 0;
    
    printf("开始校准:请缓慢旋转传感器360度...\n");
    
    // 采集1000个样本
    for (sample_count = 0; sample_count < 1000; sample_count++) {
        if (HMC5983_ReadRaw(&data)) {
            // 更新最小值
            if (data.x < x_min) x_min = data.x;
            if (data.y < y_min) y_min = data.y;
            if (data.z < z_min) z_min = data.z;
            
            // 更新最大值
            if (data.x > x_max) x_max = data.x;
            if (data.y > y_max) y_max = data.y;
            if (data.z > z_max) z_max = data.z;
        }
        
        Delay_ms(10);
    }
    
    // 计算偏移和比例因子
    cal_offset_x = (x_max + x_min) / 2.0f;
    cal_offset_y = (y_max + y_min) / 2.0f;
    cal_offset_z = (z_max + z_min) / 2.0f;
    
    float avg_delta_x = (x_max - x_min) / 2.0f;
    float avg_delta_y = (y_max - y_min) / 2.0f;
    float avg_delta_z = (z_max - z_min) / 2.0f;
    
    float avg_delta = (avg_delta_x + avg_delta_y + avg_delta_z) / 3.0f;
    
    cal_scale_x = avg_delta / avg_delta_x;
    cal_scale_y = avg_delta / avg_delta_y;
    cal_scale_z = avg_delta / avg_delta_z;
    
    printf("校准完成!\n");
    printf("X: min=%d, max=%d, offset=%.2f, scale=%.4f\n", 
           x_min, x_max, cal_offset_x, cal_scale_x);
    printf("Y: min=%d, max=%d, offset=%.2f, scale=%.4f\n", 
           y_min, y_max, cal_offset_y, cal_scale_y);
    printf("Z: min=%d, max=%d, offset=%.2f, scale=%.4f\n", 
           z_min, z_max, cal_offset_z, cal_scale_z);
}

参考代码 地磁传感器HMC5983的驱动程序 www.youwenfan.com/contentcnt/73320.html

使用示例

示例1:基础使用(连续测量模式)

#include "hmc5983.h"
#include <stdio.h>

int main(void) {
    HMC5983_Config_t config = HMC5983_DEFAULT_CONFIG;
    HMC5983_Data_t data;
    
    // 初始化I2C接口(用户实现)
    I2C_Init();
    
    // 初始化HMC5983
    if (!HMC5983_Init(&config)) {
        printf("HMC5983初始化失败!\n");
        return -1;
    }
    
    printf("HMC5983初始化成功!\n");
    
    // 连续读取数据
    while (1) {
        if (HMC5983_ReadCalibrated(&data)) {
            printf("X=%.2f mG, Y=%.2f mG, Z=%.2f mG, Heading=%.1f°\n",
                   data.x * 2.56f,  // 转换为mG(假设增益4.7Ga)
                   data.y * 2.56f,
                   data.z * 2.56f,
                   data.heading);
        }
        
        Delay_ms(100);  // 10Hz采样
    }
    
    return 0;
}

示例2:单次测量模式(低功耗)

// 单次测量模式配置
HMC5983_Config_t config = {
    .i2c_addr = HMC5983_I2C_ADDR,
    .config_a = HMC5983_TEMP_ENABLE | HMC5983_AVERAGE_1 | HMC5983_RATE_0_75HZ,
    .config_b = HMC5983_GAIN_4_7GA,
    .mode = HMC5983_MODE_SINGLE,
    .declination_angle = -2.5f  // 北京地区磁偏角约-2.5°
};

// 单次测量函数
bool ReadSingleMeasurement(HMC5983_Data_t *data) {
    // 设置为单次测量模式
    HMC5983_SetMode(HMC5983_MODE_SINGLE);
    
    // 等待测量完成(约6ms)
    Delay_ms(10);
    
    // 读取数据
    bool success = HMC5983_ReadCalibrated(data);
    
    // 返回空闲模式省电
    HMC5983_SetMode(HMC5983_MODE_IDLE);
    
    return success;
}

示例3:STM32 HAL库I2C实现

// 基于STM32 HAL库的I2C底层函数
bool I2C_WriteByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) {
    uint8_t buffer[2] = {reg_addr, data};
    
    if (HAL_I2C_Master_Transmit(&hi2c1, dev_addr << 1, buffer, 2, 100) != HAL_OK) {
        return false;
    }
    
    return true;
}

bool I2C_ReadBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t *buffer, uint8_t len) {
    // 先发送寄存器地址
    if (HAL_I2C_Master_Transmit(&hi2c1, dev_addr << 1, &reg_addr, 1, 100) != HAL_OK) {
        return false;
    }
    
    // 然后读取数据
    if (HAL_I2C_Master_Receive(&hi2c1, dev_addr << 1, buffer, len, 100) != HAL_OK) {
        return false;
    }
    
    return true;
}

void Delay_ms(uint32_t ms) {
    HAL_Delay(ms);
}

优化建议

1. 中断模式(使用DRDY引脚)

// 配置DRDY引脚中断
void EXTI_IRQHandler(void) {
    if (HMC5983_IsDataReady()) {
        HMC5983_Data_t data;
        HMC5983_ReadCalibrated(&data);
        // 处理数据...
    }
}

2. DMA传输(提高效率)

// 使用DMA读取6个数据寄存器
void HMC5983_ReadDMA(HMC5983_Data_t *data) {
    uint8_t reg_addr = HMC5983_REG_DATA_X_MSB;
    
    // 启动DMA传输
    HAL_I2C_Mem_Read_DMA(&hi2c1, HMC5983_I2C_ADDR << 1, 
                         reg_addr, I2C_MEMADD_SIZE_8BIT,
                         (uint8_t *)data, 6);
}

// DMA完成回调
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
    // 处理完成的数据
}

3. 滤波算法

// 移动平均滤波
#define FILTER_SIZE 10
typedef struct {
    int16_t buffer[FILTER_SIZE];
    uint8_t index;
    int32_t sum;
} Filter_t;

int16_t MovingAverageFilter(Filter_t *filter, int16_t new_value) {
    // 减去最旧的值
    filter->sum -= filter->buffer[filter->index];
    
    // 添加新值
    filter->buffer[filter->index] = new_value;
    filter->sum += new_value;
    
    // 更新索引
    filter->index = (filter->index + 1) % FILTER_SIZE;
    
    return (int16_t)(filter->sum / FILTER_SIZE);
}

注意事项

  1. 安装方向:传感器必须水平安装,X轴指向北方
  2. 干扰源:远离电机、电源线、铁磁材料
  3. 温度补偿:启用温度补偿可提高精度
  4. 数据溢出:增益设置过高可能导致数据溢出(检查状态寄存器)
  5. 校准:首次使用必须进行校准
  6. 磁偏角:根据地理位置设置正确的磁偏角

故障排除

问题 可能原因 解决方案
初始化失败 I2C地址错误 检查SDO引脚电平(0x1E或0x1F)
读数不稳定 电磁干扰 远离干扰源,增加滤波
航向角错误 未校准 执行校准程序
数据溢出 增益过高 降低增益设置
通信超时 I2C总线问题 检查上拉电阻、线长

HMC5983驱动程序提供了从基础到高级的所有功能,可以直接集成到各种嵌入式项目中。

posted @ 2026-04-19 13:11  小前端攻城狮  阅读(8)  评论(0)    收藏  举报