【51单片机快速入门指南】4.4:I2C 读取HMC5883L / QMC5883L 磁力计
目錄
- 硬知識
- 簡介
- 操作模式
- HMC5883L
- 連續測量模式
- 單次測量模式
- 閑置模式
- QMC5883L
- 連續測量模式
- 待命模式
- 主要差異
- 寄存器
- 寄存器列表
- HMC5883L
- QMC5883L
- 配置寄存器
- HMC5883L
- 配置寄存器 A
- 配置寄存器 B
- 模式寄存器
- QMC5883L
- 控制寄存器1
- 控制寄存器2
- SET/RESET Period Register
- 數據輸出寄存器
- HMC5883L
- QMC5883L
- 狀態寄存器
- HMC5883L
- QMC5883L
- 識別寄存器
- HMC5883L
- QMC5883L
- 示例程序
- XMC5883L.c
- XMC5883L.h
- 測試程序
- 實驗現象
STC15F2K60S2 16.384MHz
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位機:Vofa+ 1.3.10
硬知識
摘自《HMC5883L中文規格書》、《QMC5883L Datasheet 1.0》、《QMC5883L寄存器對比及參考設置》、QMC5883L說明文檔 —— yedongnan001
簡介
HMC5883L
????????霍尼韋爾 HMC5883L 是一種表面貼裝的高集成模塊,并帶有數字接口的弱磁傳感器芯片,應用于低成本羅盤和磁場檢測領域。
QMC5883L
????????QMC5883L源于霍尼韋爾的HMC5883L,是一款表面貼裝的集成了信號處理電路的三軸磁性傳感器,應用場景主要包括羅盤、導航、無人機、機器人和手持設備等一些高精度的場合。
性能對比
操作模式
HMC5883L
連續測量模式
????????連續測量模式,在客戶所選擇的速率下進行連續的測量,并所測量的更新數據輸出寄存器。如果有必要,數據可以從數據輸出寄存器重新讀取,但是,如果主機并不能確保在下次測量完成之前可以訪問數據寄存器,數據寄存器上的舊的數據會被新的測量數據取代。為了保存測量之間的電流,該裝置被放置在一個類似閑置模式的狀態,但模式寄存器沒有改變成空閑模式。即MD[n]位不變。配置寄存器A的設置在連續測量模式時會影響數據輸出速率(比特DO[n]) ,測量配置(bits MS[n]),和增益(bits GN[n])。所有寄存器在連續測量模式中保留數值。 在連續測量模式下I2C總線可被網絡內的其他裝置啟用。
單次測量模式
????????這是預設的供電模式。在單測量模式,該裝置進行單次測量并將測量數據更新至輸出數據寄存器中。在完成測量和輸出數據寄存器的更新以后,通過設置MD[n] bits,該裝置被置于閑置模式,模式寄存器變更為閑置模式。配置寄存器的設置在單一測量模式時影響測量配置(bits MS[n])。。在單測量模式中所有寄存器保留數值。 在單測量模式下I2C總線可被網絡內其他裝置啟用。
閑置模式
????????在此模式下,裝置可以通過I2C總線訪問,但主要電源能耗是禁用的,如ADC,放大器,傳感器偏置電流,但不僅限于這些。在空閑模式下所有寄存器保留數值。在閑置測量模式下I2C總線可被網絡內其他裝置啟用。
QMC5883L
連續測量模式
????????此模式下,磁性傳感器連續進行測量并把測量數據置于數據輸出寄存器中。測量數據的偏移和溫度的影響將會自動得到補償。
????????正常情況下的讀順序:
????????測量時讀取
????????測量過程中讀取的將是之前測量過并保存過的數據,并且這一次測量完成后DRDY將不會被置“1”,即這一次測量的數據丟失掉了。
????????數據未讀取
????????如果第N個數據被跳過,當前的數據將會被接下來的數據覆蓋掉,此種情形下,DRDY保持高電平直到數據被讀取,DOR被置“1”,表示有一串數據丟失,同樣,下一次讀取操作后DOR將被置“0”。
????????數據鎖定直至下次測量結束
????????只要任意一個數據寄存器被讀取,所有測量數據將處于被鎖定狀態。如果下一次測量結束后,最后一個數據寄存器(05H)仍未被讀取,數據寄存器將會拒絕新數據更新當前數據的操作,注意看下圖,新數據將會被丟失。此類情形下,DOR將會被置“1”,直至下下次數據被讀取。
待命模式
????????QMC5883L上電后默認為待命模式。此狀態下,寄存器值將會通過一個超低功耗的LDO保持,對任意寄存器的讀寫操作都將會喚醒I2C總線接口。內部時鐘被停止,同時也不會進行磁場測量。
主要差異
????????HMC5883L和QMC5883L的寄存器地址配置不能說一模一樣,只能說毫不相關,甚至數據寄存器的順序及高位低位的先后都不一樣,程序如果不加以區分是絕對不能通用的。
????????如下表所示,
????????HMC5883的七位地址為0x1e(0x3c >> 1 = 0x1e)
????????QMC5883的七位地址為0x0d(0x18 >> 1 = 0x0d)(默認,SI接GND) 或 0x0c(0x1a >> 1 = 0x0c)(SI接VDD)
外觀差異
????????引自《用前必讀.txt》
????????進口HMC5883 —— IC絲印 L883
????????國產QMC5883 —— IC絲印 D5883
????????實際如下圖所示,我買到的是QMC5883L
寄存器
寄存器列表
HMC5883L
QMC5883L
配置寄存器
HMC5883L
配置寄存器 A
????????配置寄存器是用來配置該裝置設置的數據輸出速率和測量配置。 CRA0 通過 CRA7 表明位的位置,用 CAR 指示在配置寄存器中的位。 CRA7 指示數據流的第一位。括號中的數目顯示是該位的默認值。
????????下表的數據顯示在連續測量模式下的所有可選的輸出速率。所有這三個通道應在某一特定數據速率下測量。其他輸出速率可以通過控制單測量模式下的 DRDY 中斷引腳來獲得,最大速率為 160Hz。
配置寄存器 B
????????配置寄存器 B 設置裝置的增益。 CRB0 通過 CRB7 識別位的位置,用 CRB 指示在配置寄存器里的位。CRB7 表示數據流中的第一位。括號中的數目顯示的是位的默認值。
????????下表描述增益設置。使用以下“增益”一欄將counts轉換成Guass。在總共磁場強度引起所有數據輸出存儲器中一個溢位(飽和)時選擇較低的增益值(高GN#值)。
模式寄存器
????????該寄存器是一個8位可讀可寫的寄存器。該寄存器是用來設定裝置的操作模式。 MR0通過MR7識別位的位置,MR表明模式寄存器里的位。MR7指示數據流中的第一位。括號中的數字顯示的是位的默認值。
QMC5883L
控制寄存器1
????????控制寄存器1位于地址09H,它設置操作模式(MODE)。輸出數據更新速率(ODR),磁場測量范圍或傳感器的靈敏度(RNG)和過采樣率(OSR)。
????????兩個MODE寄存器可以傳輸設備中的操作模式,兩種模式是待機模式和連續測量模式。POR (Power-on-Reset)后默認模式為standby。模式之間的切換沒有任何限制。
????????輸出數據速率由ODR寄存器控制。數據更新頻率可選擇10Hz、50Hz、100Hz和200Hz四種頻率。對于大多數的封裝應用,我們推薦10hz的低功耗。對于游戲,可以使用高更新率,如100Hz或200Hz。
????????磁傳感器的磁場范圍可以通過寄存器RNG來選擇。全量程范圍由應用環境決定。對于磁清晰的環境,可以使用低場范圍,如+/- 2高斯。磁場范圍與磁傳感器的靈敏度密切相關。最低的視場范圍有最高的靈敏度,因此,更高的分辨率。
????????過采樣率(OSR)寄存器用于控制內部數字濾波器的帶寬。OSR值越大,濾波器帶寬越小,帶內噪聲越小,功耗越高。它可以用來達到噪音和功率之間的良好平衡。有四種過采樣率可選,64,128,256或512。
控制寄存器2
????????控制寄存器2位于地址0AH。它控制中斷引腳啟用(INT_ENB),點滾過功能啟用(POL_PNT)和軟復位(SOFT_RST)。
????????中斷啟用由控制寄存器2中的INT_ENB控制。一旦中斷被啟用,當新的數據在數據輸出寄存器中,它將置位。
????????INT_ENB:“0”:允許中斷PIN,“1”:禁止中斷PIN
指針滾轉函數由ROL_PNT寄存器控制。開啟點滾轉功能后,如果I2C讀取從00H ~ 06H的任意地址開始,則I2C數據指針自動在00H~06H之間滾動。
????????ROL_PNT: 0:正常,1:開啟指針滾轉功能
????????軟復位可以通過將寄存器SOFT_RST更改為set來實現。軟復位可以在任何時間、任何模式下調用。例如,如果軟復位發生在連續模式讀取中間,由于模式寄存器默認被重置為“00”,QMC5883L立即切換到待機模式。
????????SOFT_RST:“0”:正常。“1”:軟復位,恢復所有寄存器的默認值。
SET/RESET Period Register
????????SET/RESET周期由FBR[7:0]控制。建議將寄存器0BH寫成0x01。
數據輸出寄存器
HMC5883L
數據輸出 X 寄存器 A 和B
????????數據輸出 X 寄存器是兩個 8 位寄存器,數據輸出寄存器 A 和 B。這些寄存器儲存從通道 X 所測量結果。數據輸出 X 寄存器 A 儲存一個來自測量結果中的 MSB(高位數據),數據輸出 X 寄存器 B 儲存一個來自測量結果中的 LSB(低位數據)。存儲在這兩個寄存器的值是一個 16 位值以二進制的補碼形式存在,其范圍是 0xF800到 0x07FF。DXRA0 至 DXRA7、DXRB0 至 DXRB7 標識出位置, DXRA 和 DXRB 標識出在數據輸出寄存器 X 中的位。DXRA7 和 DXRB7 標識出數據流的第一位,括號中的數目顯示該位的默認值。
????????在事件的ADC上溢或下溢閱讀給定的通道,或者如果有一個數學溢出的過程,這種數據寄存器將包含-4096的值。在下一次有效測量完成進行之后,該寄存器上的值將被清除。
數據輸出 Y 寄存器 A 和B
????????數據輸出 Y 寄存器是兩個 8 位寄存器,數據輸出寄存器 A 和 B,這些寄存器儲存從通道 Y 所測量的結果。數據輸出 Y 寄存器 A 儲存一個來自測量結果中的 MSB(高位數據),數據輸出 Y 寄存器 B 包含一個來自測量結果中的 LSB(低位數據)。存儲在這兩個寄存器的值是一個 16 位值以二進制的補碼形式存在,其范圍是0xF800 到 0x07FF。DYRA0 至 DYRA7、DYRB0 至 DYRB7 標識位置, DYRA 和 DYRB 標識在數據輸出寄存器 Y 中的位。DYRA7 和 DYRB7 標識數據流的第一位。括號中的數目顯示該位的默認值。
????????在事件的ADC上溢或下溢閱讀給定的通道,或者如果有一個數學溢出的過程,這種數據寄存器將包含值為-4096。在下一次有效測量進行之后,該寄存器上的值將被清除。
數據輸出 Z 寄存器 A 和 B
????????數據輸出 Z 寄存器是兩個 8 位寄存器,數據輸出寄存器 A 和 B,這些寄存器儲存從通道 Z 所測量的結果。數據輸出 Z 寄存器 A 儲存一個來自測量結果中的 MSB(高位數據),數據輸出 Z 寄存器 B 包含一個來自測量結果中的 LSB(低位數據)。存儲在這兩個寄存器的值是一個 16 位值以二進制的補碼形式存在,其范圍是0xF800 到 0x07FF。DZRA0 至 DZRA7、DZRB0 至 DZRB7 標識位置,DZRA 和 DZRB,標識在數據輸出寄存器 Z 中的位。DZRA7 和 DZRB7 標識數據流的第一位。括號中的數目顯示該位的默認值。
????????在事件的ADC上溢或下溢閱讀給定的通道,或者如果有一個數學溢出的過程,這種數據寄存器將包含價值-4096。在下一次有效測量進行之后,該寄存器上的值將被清除。
數據輸出寄存器操作
????????當一個或一個以上的輸出寄存器在被讀取時,如果所有六種數據輸出寄存器未被讀取完,那么新的數據不能被更新到相應的數據輸出寄存器。這一要求也影響 DRDY 和 RDY ,在新的數據未被更新到所有輸出寄存器之前是不能被清除的。
QMC5883L
????????寄存器00H ~ 05H存儲連續測量中各軸磁傳感器的測量數據。
????????在連續測量模式下,輸出數據根據控制寄存器1中的數據更新速率ODR設置定期刷新。無論通過I2C讀取狀態如何,數據都保持不變,直到新數據替換它們。每條軸的數據寬度為16位2的補碼,即01H/03H/05H的MSB表示每條軸的符號。每個通道的輸出數據范圍為-32768到32767。
溫度數據寄存器
????????寄存器07H-08H存儲溫度傳感器輸出數據。16位溫度傳感器輸出是2的補碼。
????????溫度傳感器的增益是工廠校準的,但其偏移量沒有被補償,只有相對溫度值是準確的。溫度系數約為100 LSB/℃
狀態寄存器
HMC5883L
????????狀態寄存器是一個8位只讀寄存器。該寄存器是表明裝置的狀態, SR0到SR7表明位的位置,SR表明在狀態寄存器的位, SR7指數據流的第一位。
QMC5883L
????????有兩個狀態寄存器位于地址06H和0CH。
????????寄存器06H有三個位表示狀態標志,其余為工廠使用保留。狀態寄存器是只讀位。
????????數據就緒寄存器(Data Ready Register, DRDY),當所有三軸數據就緒時設置,并在連續測量模式下加載到輸出數據寄存器。通過I2C推薦通過讀取任何數據寄存器(00H~05H)將其重置為“0”
????????DRDY: 0:無新數據,1:有新數據
????????如果三軸磁傳感器通道有數據超出范圍,則設置溢出標志(OVL)為“1”。每個軸的輸出數據在-32768和32767處飽和,如果任何一個軸超過這個范圍,OVL標志設置為“1”。如果下一次測量回到(-32768,32767)的范圍,該標志將被重置為“0”,否則,它將保持為“1”。
????????OVL: 0:正常,1:數據溢出
????????如果在連續測量模式下讀取時跳過輸出數據寄存器的所有通道,則數據跳過位設置為“1”。通過I2C讀取任何數據寄存器(00H~05H),復位為“0”
????????DOR: 0:正常,1:跳過數據讀取
識別寄存器
HMC5883L
識別寄存器 A
????????識別寄存器 A 是用來識別裝置。IRA0 通過 IRA7 表明位的位置,而 IRA 表明在識別寄存器 A 中的位。IRA7 指數據流的第一位。括號中的數目顯示的默認值是位
????????該裝置的識別值存儲在本寄存器中。這是一個只讀寄存器。
????????寄存器值: ASCII 值 H
識別寄存器 B
????????識別寄存器 B 是用來識別裝置。IRB0 到 IRB7 表明位的位置,而 IRB 表明在識別寄存器 B 中的位。IRB7 指數據流的第一位。
????????寄存器值:ASCII 值 4
識別寄存器 C
????????鑒定寄存器 C 是用來識別裝置,IRC0 到 IRC7 表明位的位置,而 IRC 表明在識別寄存器 C 中的位,IRC7 指數據流的第一位。
????????寄存器值: ASCII 值 3
QMC5883L
????????這個寄存器是芯片識別寄存器。它返回0xff。
示例程序
???????stdint.h見【51單片機快速入門指南】1:基礎知識和工程創建
???????軟件I2C程序見【51單片機快速入門指南】4: 軟件 I2C
???????串口部分見【51單片機快速入門指南】3.3:USART 串口通信
XMC5883L.c
/** ****************************************************************************** * @file XMC5883L.c * @author Royic * @date 2021-11-27 * @brief XMC5883L傳感器驅動 ****************************************************************************** */ #include "XMC5883L.h" #include "./Software_I2C/Software_I2C.h"static int i2cWrite(uint8_t reg_, uint8_t Data) {return i2c_mem_write(MAG_ADDRESS, reg_, &Data, 1); }static int i2cRead(uint8_t reg_, uint8_t len, uint8_t* buf) {return i2c_mem_read(MAG_ADDRESS, reg_, buf, len); }/** * @brief xmc5883初始化,包含傳感器校準 * @note */ void xmc5883lInit(void) { #ifdef HMC5883Li2cWrite(ConfigRegA, Sample_MAX << 5 | DataOutputRate_Max << 2 | NormalOperation);i2cWrite(ConfigRegB, Full_Scale_1_9G << 5);i2cWrite(ModeRegister, ContinuousConversion); #endif #ifdef QMC5883Li2cWrite(ConfigReg1, Sample_MAX << 6 | Full_Scale_2G << 4 | DataOutputRate_Max << 2 | ContinuousConversion);i2cWrite(ConfigReg2, Enable_Interrupt_PIN << 7 | ROL_PNT_Normal << 6 | SOFT_RST_Normal);i2cWrite(Period_FBR, 0x01); #endif }/** * @brief 讀取磁場傳感器數據。 * @note * @param magData:存儲磁場傳感器原始數據的指針 */ #ifdef QMC5883Lint16_t QMC5883L_Temp = 0; #endif void xmc5883lRead(int16_t *mag_x, int16_t *mag_y, int16_t *mag_z) { #ifdef HMC5883Luint8_t buf[6];i2cRead(MAG_DATA_REGISTER, 6, buf);*mag_x = buf[0] << 8 | buf[1];*mag_z = buf[2] << 8 | buf[3];*mag_y = buf[4] << 8 | buf[5]; #endif #ifdef QMC5883Luint8_t buf[9];i2cRead(MAG_DATA_REGISTER, 9, buf);*mag_x = buf[0] | buf[1] << 8;*mag_y = buf[2] | buf[3] << 8;*mag_z = buf[4] | buf[5] << 8;QMC5883L_Temp = buf[7] | buf[8] << 8; #endif }XMC5883L.h
#ifndef XMC5883L_H_ #define XMC5883L_H_#include "XMC5883L.h" #include "stdint.h"#define QMC5883L //#define HMC5883L #define _FAIL 1 #define _SUCCESS 0#ifdef QMC5883L#ifdef HMC5883L#error //同時define了QMC5883L、HMC5883L#endif #endif#ifdef HMC5883L#define MAG_ADDRESS 0x1E#define MAG_DATA_REGISTER 0x03#define MAG_X_DATA_REGISTER 0x03#define MAG_Y_DATA_REGISTER 0x07#define MAG_Z_DATA_REGISTER 0x05#define ConfigRegA 0x00// ConfigRegA valid Data output rates for 5883L#define DataOutputRate_0_75HZ 0x00#define DataOutputRate_1_5HZ 0x01#define DataOutputRate_3HZ 0x02#define DataOutputRate_7_5HZ 0x03#define DataOutputRate_15HZ 0x04#define DataOutputRate_30HZ 0x05#define DataOutputRate_75HZ 0x06#define DataOutputRate_Max DataOutputRate_75HZ// ConfigRegA valid sample averaging for 5883L#define SampleAveraging_1 0x00#define SampleAveraging_2 0x01#define SampleAveraging_4 0x02#define SampleAveraging_8 0x03#define Sample_MAX SampleAveraging_8#define NormalOperation 0x00#define PositiveBiasConfig 0x01#define NegativeBiasConfig 0x02#define ConfigRegB 0x01#define Full_Scale_0_88G 0x00#define Full_Scale_1_3G 0x01#define Full_Scale_1_9G 0x02#define Full_Scale_2_5G 0x03#define Full_Scale_4_0G 0x04#define Full_Scale_4_7G 0x05#define Full_Scale_5_6G 0x06#define Full_Scale_8_1G 0x07#define ModeRegister 0x02#define ContinuousConversion 0x00#define SingleConversion 0x01#define StatusReg 0x09 #define IDRegA 0x0A#define IDRegB 0x0B#define IDRegC 0x0C #endif#ifdef QMC5883L // #define MAG_ADDRESS 0x0C //SI = GND#define MAG_ADDRESS 0x0D //SI = VDD#define MAG_DATA_REGISTER 0x00#define MAG_X_DATA_REGISTER 0x00#define MAG_Y_DATA_REGISTER 0x02#define MAG_Z_DATA_REGISTER 0x04#define MAG_TEMP_DATA_REGISTER 0x07#define ConfigReg1 0x09// ConfigReg1 valid Data output rates for 5883L#define DataOutputRate_10HZ 0x00#define DataOutputRate_50HZ 0x01#define DataOutputRate_100HZ 0x02#define DataOutputRate_200HZ 0x03#define DataOutputRate_Max DataOutputRate_200HZ#define SampleOverRatio_512 0x00#define SampleOverRatio_256 0x01#define SampleOverRatio_128 0x02#define SampleOverRatio_64 0x03#define Sample_MAX SampleOverRatio_512#define Full_Scale_2G 0x00#define Full_Scale_8G 0x01#define StandbyConversion 0x00#define ContinuousConversion 0x01#define ConfigReg2 0x0A#define Enable_Interrupt_PIN 0x00#define Disable_Interrupt_PIN 0x01#define ROL_PNT_Normal 0x00#define ROL_PNT_Enable 0x01#define SOFT_RST_Normal 0x00#define SOFT_RST_Reset 0x01#define StatusReg 0x06#define Period_FBR 0x0b#define IDReg 0x0d //可讀到0xFFextern int16_t QMC5883L_Temp; #endifvoid xmc5883lInit(void); void xmc5883lRead(int16_t *mag_x, int16_t *mag_y, int16_t *mag_z);#endif //------------------End of File----------------------------測試程序
#include <STC15F2K60S2.H> #include "intrins.h" #include "stdint.h" #include "USART.h" #include "./Software_I2C/Software_I2C.h" #include "XMC5883L.h"void Delay1ms() //@16.384MHz {unsigned char i, j;i = 16;j = 237;do{while (--j);} while (--i); }void delay_ms(uint32_t ms) {while(ms --)Delay1ms(); }#define LED_PORT P0void main(void) {int16_t mag_x, mag_y, mag_z;AUXR &= 0xBF; //定時器時鐘12T模式 1T的51使用12T的定時器程序時需要加入這兩句AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 16384000, 1200, DOUBLE_BAUD_ENABLE, USART_TIMER_1);xmc5883lInit();while(1){xmc5883lRead(&mag_x, &mag_y, &mag_z);printf("%d,%d,%d\r\n", mag_x, mag_y, mag_z);} }實驗現象
轉動板子,可見數據隨之變化。
總結
以上是生活随笔為你收集整理的【51单片机快速入门指南】4.4:I2C 读取HMC5883L / QMC5883L 磁力计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mikrotikROS系统的几种安装方法
- 下一篇: java 读取网络js文件_JavaSc