HMC5883L

霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块,并带有数字接口的弱磁传感器芯片,应用于低成本罗盘和磁场检测领域。HMC5883L 包括最先进的高分辨率 HMC118X 系列磁阻传感器,并附带霍尼韦尔专利的集成电路包括放大器、自动消磁驱动器、偏差校准、能使罗盘精度控制在 1°~2°的 12 位模数转换器.简易的 I2C 系列总线接口。HMC5883L 是采用无铅表面封装技术,带有 16 引脚,尺寸为 3.0X3.0X0.9mm。HMC5883L 的所应用领域有手机、笔记本电脑、消费类电子、汽车导航系统和个人导航系统

   HMC5883主要有接口是IIC,同时提供一个数据中断引脚,一般而言,电路设计如下


  该传感器芯片的驱动并不复杂,主要是设置几个寄存器,如下所示

[cpp]  view plain  copy
  1. //HMC5883寄存器定义  
  2. //寄存器地址定义  
  3. #define HMC_CONFIG_A_REG    0X00    //配置寄存器A  
  4. //bit0-bit1 xyz是否使用偏压,默认为0正常配置  
  5. //bit2-bit4 数据输出速率, 110为最大75HZ 100为15HZ 最小000 0.75HZ  
  6. //bit5-bit5每次采样平均数 11为8次 00为一次  
  7.   
  8. #define HMC_CONFIG_B_REG    0X01    //配置寄存器B  
  9. //bit7-bit5磁场增益 数据越大,增益越小 默认001  
  10.   
  11. #define HMC_MODE_REG        0X02    //模式设置寄存器  
  12. //bit0-bit1 模式设置 00为连续测量 01为单一测量  
  13.   
  14. #define HMC_XMSB_REG        0X03    //X输出结果  
  15. #define HMC_XLSB_REG        0X04  
  16.   
  17. #define HMC_ZMSB_REG        0X05    //Z输出结果  
  18. #define HMC_ZLSB_REG        0X06  
  19.   
  20. #define HMC_YMSB_REG        0X07    //Y输出结果  
  21. #define HMC_YLSB_REG        0X08  
  22.   
  23. #define HMC_STATUS_REG      0X09    //只读的状态  
  24. //bit1 数据更新时该位自动锁存,等待用户读取,读取到一半的时候防止数据改变  
  25. //bit0 数据已经准备好等待读取了,DRDY引脚也能用  
  26.   
  27. #define HMC_CHEAK_A_REG     0X0A    //三个识别寄存器,用于检测芯片完整性  
  28. #define HMC_CHEAK_B_REG     0X0B  
  29. #define HMC_CHEAK_C_REG     0X0C  
  30.   
  31. #define HMC_CHECKA_VALUE    0x48    //三个识别寄存器的默认值  
  32. #define HMC_CHECKB_VALUE    0x34  
  33. #define HMC_CHECKC_VALUE    0x33  

建议选择最大速率,八倍采样输出,同时该传感器支持读写地址指针自动变化,但是针对随机读取的驱动而言,该特性不重要

另外,一般而言,地址为0x3c,驱动代码如下

[plain]  view plain  copy
  1. #include "hmc5883.h"  
  2. #include "math.h"  
  3.   
  4. struct HMCVALUE hmcValue;  
  5. u8 dataReady = 0;  
  6.   
  7.   
  8. //IO方向设置  
  9. #define HMC_SDA_IN()  {GPIOC->CRH&=0XFFFFFFF0;GPIOC->CRH|=8;}  
  10. #define HMC_SDA_OUT() {GPIOC->CRH&=0XFFFFFFF0;GPIOC->CRH|=3;}  
  11.   
  12. //IO操作函数       
  13. #define HMC_SCL    PCout(9) //SCL  
  14. #define HMC_SDA    PCout(8) //SDA      
  15. #define HMC_READ_SDA   PCin(8)  //输入SDA   
  16.   
  17. #define HMC_DRDY    PCin(7)  
  18.   
  19. /**************************HMC5883 IIC驱动函数*********************************/  
  20.   
  21. static void Hmc5883IOInit(void)  
  22. {  
  23.     GPIO_InitTypeDef GPIO_InitStructure;  
  24.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );   
  25.       
  26.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;  
  27.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出  
  28.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  29.     GPIO_Init(GPIOC, &GPIO_InitStructure);  
  30.       
  31.     //PC7 drdy引脚   
  32.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;  
  33.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;   //浮空输入  
  34.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  35.     GPIO_Init(GPIOC, &GPIO_InitStructure);  
  36.       
  37.     HMC_SCL = 1;  
  38.     HMC_SDA = 1;  
  39. }  
  40.   
  41.   
  42.   
  43. //发送IIC起始信号  
  44. static void ComStart(void)  
  45. {  
  46.     HMC_SDA_OUT();     //sda线输出  
  47.     HMC_SDA=1;          
  48.     HMC_SCL=1;  
  49.     DelayUs(5);  
  50.     HMC_SDA=0;//START:when CLK is high,DATA change form high to low   
  51.     DelayUs(5);  
  52.     HMC_SCL=0;//钳住I2C总线,准备发送或接收数据  
  53. }  
  54. //发送IIC停止信号  
  55. static void ComStop(void)  
  56. {  
  57.     HMC_SDA_OUT();//sda线输出  
  58.     HMC_SDA=0;//STOP:when CLK is high DATA change form low to high  
  59.     HMC_SCL=1;  
  60.     DelayUs(5);  
  61.     HMC_SDA=1;//发送I2C总线结束信号  
  62.     DelayUs(5);       
  63. }  
  64. //等待ACK,为1代表无ACK 为0代表等到了ACK  
  65. static u8 ComWaitAck(void)  
  66. {  
  67.     u8 waitTime = 0;  
  68.     HMC_SDA_OUT();//sda线输出  
  69.     HMC_SDA = 1;  
  70.     DelayUs(5);  
  71.     HMC_SDA_IN();      //SDA设置为输入  
  72.     HMC_SCL=1;  
  73.     DelayUs(5);  
  74.     while(HMC_READ_SDA)  
  75.     {  
  76.         waitTime++;  
  77.         DelayUs(1);  
  78.         if(waitTime > HMC_ACK_WAIT_TIME)  
  79.         {  
  80.             ComStop();  
  81.             return 1;  
  82.         }  
  83.     }  
  84.     HMC_SCL = 0;  
  85.     return 0;  
  86.       
  87. }  
  88.   
  89. static void ComSendAck(void)  
  90. {  
  91.     HMC_SCL = 0;  
  92.     HMC_SDA_OUT();  
  93.     HMC_SDA = 0;  
  94.     DelayUs(2);  
  95.     HMC_SCL = 1;  
  96.     DelayUs(5);  
  97.     HMC_SCL = 0;  
  98.     DelayUs(5);  
  99. }  
  100.   
  101. static void ComSendNoAck(void)  
  102. {  
  103.     HMC_SCL = 0;  
  104.     HMC_SDA_OUT();  
  105.     HMC_SDA = 1;  
  106.     DelayUs(2);  
  107.     HMC_SCL = 1;  
  108.     DelayUs(5);  
  109.     HMC_SCL = 0;  
  110.     DelayUs(5);  
  111. }  
  112. //返回0 写入收到ACK 返回1写入未收到ACK  
  113. static u8 ComSendByte(u8 byte)  
  114. {  
  115.     u8 t;     
  116.     HMC_SDA_OUT();    
  117.     for(t=0;t<8;t++)  
  118.     {                
  119.         HMC_SDA=(byte&0x80)>>7;  
  120.         byte<<=1;          
  121.         HMC_SCL=1;  
  122.         DelayUs(5);   
  123.         HMC_SCL=0;    
  124.         DelayUs(5);  
  125.     }      
  126.     return ComWaitAck();  
  127. }  
  128.   
  129. static void ComReadByte(u8* byte)  
  130. {  
  131.     u8 i,receive=0;  
  132.     HMC_SDA_IN();//SDA设置为输入  
  133.     for(i=0;i<8;i++ )  
  134.     {  
  135.         receive <<= 1;  
  136.         HMC_SCL=1;   
  137.         DelayUs(5);  
  138.         if(HMC_READ_SDA)receive++;  
  139.         HMC_SCL=0;   
  140.         DelayUs(5);   
  141.     }                       
  142.     *byte = receive;  
  143. }  
  144.   
  145. /**************************HMC5883 IIC驱动函数*********************************/  
  146.   
  147.   
  148. //向HMC写入一个字节数据,失败返回1 成功返回0  
  149. u8 Hmc5883WriteReg(u8 regValue,u8 setValue)  
  150. {  
  151.     u8 res;  
  152.     ComStart();                     //起始信号  
  153.     res = ComSendByte(HMC_ADDR);    //发送设备地址+写信号  
  154.     if(res)  
  155.     {  
  156.         #ifdef HMC_DEBUG  
  157.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  158.         #endif  
  159.         return res;  
  160.     }  
  161.     res = ComSendByte(regValue);    //内部寄存器地址  
  162.     if(res)  
  163.     {  
  164.         #ifdef HMC_DEBUG  
  165.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  166.         #endif  
  167.         return res;  
  168.     }  
  169.     res = ComSendByte(setValue);    //内部寄存器数据  
  170.     if(res)  
  171.     {  
  172.         #ifdef HMC_DEBUG  
  173.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  174.         #endif  
  175.         return res;  
  176.     }  
  177.     ComStop();                      //发送停止信号  
  178.     return res;  
  179. }  
  180.   
  181. //**************************************  
  182. //从I2C设备读取一个字节数据  
  183. //**************************************  
  184. u8 Hmc5883ReadReg(u8 regAddr,u8* readValue)  
  185. {  
  186.     u8 res;  
  187.     ComStart();                         //起始信号  
  188.     res = ComSendByte(HMC_ADDR);        //发送设备地址+写信号  
  189.     if(res)  
  190.     {  
  191.         #ifdef HMC_DEBUG  
  192.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  193.         #endif  
  194.         return res;  
  195.     }  
  196.     res = ComSendByte(regAddr);         //发送存储单元地址,从0开始   
  197.     if(res)  
  198.     {  
  199.         #ifdef HMC_DEBUG  
  200.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  201.         #endif  
  202.         return res;  
  203.     }  
  204.     ComStart();                         //起始信号  
  205.     res = ComSendByte(HMC_ADDR+1);      //发送设备地址+读信号  
  206.     if(res)  
  207.     {  
  208.         #ifdef HMC_DEBUG  
  209.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  210.         #endif  
  211.         return res;  
  212.     }  
  213.     ComReadByte(readValue);             //读出寄存器数据  
  214.     ComSendNoAck();                     //发送非应答信号  
  215.     ComStop();                          //停止信号  
  216.     return res;  
  217. }  
  218.   
  219.   
  220. static void HmcDefaultConfig(void)  
  221. {  
  222.     Hmc5883WriteReg(HMC_CONFIG_A_REG,HMC_DEFAULT_CONFIGA_VALUE);  
  223.     Hmc5883WriteReg(HMC_CONFIG_B_REG,HMC_DEFAULT_CONFIGB_VALUE);  
  224.     Hmc5883WriteReg(HMC_MODE_REG,HMC_DEFAULT_MODE_VALUE);  
  225. }  
  226.   
  227. //配置HMC drdy引脚中断  
  228. void HmcDrdyPinIntInit(void)  
  229. {  
  230.     EXTI_InitTypeDef EXTI_InitStructure;  
  231.     NVIC_InitTypeDef NVIC_InitStructure;  
  232.       
  233.     //GPIOC.7 中断线以及中断初始化配置   下降沿触发  
  234.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource7);  
  235.       
  236.     EXTI_InitStructure.EXTI_Line=EXTI_Line7;  
  237.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;   
  238.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断  
  239.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;  
  240.     EXTI_Init(&EXTI_InitStructure);     //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器  
  241.       
  242.     NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;          //使能所在的外部中断通道  
  243.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = HMC_DRDY_PreemptionPriority; //抢占优先级   
  244.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = HMC_DRDY_SubPriority;                   //子优先级  
  245.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                             //使能外部中断通道  
  246.     NVIC_Init(&NVIC_InitStructure);  
  247. }  
  248.   
  249. //对应的外部中断处理函数  
  250. void EXTI9_5_IRQHandler()  
  251. {  
  252.     if(EXTI_GetFlagStatus(EXTI_Line7) == SET)  
  253.     {  
  254.         EXTI_ClearFlag(EXTI_Line7);  
  255.         dataReady = 1;  
  256.     }  
  257. }  
  258. //失败返回1,初始化通过之后基本通讯就没有问题了就可以不再判定通讯结果了  
  259. u8 HmcInit(void)  
  260. {  
  261.     u8 hmcCheckValue = 0x00;  
  262.     u8 res = 0;  
  263.     Hmc5883IOInit();    //接口初始化  
  264.     while(HMC_DRDY == 1);//等待数据引脚正常  
  265.     HmcDrdyPinIntInit();//配置中断  
  266.     DelayMs(100);  
  267.     //验证A识别  
  268.     res = Hmc5883ReadReg(HMC_CHEAK_A_REG,&hmcCheckValue);  
  269.     if(res)  
  270.     {  
  271.         #ifdef HMC_DEBUG  
  272.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  273.         #endif  
  274.     }  
  275.     if(hmcCheckValue != HMC_CHECKA_VALUE)   //自检通过  
  276.     {  
  277.         return 1;  
  278.     }  
  279.     //验证B识别  
  280.     res = Hmc5883ReadReg(HMC_CHEAK_B_REG,&hmcCheckValue);  
  281.     if(res)  
  282.     {  
  283.         #ifdef HMC_DEBUG  
  284.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  285.         #endif  
  286.     }  
  287.     if(hmcCheckValue != HMC_CHECKB_VALUE)   //自检通过  
  288.     {  
  289.         return 1;  
  290.     }  
  291.     //验证C识别  
  292.     res = Hmc5883ReadReg(HMC_CHEAK_C_REG,&hmcCheckValue);  
  293.     if(res)  
  294.     {  
  295.         #ifdef HMC_DEBUG  
  296.         printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);  
  297.         #endif  
  298.     }  
  299.     if(hmcCheckValue != HMC_CHECKC_VALUE)   //自检通过  
  300.     {  
  301.         return 1;  
  302.     }  
  303.     HmcDefaultConfig();  
  304.     //全部验证通过  
  305.     return 0;  
  306. }  
  307.   
  308.   
  309.   
  310. void Hmc5883Reflush(void)  
  311. {  
  312.     u16 xValue = 0x00,yValue = 0x00,zValue = 0x00;  
  313.     u8 temp;  
  314.     Hmc5883ReadReg(HMC_XMSB_REG,&temp);  
  315.     xValue |= temp;  
  316.     xValue <<=8;  
  317.     Hmc5883ReadReg(HMC_XLSB_REG,&temp);  
  318.     xValue |=  temp;  
  319.       
  320.     Hmc5883ReadReg(HMC_ZMSB_REG,&temp);  
  321.     zValue |=  temp;  
  322.     zValue <<=8;  
  323.     Hmc5883ReadReg(HMC_ZLSB_REG,&temp);  
  324.     zValue |=  temp;  
  325.       
  326.     Hmc5883ReadReg(HMC_YMSB_REG,&temp);  
  327.     yValue |=  temp;  
  328.     yValue <<=8;  
  329.     Hmc5883ReadReg(HMC_YLSB_REG,&temp);  
  330.     yValue |=  temp;  
  331.       
  332.     hmcValue.hmcXvalue = (s16)xValue;  
  333.     hmcValue.hmcYvalue = (s16)yValue;  
  334.     hmcValue.hmcZvalue = (s16)zValue;  
  335.       
  336.     hmcValue.hmcAxis = atan2((double)hmcValue.hmcYvalue,(double)hmcValue.hmcXvalue) * (180 / 3.14159265) + 180; // angle in degrees  
  337.     #ifdef HMC_DEBUG  
  338.     printf("x = %d \t y = %d \t z = %d \t axis = %f\r\n",xValue,yValue,zValue,hmcValue.hmcAxis);  
  339.     #endif  
  340. }  

头文件定义如下(中断有优先级请自行定义)

[plain]  view plain  copy
  1. #ifndef __HMC5883_H_  
  2. #define __HMC5883_H_  
  3.   
  4. #include "common.h"  
  5. #include "stm32f10x.h"  
  6. #include "delay.h"  
  7. #include "ioremap.h"  
  8. #include "uart.h"  
  9.   
  10. #define HMC_DEBUG   1   //是否输出调试信息  
  11.   
  12. //没有主机改变地址的话地址是可以自动更新的,不过该驱动没有用这个模式  
  13.   
  14.   
  15. //HMC5883寄存器定义  
  16. //寄存器地址定义  
  17. #define HMC_CONFIG_A_REG    0X00    //配置寄存器A  
  18. //bit0-bit1 xyz是否使用偏压,默认为0正常配置  
  19. //bit2-bit4 数据输出速率, 110为最大75HZ 100为15HZ 最小000 0.75HZ  
  20. //bit5-bit5每次采样平均数 11为8次 00为一次  
  21.   
  22. #define HMC_CONFIG_B_REG    0X01    //配置寄存器B  
  23. //bit7-bit5磁场增益 数据越大,增益越小 默认001  
  24.   
  25. #define HMC_MODE_REG        0X02    //模式设置寄存器  
  26. //bit0-bit1 模式设置 00为连续测量 01为单一测量  
  27.   
  28. #define HMC_XMSB_REG        0X03    //X输出结果  
  29. #define HMC_XLSB_REG        0X04  
  30.   
  31. #define HMC_ZMSB_REG        0X05    //Z输出结果  
  32. #define HMC_ZLSB_REG        0X06  
  33.   
  34. #define HMC_YMSB_REG        0X07    //Y输出结果  
  35. #define HMC_YLSB_REG        0X08  
  36.   
  37. #define HMC_STATUS_REG      0X09    //只读的状态  
  38. //bit1 数据更新时该位自动锁存,等待用户读取,读取到一半的时候防止数据改变  
  39. //bit0 数据已经准备好等待读取了,DRDY引脚也能用  
  40.   
  41. #define HMC_CHEAK_A_REG     0X0A    //三个识别寄存器,用于检测芯片完整性  
  42. #define HMC_CHEAK_B_REG     0X0B  
  43. #define HMC_CHEAK_C_REG     0X0C  
  44.   
  45. #define HMC_CHECKA_VALUE    0x48    //三个识别寄存器的默认值  
  46. #define HMC_CHECKB_VALUE    0x34  
  47. #define HMC_CHECKC_VALUE    0x33  
  48.   
  49.   
  50. //HMC5883地址定义  
  51. #define HMC_ADDR          0X3C          //写地址,读地址+1  
  52.   
  53.   
  54. //HMC5883 初始化宏定义  
  55. #define HMC_DEFAULT_CONFIGA_VALUE       0x78     //75hz 8倍采样 正常配置  
  56. #define HMC_DEFAULT_CONFIGB_VALUE       0x00     //+-0.88GA增益  
  57. #define HMC_DEFAULT_MODE_VALUE          0x00     //连续测量模式  
  58.   
  59.   
  60. #define HMC_ACK_WAIT_TIME   200     //iic通讯时的ack等待时间  
  61.   
  62. //HMC5883驱动结构体定义  
  63. typedef struct HMCVALUE   
  64. {  
  65.     s16 hmcXvalue;  
  66.     s16 hmcYvalue;  
  67.     s16 hmcZvalue;  
  68.     double hmcAxis;  
  69. }HMCVALUE;  
  70.   
  71.   
  72.   
  73. u8 HmcInit(void);  
  74.   
  75. u8 Hmc5883WriteReg(u8 regValue,u8 setValue);  
  76.   
  77. u8 Hmc5883ReadReg(u8 regAddr,u8* readValue);  
  78.   
  79. void Hmc5883Reflush(void);  
  80.   
  81.   
  82.   
  83. extern struct HMCVALUE hmcValue;  
  84. extern u8 dataReady;  
  85.   
  86.   
  87. #endif  

引脚连接电路如下

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值