HMC5883L–STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

HMC5883L–STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L本文使用了 STM32CUBE KEIL5 进行对 HMC5883L 磁力计的数据读取发送测试 使用 hal 库进行编写 同时使用了串口重定向进行发送 过程简单 效果明显 hmc5883l

大家好,欢迎来到IT知识分享网。

一、基础知识

1、HMC5883L磁力计的基础知识

磁力计是用来测量磁场强弱(也就是磁感应强度)的,磁感应强度是一个矢量,我们本篇使用的HMC5883L可以用来测量三个轴向的磁感应强度。

磁感应强度的标准单位是特斯拉(Tesla),也有用高斯(Gauss)来表示的,换算关系是1Tesla=10000Gauss。

当垂直于磁场方向长度为1m的导体,通过1A电流时,所受磁场的作用力的大小为1N,则该磁场的磁感应强度为1T。

磁力计可以用来检测地球磁场方向,也就是作为指南针使用,在航模或者四轴飞行器中,可以用来修正偏航角。

2、HMC5883L的寄存器对应表

后续代码的编写就是写入读取寄存器来进行编写

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L该图为寄存器对应图(引用于@向全栈冲锋)

3、硬件连接方面

硬件方面,磁力计模块上只连VCC、GND、SCL、SDA四根线,SCL连接到stm32的PB6,SDA连接到stm32的PB7,由于该模块的电路板上已经设计了上拉电阻,所以I2C接口的两根线不用再外接上拉了。

以下是电路连接图:

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

二、软件编写方面

1、STM32CUBEMX配置

1.0、软件版本

STM32CUBEMX 版本:V6.2.0

HAL库 版本:STM32Cube FW_F4 V1.28.0

1.1、新建工程

选择相应的芯片型号(本文使用的是STM32F407VET6)

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

1.2、初始化配置

1.2.1、配置RCC
HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L1.2.2、配置debug
HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L1.2.3、配置时钟频率

        频率设置为168MhzHMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

1.3、外设配置

1.3.1、I2C参数配置

STM32F407 的标准I2C接口最大支持100K工作频率,本文选择最大工作频100k,以配置I2C的参数。HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

GPIO接口配置

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L1.3.2、串口配置

选择USART1进行串口的发送,在后续实验中用来发送实验数据,后续将进行串口重定向

RX:PA10

TX:PA9

波特率:

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

1.4、生产代码

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

2、KEIL5代码编写

2.1、I2C初始化

生产的代码已经自动配置了I2C

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

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

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L2.3.4、引用头文件

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

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L串口重定向完成

即可使用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函数即可

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L

进行编译后,开启串口,即可看到现象

HMC5883L--STM32+CUBEMX(HAL库)基于硬件I2C使用HMC5883L串口正常发送,实验成功

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

(0)
上一篇 2025-11-14 08:45
下一篇 2025-11-14 09:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信