当前位置: 首页 > news >正文

STM32硬件接口I2C应用(基于HMC5883L)

目录

概述

1 STM32Cube控制配置I2C

1.1 I2C参数配置

1.2 使用STM32Cube产生工程

2 HAL库函数介绍

2.1 初始化函数

2.2 写数据函数

 2.3 读数据函数

3 认识HMC5883L

3.1 HMC5883L功能介绍

3.2 HMC5883L的寄存器

4 HMC5883L驱动程序实现

4.1 驱动函数实现

4.2 完整驱动代码

5 测试

6 逻辑分析仪捕捉波形


概述

本文主要介绍STM32F4的内部I2C接口的使用方法,包括使用STM32Cube配置i2c接口函数,还介绍了STM32 HAL库中的接口函数,为了验证接口函数的是否能够正常工作,还使用HMC5883L
作为device,以I2C接口作为通信接口,以实现该芯片数据的读写操作。

1 STM32Cube控制配置I2C

STM32CubeMX 版本: 6.11

HAL库版本: STM32Cube_FW_F4_V1.27.1

1.1 I2C参数配置

STM32F407 的标准I2C接口最大支持100K工作频率,笔者选择最大工作频100k,以配置I2C的参数。

I2C使用的GPIO接口如下:

使用MCU类型和HAL库的版本

1.2 使用STM32Cube产生工程

 在配置完成项目后,点击GENERATE生成项目,打开项目后项目目录如下,和I2C相关的代码如下:

代码第40行:选择I2C2作为硬件接口

代码第41行:I2C通信速率为100K

代码第44行:定义地址位7bit

2 HAL库函数介绍

STM32 HAL库函数数量很多,本文仅介绍笔者使用的一些函数接口。其他函数在使用的时候在具体研究,而不许把每个函数搞清楚才去应用。

2.1 初始化函数

函数原型:

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);

参数介绍

hi2c:  指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

 一个使用案例: 如果已经初始化完成hi2c结构,初始化时,直接调用该结构体即可。

2.2 写数据函数

函数原型:

HAL_StatusTypeDef HAL_I2C_Mem_Write(   I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

参数介绍:

hi2c:  指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

DevAddress: 目标设备地址:设备的7位地址值在调用接口之前,必须将数据表向左移动

MemAddress:内存地址

MemAddSize:内存地址大小

pData:            写数据指针

Size:               写数据大小

Timeout:         写数据超时时间

 2.3 读数据函数

函数原型:

HAL_StatusTypeDef HAL_I2C_Mem_Read( I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

参数介绍:

hi2c:  指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

DevAddress: 目标设备地址:设备的7位地址值在调用接口之前,必须将数据表向左移动

MemAddress:内存地址

MemAddSize:内存地址大小

pData:            读数据指针

Size:               读数据大小

Timeout:         读数据超时时间

3 认识HMC5883L

3.1 HMC5883L功能介绍

霍尼韦尔HMC5883L是一款表面贴装的多芯片模块,专为低场磁传感设计,具有数字接口,适用于低成本罗盘和磁强计等应用。HMC5883L包括我们最先进的高分辨率HMC118X系列磁阻传感器,以及包含放大、自动消磁带驱动器、偏移抵消和12位ADC的ASIC,可实现1°至2°罗盘航向精度。I2C串行总线允许简单的接口。HMC5883L是3.0 × 3.0 × 0.9mm表面贴装16引脚无引线芯片载体(LCC)。

HMC5883L采用霍尼韦尔的各向异性磁阻(AMR)技术,与其他磁传感器技术相比具有优势。这些各向异性定向传感器具有高精度的轴内灵敏度和线性度。这些传感器的固态结构具有非常低的交叉轴灵敏度,旨在测量地球磁场的方向和大小,从毫高斯到8高斯。霍尼韦尔的磁传感器是业内最灵敏、最可靠的低场传感器之一。

3.2 HMC5883L的寄存器

该设备通过许多片上寄存器进行控制和配置,这些寄存器将在本节中描述。在以下描述中,除另有说明外,set表示逻辑1,reset或clear表示逻辑0。

4 HMC5883L驱动程序实现

4.1 驱动函数实现

1)写寄存器函数

代码第25行: 调用HAL_I2C_Mem_Write实现写寄存器功能

2)读寄存器函数

代码第37行: 调用HAL_I2C_Mem_Read实现读寄存器功能

4.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;elsereturn 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;elsereturn 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 1hmc5883L_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);#endifg_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)创建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 __cplusplusextern "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        0x03typedef 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

5 测试

1)编写测试代码

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);}
}

2)编写代码,并下载到板卡中,运行代码

6 逻辑分析仪捕捉波形

 读取数据的波形

相关文章:

  • Matlab使用Simulink仿真实现AM和BPSK信号的解调
  • 玄机——第二章 日志分析-apache日志分析 wp
  • 科研辅助工具
  • C# 下载文件2
  • 【机器学习300问】118、循环神经网络(RNN)的基本结构是怎样的?
  • FastAdmin后台开发框架 lang 任意文件读取漏洞复现
  • 如何衡量llm 数据集的多样性
  • Eigne库安装及使用教程
  • springboot 3.x 之 集成rabbitmq实现动态发送消息给不同的队列
  • 证明 几何分布 的期望和方差
  • 实现锚点链接点击tab跳转到指定位置 并且滚动鼠标顶部锚点的样式也跟随变化
  • 了解 XML HttpRequest 及其在 Web 开发中的应用
  • 什么是模型轻量化?如何自动进行模型轻量化?
  • Linux命令的语法和帮助系统
  • 海豚调度异常处理: 使用 arthas 在内存中删除启动失败的工作流
  • ES6指北【2】—— 箭头函数
  • JavaScript-如何实现克隆(clone)函数
  • Angular 4.x 动态创建组件
  • HTTP中的ETag在移动客户端的应用
  • isset在php5.6-和php7.0+的一些差异
  • java多线程
  • js
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 基于 Babel 的 npm 包最小化设置
  • ------- 计算机网络基础
  • 扑朔迷离的属性和特性【彻底弄清】
  • 巧用 TypeScript (一)
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 【干货分享】dos命令大全
  • (2)(2.10) LTM telemetry
  • (ibm)Java 语言的 XPath API
  • (阿里云万网)-域名注册购买实名流程
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET处理HTTP请求
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET面试题(二)
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • @synthesize和@dynamic分别有什么作用?
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [2016.7.Test1] T1 三进制异或
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [asp.net core]project.json(2)
  • [BZOJ1008][HNOI2008]越狱
  • [C++]类和对象(中)
  • [ccc3.0][数字钥匙] UWB配置和使用(二)
  • [CSS] 点击事件触发的动画
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)