加入星計劃,您可以享受以下權(quán)益:

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

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

05/23 16:59
4903
服務(wù)支持:
技術(shù)交流群

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

虛擬商品不可退

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

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

前言

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

一、模塊介紹

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

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

二、資料獲取

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

????

實驗效果

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

接線方式如下

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

測試所得

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

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

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

三、代碼編寫

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

main.c

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

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

extern HMC_XYZ hmc_xyz_init; // 初始化結(jié)構(gòu)體

int main(void)
{
	delay_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(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"
 
// 結(jié)構(gòu)體
typedef struct
{
	short HMC_X;
	short	HMC_Y;
	short HMC_Z; // HMC5883三軸數(shù)據(jù)輸出
	float Angle; // 偏轉(zhuǎn)角度
	
} 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; // 初始化結(jié)構(gòu)體
 
//==============================模擬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總線結(jié)束信號
	GY_IIC_Delay();							   	
}
//等待應(yīng)答信號到來
//返回值:1,接收應(yīng)答失敗
//        0,接收應(yīng)答成功
u8 GY_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	GY_SDA_IN();      //SDA設(shè)置為輸入  
	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應(yīng)答
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應(yīng)答		    
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é)
//返回從機有無應(yīng)答
//1,有應(yīng)答
//0,無應(yīng)答			  
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設(shè)置為輸入
    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();		//等待應(yīng)答 
    GY_IIC_Send_Byte(Register_Address);	//寄存器地址
    GY_IIC_Wait_Ack();		//等待應(yīng)答
    GY_IIC_Start();
	GY_IIC_Send_Byte(Slave_Address + 1);//0X3D	
    GY_IIC_Wait_Ack();		//等待應(yīng)答 
	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ā)送設(shè)備地址
	 if(GY_IIC_Wait_Ack())	//等待應(yīng)答
	 {
	 	 GY_IIC_Stop();		 
 		 return 1;		
	 }
     GY_IIC_Send_Byte(Register_Address); //寫寄存器地址
     GY_IIC_Wait_Ack();		          //等待應(yīng)答 
	 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磁力計的應(yīng)用(電子指南針)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模型 風(fēng)險等級 參考價格 更多信息
LM95233CISD 1 National Semiconductor Corporation Switch/Digital Output Temperature Sensor, DIGITAL TEMP SENSOR-SERIAL, 11BIT(s), 2Cel, SQUARE, SURFACE MOUNT, LLP-14
$5.58 查看
DS18S20Z+ 1 Maxim Integrated Products Serial Switch/Digital Sensor, 9 Bit(s), 0.50Cel, Rectangular, 8 Pin, Surface Mount, ROHS COMPLIANT, SOP-8
$6.08 查看
LM50CIM3X 1 Texas Instruments &plusmn;2&deg;C analog output temperature sensor, with 10mV/&deg;C gain 3-SOT-23 -40 to 150

ECAD模型

下載ECAD模型
$1.52 查看

相關(guān)推薦

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

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