大家好,欢迎来到IT知识分享网。
一、基础知识
1、HMC5883L磁力计的基础知识
磁力计是用来测量磁场强弱(也就是磁感应强度)的,磁感应强度是一个矢量,我们本篇使用的HMC5883L可以用来测量三个轴向的磁感应强度。
磁感应强度的标准单位是特斯拉(Tesla),也有用高斯(Gauss)来表示的,换算关系是1Tesla=10000Gauss。
当垂直于磁场方向长度为1m的导体,通过1A电流时,所受磁场的作用力的大小为1N,则该磁场的磁感应强度为1T。
磁力计可以用来检测地球磁场方向,也就是作为指南针使用,在航模或者四轴飞行器中,可以用来修正偏航角。
2、HMC5883L的寄存器对应表
后续代码的编写就是写入读取寄存器来进行编写

3、硬件连接方面
硬件方面,磁力计模块上只连VCC、GND、SCL、SDA四根线,SCL连接到stm32的PB6,SDA连接到stm32的PB7,由于该模块的电路板上已经设计了上拉电阻,所以I2C接口的两根线不用再外接上拉了。
以下是电路连接图:
二、软件编写方面
1、STM32CUBEMX配置
1.0、软件版本
STM32CUBEMX 版本:V6.2.0
HAL库 版本:STM32Cube FW_F4 V1.28.0
1.1、新建工程
选择相应的芯片型号(本文使用的是STM32F407VET6)
1.2、初始化配置
1.2.1、配置RCC
1.2.2、配置debug
1.2.3、配置时钟频率
频率设置为168Mhz
1.3、外设配置
1.3.1、I2C参数配置
STM32F407 的标准I2C接口最大支持100K工作频率,本文选择最大工作频100k,以配置I2C的参数。
GPIO接口配置
1.3.2、串口配置
选择USART1进行串口的发送,在后续实验中用来发送实验数据,后续将进行串口重定向
RX:PA10
TX:PA9
波特率:
1.4、生产代码
2、KEIL5代码编写
2.1、I2C初始化
生产的代码已经自动配置了I2C
2.2、HMC5883L代码编写
2.2.1、创建hmc5883l.c,编写如下代码
/* USER CODE BEGIN Header */ / * File Name : hmc5883l.c * Description : I2C drive based on STM32F4 * STM32 HAL library ver: STM32Cube_FW_F4_V1.27.1 * * @attention * * Copyright (c) 2024~2029 mingfei.tang * All rights reserved. * * */ /* USER CODE END Header */ #include "hmc5883l.h" HMC5883L_T g_tMag; static uint8_t hmc5883L_WeReg( uint16_t regAdd, uint8_t *pData, uint16_t Size ) { HAL_StatusTypeDef status; status = HAL_I2C_Mem_Write( &hi2c2, HMC5883L_SLAVE_ADDRESS, regAdd, I2C_MEMADD_SIZE_8BIT, pData, Size, 1000); if( status == HAL_OK) return HMC5883L_OK; else return HMC5883L_ERROR; } static uint8_t hmc5883L_RdReg( uint16_t regAdd, uint8_t *pData, uint16_t Size ) { HAL_StatusTypeDef status; status = HAL_I2C_Mem_Read( &hi2c2, HMC5883L_SLAVE_ADDRESS, regAdd, I2C_MEMADD_SIZE_8BIT, pData, Size, 1000); if( status == HAL_OK) return HMC5883L_OK; else return HMC5883L_ERROR; } void hmc5883L_WriteByte(uint8_t _ucRegAddr, uint8_t _ucRegData) { hmc5883L_WeReg( _ucRegAddr, &_ucRegData, 1); } uint8_t hmc5883L_ReadByte(uint8_t _ucRegAddr) { uint8_t _ucRegData; hmc5883L_RdReg( _ucRegAddr, &_ucRegData, 1); return _ucRegData; } void hmc5883l_Init(void) { /* 设置Mode寄存器 */ #if 1 hmc5883L_WriteByte(0x00, 0x70); hmc5883L_WriteByte(0x01, 0x20); hmc5883L_WriteByte(0x02, 0x00); #else /* 自校准模式 */ hmc5883L_WriteByte(0x00, 0x70 + 2); hmc5883L_WriteByte(0x01, 0x20); hmc5883L_WriteByte(0x02, 0x00); #endif g_tMag.CfgRegA = hmc5883L_ReadByte(0); g_tMag.CfgRegB = hmc5883L_ReadByte(1); g_tMag.ModeReg = hmc5883L_ReadByte(2); g_tMag.IDReg[0] = hmc5883L_ReadByte(10); g_tMag.IDReg[1] = hmc5883L_ReadByte(11); g_tMag.IDReg[2] = hmc5883L_ReadByte(12); g_tMag.IDReg[3] = 0; /* 设置最小最大值初值 */ g_tMag.X_Min = 4096; g_tMag.X_Max = -4096; g_tMag.Y_Min = 4096; g_tMag.Y_Max = -4096; g_tMag.Z_Min = 4096; g_tMag.Z_Max = -4096; } void hmc5883l_ReadData(void) { uint8_t ucReadBuf[7]; hmc5883L_RdReg( DATA_OUT_X, ucReadBuf, 7); /* 将读出的数据保存到全局结构体变量 */ g_tMag.X = (int16_t)((ucReadBuf[0] << 8) + ucReadBuf[1]); g_tMag.Z = (int16_t)((ucReadBuf[2] << 8) + ucReadBuf[3]); g_tMag.Y = (int16_t)((ucReadBuf[4] << 8) + ucReadBuf[5]); g_tMag.Status = ucReadBuf[6]; /* 统计最大值和最小值 */ if ((g_tMag.X > - 2048) && (g_tMag.X < 2048)) { if (g_tMag.X > g_tMag.X_Max) { g_tMag.X_Max = g_tMag.X; } if (g_tMag.X < g_tMag.X_Min) { g_tMag.X_Min = g_tMag.X; } } if ((g_tMag.Y > - 2048) && (g_tMag.Y < 2048)) { if (g_tMag.Y > g_tMag.Y_Max) { g_tMag.Y_Max = g_tMag.Y; } if (g_tMag.Y < g_tMag.Y_Min) { g_tMag.Y_Min = g_tMag.Y; } } if ((g_tMag.Z > - 2048) && (g_tMag.Z < 2048)) { if (g_tMag.Z > g_tMag.Z_Max) { g_tMag.Z_Max = g_tMag.Z; } if (g_tMag.Z < g_tMag.Z_Min) { g_tMag.Z_Min = g_tMag.Z; } } } void hmc5883l_test( void ) { hmc5883l_Init(); while(1) { hmc5883l_ReadData(); printf("X=%5d(%5d,%5d),Y=%6d(%5d,%5d),Z=%6d(%5d,%5d)\r", g_tMag.X, g_tMag.X_Min, g_tMag.X_Max, g_tMag.Y, g_tMag.Y_Min, g_tMag.Y_Max, g_tMag.Z, g_tMag.Z_Min, g_tMag.Z_Max); HAL_Delay(100); } } /* End of this file */
2.2.2、创建hmc5883l.h,编写如下代码
/* USER CODE BEGIN Header */ / * File Name : hmc5883l.h * Description : I2C drive based on STM32F4 * * @attention * * Copyright (c) 2024~2029 mingfei.tang * All rights reserved. * * */ /* USER CODE END Header */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __HMC5883L_H #define __HMC5883L_H #ifdef __cplusplus extern "C" { #endif #include "stdio.h" #include "main.h" #define HMC5883L_OK 1 #define HMC5883L_ERROR 0 #define bsp_DelayMS HAL_Delay #define HMC5883L_SLAVE_ADDRESS 0x3C /* I2C从机地址 */ #define DATA_OUT_X 0x03 typedef struct { int16_t X; int16_t Y; int16_t Z; int16_t X_Min; int16_t Y_Min; int16_t Z_Min; int16_t X_Max; int16_t Y_Max; int16_t Z_Max; uint8_t Status; uint8_t CfgRegA; uint8_t CfgRegB; uint8_t CfgRegC; uint8_t ModeReg; uint8_t IDReg[3+1]; }HMC5883L_T; extern HMC5883L_T g_tMag; void hmc5883l_test( void ); #ifdef __cplusplus } #endif #endif /*__BH1750_H */ __HMC5883L_H
2.2.3、主函数进行hmc5883l.h文件的引用
#include "hmc5883l.h"
hmc5883代码编写完成
2.3、USART1串口 printf()函数重载
2.3.1、编写uart.h
#ifndef _UART_H #define _UART_H #include "main.h" #include "stdio.h" int fputc(int ch, FILE *f) ; #endif
2.3.2、编写uart.c
#include "uart.h" #include "usart.h" extern UART_HandleTypeDef huart1; //???? /* USER CODE BEGIN 1 */ #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ / * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END 1 */
注意此处使用的是USART1,根据实际应用进行修改即可
extern UART_HandleTypeDef huart1;
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
2.3.3、在设置中勾选LIH

#include "hmc5883l.h" #include "stdio.h" #include "uart.h"

即可使用printf()函数进行串口发送
printf("Hellow World");
2.4 测试代码编写在hmc5883l.c中,
void hmc5883l_test( void ) { hmc5883l_Init(); hmc5883l_ReadData(); printf("X1=%5d(%5d,%5d),Y1=%6d(%5d,%5d),Z1=%6d(%5d,%5d)\r", g_tMag.X, g_tMag.X_Min, g_tMag.X_Max, g_tMag.Y, g_tMag.Y_Min, g_tMag.Y_Max, g_tMag.Z, g_tMag.Z_Min, g_tMag.Z_Max); HAL_Delay(100); }
同时在hmc5883l.h中进行声明
void hmc5883l_test( void );
在2.2中已经对测试代码进行了编写,如果是直接复制则无需再次编写
2.5进行测试
主函数中调用hmc5883l_tset函数即可
进行编译后,开启串口,即可看到现象

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/118311.html


1.2.2、配置debug
1.2.3、配置时钟频率

1.3.2、串口配置


