历史上的今天
返回首页

历史上的今天

今天是:2025年03月12日(星期三)

正在发生

2018年03月12日 | 基于STM32的三轴数字罗盘HMC5883L模块的测试方案

2018-03-12 来源:互联网

最近买了个数字罗盘模块,调通后发现很不错,非常灵敏,测试的时候精度在1°以内。连续测量模式下,最快测量、输出速率可达75hz,模块每次测量完毕并将数据更新至寄存器后,其DRDY引脚便产生一个低电平脉冲(可以配置一个外部中断捕获DRDY引脚的下降沿,并在中断服务程序中读取数据),在STM32中可以设置一个下降沿触发的外部中断,并在中断服务程序中调用角度数据读取函数。以下为操作该模块的主要步骤。


一、IIC协议相关操作(单片机作为主机控制时钟线)


  宏定义:

  //这里用到了STM32的位带区操作,方便实现对一个位的操作

  //PB13配置为OD输出,同时外部给上拉电阻,这样既可输出信号给从机,也能

  //在PB13为漏极开路状态时接收从机的信号(STM32的IO配置为输出模式时,

  //IO口的电平也会不断地被捕获到输入寄存器中)

  //PB14配置为推挽输出,PB15配置为浮空输入

  #defineR_SDAIPB13//PB13输入寄存器

  #defineW_SDAOPB13//PB13输出寄存器

  #defineW_SCLOPB14//PB14输出寄存器

  #defineR_DRDYIPB15//PB15输入寄存器

  #defineXmsb0//X轴数字量的高8位

  #defineXlsb1//X轴数字量的低8位

  #defineZmsb2//Z轴数字量的高8位

  #defineZlsb3//Z轴数字量的低8位

  #defineYmsb4//Y轴数字量的高8位

  #defineYlsb5//Y轴数字量的低8位

  附位带宏定义:

  #defineGPIOB_ODR_Addr(GPIOB_BASE+12)//0x40010C0C

  #defineGPIOB_IDR_Addr(GPIOB_BASE+8)//0x40010C08

  #defineBITBAND_Addr(Addr,num)((volaTIleunsignedlong*)(0x42000000+32*(Addr-0x40000000)+4*num))

  #defineIPB13*BITBAND_Addr(GPIOB_IDR_Addr,13)

  #defineOPB13*BITBAND_Addr(GPIOB_ODR_Addr,13)

  #defineOPB14*BITBAND_Addr(GPIOB_ODR_Addr,14)

  #defineIPB15*BITBAND_Addr(GPIOB_IDR_Addr,15)

  启动IIC传输:

  void_iic_Start()

  {

  W_SCL=1;

  W_SDA=1;

  _delay();

  W_SDA=0;//SCL高时,拉低SDA,表示开始IIC传输,占用总线

  _delay();

  W_SCL=0;//控制SCL

  _delay();

  }

  停止IIC传输:

  void_iic_Stop()

  {

  W_SCL=1;//释放SCL(由于没有其他主器件,SCL无需开漏)

  W_SDA=0;

  发送一个字节:

  uint8_t_iic_SendByte(uint8_tdat)

  {

  uint8_TI;

  for(i=0;i《8;i++)

  {

  _delay();

  W_SDA=dat》》7;//SCL拉高之前写SDA

  dat=dat《《1;

  _delay();

  W_SCL=1;//拉高SCL,从器件开始读取SDA

  _delay();

  W_SCL=0;//重新拉低SCL

  }

  W_SDA=1;//释放SDA

  W_SCL=1;//拉高SCL,读取从器件应答信号

  //等待应答

  i=100;

  while(i&&R_SDA){i--;_delay();}

  if(i==0)//无应答

  {

  W_SCL=0;//重新拉低SCL

  return0;

  }

  else{//有应答

  _delay();

  W_SCL=0;//重新拉低SCL

  return1;

  }

  }

  _delay();

  W_SDA=1;//SCL为高时,拉高SDA表示结束ICC传输,释放总线

  }

  接收一个字节:

  uint8_t_iic_ReadByte(uint8_tAck)

  {

  uint8_ttemp,i;

  W_SDA=1;//释放SDA

  _delay();

  for(i=0;i《8;i++)

  {

  _delay();

  W_SCL=1;//拉高SCL开始读取SDA

  temp=temp《《1;

  temp|=R_SDA;//SCL拉高之后读取SDA

  W_SCL=0;//拉低SCL,从器件开始放置数据

  }

  //发送应答信号

  if(Ack)W_SDA=0;//拉低SDA表示应答

  W_SCL=1;//拉高SCL,从器件接收应答信号

  _delay();

  W_SCL=0;//重新拉低SCL

  W_SDA=1;//释放SDA

  returntemp;

  }


  二、配置HMC5883L模块

  voidHMC5883L_Init()

  {

  _iic_Start();

  _iic_SendByte(0x3c);//写操作

  _iic_SendByte(0x00);//指针指向00,配置寄存器A

  _iic_SendByte(0x78);//数据测量、输出速率75hz

  _iic_Start();//指针定位到02,模式寄存器

  _iic_SendByte(0x3c);

  _iic_SendByte(0x02);

  _iic_SendByte(0x00);//连续测量模式

  _iic_Stop();

  }

  三、读取角度数据

  接收三轴数据,处理X,Y轴的数据并计算角度:

  int16_tHMC5883L_ReadAngle()

  {

  staTIcuint8_TI;

  staticuint8_tXYZ_Data[6];//用来存储三个轴输出的数字量

  _iic_Start();

  _iic_SendByte(0x3c);//发送HMC5883L的器件地址0x3c,写操作

  _iic_SendByte(0x03);//指针指向03,Xmsb寄存器

  _iic_Start();

  _iic_SendByte(0x3d);//改为读操作

  //依次读取三个轴的数字量

  for(i=0;i《5;i++)//前5次读取发送应答信号

  {

  XYZ_Data[i]=_iic_ReadByte(1);

  }

  XYZ_Data[5]=_iic_ReadByte(0);//不应答

  _iic_Stop();

  returnatan2((double)((int16_t)((XYZ_Data[Ymsb]《《8)+XYZ_Data[Ylsb])),(double)((int16_t)((XYZ_Data[Xmsb]《《8)+XYZ_Data[Xlsb])))*(180/3.14159265)+180;//计算角度,需要包含math.h头文件

  }


  配置好IO口,调用HMC5883L_Init()后,便可调用HMC5883L_ReadAngle()读取角度值,0~360°。以下为测试时的截图:


  测试时,模块比较灵敏且精确,稍微旋转模块便有精确的变化。由于该模块是基于对地磁场的测量,此模块容易受到其他磁场的干扰,比如将该模块靠近直流电机时,便会因为电机内的磁场而降低精度甚至失灵(之前做智能小车时就遇到这个问题,要将电机内的磁场屏蔽起来才行)。

推荐阅读

史海拾趣

问答坊 | AI 解惑

汽车点烟器输出电压和电流是多少呢?

汽车点烟器输出电压和电流是多少呢? 电脑的光驱有多少的电压和电流呢? 如果把光驱放到车上要接多大的电阻呢? 接什么东西 能把电流降到 1.5A 呢?  光驱的电流是1.5A  如果电流大了,光驱会坏吗? [ 本帖最后由 sunsonglin 于 2009-2-2 ...…

查看全部问答>

冰箱:高端驶入快车道 中国成全球“风向标”

本帖最后由 jameswangsynnex 于 2015-3-3 19:57 编辑 然国际金融危机给家电业带来了不小的冲击,但是受益于家电下乡、以旧换新等一系列利好政策,2009年我国的高端冰箱市场出现了快速增长的态势。另外,随着低碳理念的深入人心,企业节能技术不断 ...…

查看全部问答>

ARM Pc寄存器的一个问题

我在看书看到这样一段话: 对于arm指令集来说,PC指向当前指令的下两条指令的地址,由于ARM指令是字对齐的,PC值的第0位和第一位总为0, 这句话全不懂,谁能解释下呢…

查看全部问答>

问一下MSP430f42xx里的SAD( Sigma-Delta A/D)怎么用啊?

本帖最后由 paulhyde 于 2014-9-15 09:44 编辑 Sigma-Delta A/D 原理基本不懂····和逐次比较的有什么不同?还有怎样操作它?  …

查看全部问答>

基于ARM与SD卡的大容量数据存储技术的应用研究

0 引言   在现场测控系统中,RTU(远程测控终端)存储容量、存储数据的转移问题始终是RTU的重要环节。RTU的存储容量一般为几十K~几百K字节,数据转移通常采用不掉电静态RAM、EEPROM存储模块,或采用便携式计算机通过串行口读取RTU数据。 ...…

查看全部问答>

【悬赏求助】launchpad捕获按键按下的时间

最近在学习launchpad,中断方面困难重重。。。我想实现这样一个功能:P1.1设为输入,连接一个按键,然后利用中断判断按键按下的时间,要是短按的话就LED1翻转,长按的话LED2翻转。这样的话,我知道应该用捕获模式获取时间信息对吧,但是实现过程一 ...…

查看全部问答>

MSP430硬件I2C程序

MSP430硬件I2C程序,已测试通过,有兴趣的可探讨探讨…

查看全部问答>

今年刚大一下学期,学的电子信息专业,我应该入手怎样51单片机,本人小白,

刚刚进入大学,不想时间都被浪费,想自学51单片机,不知道怎么下手,     论坛的帖子也下了一些,也看了有一些,大二大三的学长要我先看书,    我到底是应该是先看书,还是边理论边实践,实践的话,应该买个什么样的51单片 ...…

查看全部问答>