加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入

嵌入式外設-HMC5883L電子指南針(電磁場)驅(qū)動代碼

05/23 16:59
4837
服務支持:
技術交流群

完成交易后在“購買成功”頁面掃碼入群,即可與技術大咖們分享疑惑和經(jīng)驗、收獲成長和認同、領取優(yōu)惠和紅包等。

虛擬商品不可退

當前內(nèi)容為數(shù)字版權作品,購買后不支持退換且無法轉移使用。

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論
放大
實物圖
相關方案
  • 方案介紹
    • 前言
    • 一、模塊介紹
    • 二、資料獲取
    • 實驗效果
    • 三、代碼編寫
    • 四、參考資料
  • 相關文件
  • 推薦器件
  • 相關推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

前言

做一個項目需要用到,但是網(wǎng)上好多資料都沒有標準庫的,故移植寫一個方便以后開發(fā)使用

一、模塊介紹

霍尼韋爾 HMC5883L 是一種表面貼裝的高集成模塊,并帶有數(shù)字接口的弱磁傳感器芯片,應用于低成本羅盤和磁場檢測領域。HMC5883L 包括最先進的高分辨率HMC118X 系列磁阻傳感器,并附帶霍尼韋爾專利的集成電路包括放大器、自動消磁驅(qū)動器、偏差校準、能使羅盤精度控制在1°~2°的12 位模數(shù)轉換器.簡易的I2C 系列總線接口。HMC5883L 是采用無鉛表面封裝技術,帶有16 引腳,尺寸為3.0X3.0X0.9mm。HMC5883L 的所應用領域有手機、筆記本電腦、消費類電子、汽車導航系統(tǒng)和個人導航系統(tǒng)。

HMC5883L 采用霍尼韋爾各向異性磁阻(AMR)技術,該技術的優(yōu)點是其他磁傳感器技術所無法企及。這些各向異性傳感器具有在軸向高靈敏度和線性高精度的特點.傳感器帶有的對于正交軸低敏感行的固相結構能用于測量地球磁場的方向和大小,其測量范圍從毫高斯到 8 高斯(gauss)。 霍尼韋爾的磁傳感器在低磁場傳感器行業(yè)中是靈敏度最高和可靠性最好的傳感器。

二、資料獲取

關注微信公眾號--星之援工作室 發(fā)送關鍵字(HMC5883L

????

實驗效果

我主要實驗一下對金屬的反饋效果,達到檢測車輛的作用,測試使用的是X軸,得到的結果還是符合預期,可以針對進出不同方向達到測試車輛行駛的方向進行記錄

接線方式如下

?首先確認一個位置,并且查看X軸數(shù)據(jù)(可以自信更新方位和檢測軸,道理一樣)

測試所得

當金屬在左側時,X軸反饋數(shù)據(jù)會大于無物體數(shù)據(jù)
反之,當金屬在左側時,X軸反饋數(shù)據(jù)會小于于無物體數(shù)據(jù)

這樣就可以判斷我們車輛的行駛方向

?連接串口可以輸出我們獲取到的消息

三、代碼編寫

?首先,模塊用到了IIC通信,我們需要進行模擬IIC通信,全部代碼如下,完整工程可以在vx公眾號獲取

main.c

/*--------------------------------------------------------*
 *                                       								  *
 *   星之援網(wǎng)絡科技工作室學習資料v1.0    									*
 *		 時間:2022.7.14                    								*
 *		 程序介紹:HMC5883L 使用               							*
 *		 實現(xiàn)效果:串口輸出 XYZ軸 以及偏轉角度  						*
 *                                      							    *
 *--------------------------------------------------------*
*/

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "hmc5883l.h"

extern HMC_XYZ hmc_xyz_init; // 初始化結構體

int main(void)
{
	delay_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //設置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應優(yōu)先級
	LED_GPIO_Config();	// LED 端口初始化 
	uart_init(115200);// 串口初始化

  GY_IIC_Init() ;
	HMC5883_Init(); // HMC5883L初始
	printf("init okn");
  while(1)
	{

		HMC5883_Get_Angle();// 讀數(shù)據(jù)
		printf("X:%d Y:%d Z:%d Angle:%.1fn",hmc_xyz_init.HMC_X,hmc_xyz_init.HMC_Y,
																		 hmc_xyz_init.HMC_Z,hmc_xyz_init.Angle );
		delay_ms(250);
		LED1_TOGGLE;
  }   
}

hmc5883l.h

#ifndef __HMC_H
#define __HMC_H
 
#include "stm32f10x_conf.h"
#include "sys.h"
 
// 結構體
typedef struct
{
	short HMC_X;
	short	HMC_Y;
	short HMC_Z; // HMC5883三軸數(shù)據(jù)輸出
	float Angle; // 偏轉角度
	
} HMC_XYZ;
 
#define SlaveAddress 0X3C     //HMC5883L從機地址
#define SelfTest_EN 1

#define CRA 0x00
#define CRB 0x01
#define MR 0x02
#define DOXMR 0x03
#define DOXLR 0x04
#define DOZMR 0x05
#define DOZLR 0x06
#define DOYMR 0x07
#define DOYLR 0x08
#define SR 0x09
#define IRA 0x0A
#define IRB 0x0B
#define IRC 0x0C

#define GY_IN_GPIO_PORT GPIOB               /* GPIO端口 */
#define GY_IN_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define GY_IN_GPIO_PIN GPIO_Pin_7           /* 連接到SCL時鐘線的GPIO */

#define GY_SCLK__GPIO_PORT GPIOB              /* GPIO端口 */
#define GY_SCLK_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define GY_SCLK__GPIO_PIN GPIO_Pin_9          /* 連接到SCL時鐘線的GPIO */

#define GY_DATA__GPIO_PORT GPIOB              /* GPIO端口 */
#define GY_DATA_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define GY_DATA__GPIO_PIN GPIO_Pin_8          /* 連接到SCL時鐘線的GPIO */

// IO操作函數(shù)
#define GY_IIC_SCL PBout(9) // SCL
#define GY_IIC_SDA PBout(8) // SDA
#define GY_READ_SDA PBin(8) // 輸入SDA
 
//IIC所有操作函數(shù)
void GY_IIC_Delay(void);				//MPU IIC延時函數(shù)
void GY_IIC_Init(void);                 //初始化IIC的IO口				 
void GY_IIC_Start(void);				//發(fā)送IIC開始信號
void GY_IIC_Stop(void);	  			    //發(fā)送IIC停止信號
void GY_IIC_Send_Byte(u8 txd);			//IIC發(fā)送一個字節(jié)
u8   GY_IIC_Read_Byte(unsigned char ack);//IIC讀取一個字節(jié)
u8   GY_IIC_Wait_Ack(void); 				//IIC等待ACK信號
void GY_IIC_Ack(void);					//IIC發(fā)送ACK信號
void GY_IIC_NAck(void);				     //IIC不發(fā)送ACK信號
 
 
// HMC5883L
u8 HMC5883_SB_Read(u8 Slave_Address, u8 Register_Address) ;
u8 HMC5883_SB_Write(u8 Slave_Address, u8 Register_Address, u8 Register_Data) ;
void HMC5883_Init(void) ;
void HMC5883_Get_Angle(void);
void HMC5883_Get_XYZ(short* x, short* y, short* z);
 
#endif

hmc5883l.C

#include "hmc5883l.h"
#include "math.h"
#include "delay.h"
#include "usart.h"
HMC_XYZ hmc_xyz_init; // 初始化結構體
 
//==============================模擬IIC函數(shù)區(qū)===================================== 
void GY_IIC_Delay(void)
{
	delay_us(2);
}
// 配置雙向I/O端口為輸出態(tài)
static void GY_SDA_OUT()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(GY_DATA_GPIO_CLK, ENABLE);

	GPIO_InitStructure.GPIO_Pin = GY_DATA__GPIO_PIN; // PC.10  DATA
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GY_DATA__GPIO_PORT, &GPIO_InitStructure); // 初始化GPIOC.10
}
// 配置雙向I/O端口為輸入態(tài)
static void GY_SDA_IN()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(GY_DATA_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GY_DATA__GPIO_PIN; // PC.10 DATA
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GY_DATA__GPIO_PORT, &GPIO_InitStructure); // 初始化GPIOC.10
}
//初始化IIC
void GY_IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(GY_DATA_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GY_DATA__GPIO_PIN; // PC.11  CE
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出
	GPIO_Init(GY_DATA__GPIO_PORT, &GPIO_InitStructure); // 初始化GPIOC.11

	GPIO_InitStructure.GPIO_Pin = GY_SCLK__GPIO_PIN; // PC.12  SCLK
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出
	GPIO_Init(GY_SCLK__GPIO_PORT, &GPIO_InitStructure); // 初始化GPIOC.12

	GY_IIC_SCL = 1;
	GY_IIC_SDA = 1;
 
}
//產(chǎn)生IIC起始信號
void GY_IIC_Start(void)
{
	GY_SDA_OUT();     //sda線輸出
	GY_IIC_SDA=1;	  	  
	GY_IIC_SCL=1;
	GY_IIC_Delay();
 	GY_IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	GY_IIC_Delay();
	GY_IIC_SCL=0;//鉗住I2C總線,準備發(fā)送或接收數(shù)據(jù) 
}	  
//產(chǎn)生IIC停止信號
void GY_IIC_Stop(void)
{
	GY_SDA_OUT();//sda線輸出
	GY_IIC_SCL=0;
	GY_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	GY_IIC_Delay();
	GY_IIC_SCL=1;  
	GY_IIC_SDA=1;//發(fā)送I2C總線結束信號
	GY_IIC_Delay();							   	
}
//等待應答信號到來
//返回值:1,接收應答失敗
//        0,接收應答成功
u8 GY_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	GY_SDA_IN();      //SDA設置為輸入  
	GY_IIC_SDA=1;GY_IIC_Delay();	   
	GY_IIC_SCL=1;GY_IIC_Delay();	 
	while(GY_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			GY_IIC_Stop();
			return 1;
		}
	}
	GY_IIC_SCL=0;//時鐘輸出0 	   
	return 0;  
} 
//產(chǎn)生ACK應答
void GY_IIC_Ack(void)
{
	GY_IIC_SCL=0;
	GY_SDA_OUT();
	GY_IIC_SDA=0;
	GY_IIC_Delay();
	GY_IIC_SCL=1;
	GY_IIC_Delay();
	GY_IIC_SCL=0;
}
//不產(chǎn)生ACK應答		    
void GY_IIC_NAck(void)
{
	GY_IIC_SCL=0;
	GY_SDA_OUT();
	GY_IIC_SDA=1;
	GY_IIC_Delay();
	GY_IIC_SCL=1;
	GY_IIC_Delay();
	GY_IIC_SCL=0;
}					 				     
//IIC發(fā)送一個字節(jié)
//返回從機有無應答
//1,有應答
//0,無應答			  
void GY_IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	GY_SDA_OUT(); 	    
    GY_IIC_SCL=0;//拉低時鐘開始數(shù)據(jù)傳輸
    for(t=0;t<8;t++)
    {              
        GY_IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		GY_IIC_SCL=1;
		GY_IIC_Delay(); 
		GY_IIC_SCL=0;	
		GY_IIC_Delay();
    }	 
} 	    
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK   
u8 GY_IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	GY_SDA_IN();//SDA設置為輸入
    for(i=0;i<8;i++ )
	{
        GY_IIC_SCL=0; 
        GY_IIC_Delay();
		GY_IIC_SCL=1;
        receive<<=1;
        if(GY_READ_SDA)receive++;   
		GY_IIC_Delay(); 
    }					 
    if (!ack)
        GY_IIC_NAck();//發(fā)送nACK
    else
        GY_IIC_Ack(); //發(fā)送ACK   
    return receive;
}
//==================================模擬IIC-END==============================
 
 
 
 
//==========================HMC5883函數(shù)定義=============================
 
u8 HMC5883_SB_Read(u8 Slave_Address, u8 Register_Address) 
{
    static u8 Res_Data = 0;
    GY_IIC_Start(); 
	GY_IIC_Send_Byte(Slave_Address);//0X3C	
	GY_IIC_Wait_Ack();		//等待應答 
    GY_IIC_Send_Byte(Register_Address);	//寄存器地址
    GY_IIC_Wait_Ack();		//等待應答
    GY_IIC_Start();
	GY_IIC_Send_Byte(Slave_Address + 1);//0X3D	
    GY_IIC_Wait_Ack();		//等待應答 
	Res_Data=GY_IIC_Read_Byte(0);//讀取數(shù)據(jù),發(fā)送nACK 
    GY_IIC_Stop();			//產(chǎn)生一個停止條件 
	return Res_Data;		
}
 
u8 HMC5883_SB_Write(u8 Slave_Address, u8 Register_Address, u8 Register_Data)
{
     GY_IIC_Start(); 
	 GY_IIC_Send_Byte(Slave_Address);//發(fā)送設備地址
	 if(GY_IIC_Wait_Ack())	//等待應答
	 {
	 	 GY_IIC_Stop();		 
 		 return 1;		
	 }
     GY_IIC_Send_Byte(Register_Address); //寫寄存器地址
     GY_IIC_Wait_Ack();		          //等待應答 
	 GY_IIC_Send_Byte(Register_Data);    //發(fā)送數(shù)據(jù)
	 if(GY_IIC_Wait_Ack())	              //等待ACK
	 {
	 	 GY_IIC_Stop();	 
		 return 1;		 
	 }		 
     GY_IIC_Stop();	 
     return 0;
     
}

uint8_t SF=0;  //Self Test Flag
void HMC5883_Init(void)
{
	uint8_t Reg[13];
	GY_IIC_Init() ;
	
	Reg[0] = HMC5883_SB_Read(SlaveAddress,CRA);
	Reg[1] = HMC5883_SB_Read(SlaveAddress,CRB);
	Reg[2] = HMC5883_SB_Read(SlaveAddress,MR);
	Reg[3] = HMC5883_SB_Read(SlaveAddress,DOXMR);
	Reg[4] = HMC5883_SB_Read(SlaveAddress,DOXLR);
	Reg[5] = HMC5883_SB_Read(SlaveAddress,DOZMR);
	Reg[6] = HMC5883_SB_Read(SlaveAddress,DOZLR);
	Reg[7] = HMC5883_SB_Read(SlaveAddress,DOYMR);
	Reg[8] = HMC5883_SB_Read(SlaveAddress,DOYLR);
	Reg[9] = HMC5883_SB_Read(SlaveAddress,SR);
	Reg[10] = HMC5883_SB_Read(SlaveAddress,IRA); //data = 0x48
	Reg[11] = HMC5883_SB_Read(SlaveAddress,IRB); //data = 0x34
	Reg[12] = HMC5883_SB_Read(SlaveAddress,IRC); //data = 0x33

	if(!((Reg[10]==0x48)&&(Reg[11]==0x34)&&(Reg[12]==0x33)))
	{
		printf("HMC5883 I2C access failure!rn");
		printf("HMC5883 regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%xrn", Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], Reg[5], Reg[6], Reg[7], Reg[8], Reg[9], Reg[10], Reg[11], Reg[12]);
	}
	else
	{
		printf("HMC5883 I2C access OK!rn");
		printf("HMC5883 regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%xrn", Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], Reg[5], Reg[6], Reg[7], Reg[8], Reg[9], Reg[10], Reg[11], Reg[12]);


		HMC5883_SB_Write(SlaveAddress,CRA, 0X70);//samples average: 8; data output rate: 15Hz; measure mode: normal
		HMC5883_SB_Write(SlaveAddress,CRB, 0X20);//gain: ± 1.3 Ga
		HMC5883_SB_Write(SlaveAddress,MR, 0X00);//continuous-measurement mode

	}
}

//void HMC5883_Init(void)
//{
//    GY_IIC_Init() ;
//    HMC5883_SB_Write(SlaveAddress, 0X00, 0X58); //寫寄存器A,30Hz數(shù)據(jù)輸出、采樣平均數(shù)0
//    HMC5883_SB_Write(SlaveAddress, 0X01, 0X40); //寫寄存器B,傳感器量程+-0.88Ga、增益1370高斯
//    HMC5883_SB_Write(SlaveAddress, 0X02, 0X00); //寫寄存器C,連續(xù)數(shù)據(jù)輸出
//    
//}
 
 
void HMC5883_Get_Angle(void)
{
    u8 i ;

    short Recive_Data[6] ;   //store temperary data
    //HMC5883_Init() ;
    for(i=0; i<6; i++)
    {
        Recive_Data[i] = HMC5883_SB_Read(SlaveAddress, i+3) ;  //get data
    }
    
    hmc_xyz_init.HMC_X = Recive_Data[0]<<8 | Recive_Data[1];//Combine MSB and LSB of X Data output register
    hmc_xyz_init.HMC_Y = Recive_Data[2]<<8 | Recive_Data[3];//Combine MSB and LSB of Z Data output register
    hmc_xyz_init.HMC_Z = Recive_Data[4]<<8 | Recive_Data[5];//Combine MSB and LSB of Y Data output register
    
    hmc_xyz_init.Angle = atan2((double)hmc_xyz_init.HMC_Y,(double) hmc_xyz_init.HMC_X) * (180 / 3.14159265) + 180; // angle in degrees
}
 
void HMC5883_Get_XYZ(short* x, short* y, short* z)
{
	u8 i;
	short Recive_Data[6];
	//HMC5883_Init();
	for (i = 0; i < 6; i++) {
		Recive_Data[i] = HMC5883_SB_Read(SlaveAddress, i + 3);
	}
	*x = Recive_Data[0] << 8 | Recive_Data[1];
	*y = Recive_Data[2] << 8 | Recive_Data[3];
	*z = Recive_Data[4] << 8 | Recive_Data[5];
}

四、參考資料

STM32模擬I2C協(xié)議獲取HMC5883L電子羅盤磁角度數(shù)據(jù) (HAL)icon-default.png?t=N7T8https://blog.csdn.net/hwytree/article/details/126407447【STM32+cubemx】0029 HAL庫開發(fā):HMC5883L磁力計的應用(電子指南針)icon-default.png?t=N7T8https://blog.csdn.net/little_grapes/article/details/127895372?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171573961816800211552065%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171573961816800211552065&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-127895372-null-null.142%5Ev100%5Epc_search_result_base7&utm_term=HMC5883L&spm=1018.2226.3001.4187

聯(lián)系方式 微信號:13648103287

  • 聯(lián)系方式.docx

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
HAL506SF-A 1 TDK Corporation Hall Effect Sensor, 2mT Min, 7.2mT Max, 0-20mA, Rectangular, Surface Mount, PLASTIC, SOT-89B-1, 4 PIN
$1.38 查看
2SS52M-S 1 Honeywell Sensing and Control Magnetoresistive Sensor, 0.4mT Min, 2.5mT Max, 20mA, Plastic/epoxy, Rectangular, 3 Pin, Through Hole Mount, PLASTIC, 3 PIN
$4.32 查看
A1220LLHLT-T 1 Allegro MicroSystems LLC Hall Effect Sensor, -4mT Min, 4mT Max, 30-60mA, Rectangular, Surface Mount, SOT-23W, 3 PIN

ECAD模型

下載ECAD模型
$1.26 查看

相關推薦

電子產(chǎn)業(yè)圖譜

方案定制,程序設計方案、單片機程序設計與講解、APP定制開發(fā)。本公眾號致力于向讀者傳遞關于程序設計和開發(fā)的相關知識,并分享一些關于軟件開發(fā)的最佳實踐。如果您有什么問題或建議,請隨時聯(lián)系我們。我們將竭誠為您服務