【模块学习】关于磁力计HMC5883L型号探索
来源:互联网 发布:三个字网络流行语 编辑:程序博客网 时间:2024/06/05 07:14
关于磁力计HMC5883L型号探索
一.序言
在众多磁力计中,HMC5883L因为其廉价实用而受到大多数嵌入式开发小白的追捧。然而某宝上不仅仅有HMC5883L这一款,还有QMC5883和HMC5983,常有商家搞不清芯片就出售,导致提供的数据手册不对应。同时,不同单片机对IIC的操作也略有差异,对小白而言也是件头疼的事情。
HMC5883L与QMC5883L区别对比
可以看到,QMC5883L的各寄存器地址与HMC5883L区别还是不小。这样,移植时候程序整体结构不用大改,把寄存器改掉即可。
(1) 修改I2C address
0x3C -> 0x1A
0x3D -> 0x1B
(2) X/Y/Z Register
起始:0x03 -> 0x00
顺序:X-Z-Y -> X-Y-Z
(3) Mode Register
0x02 -> 0x09
0x00 -> 0x01
二.HMC5983
HMC5983是HMC5883L的“加强版”,寄存器与5883基本一致,但同时支持I2C和SPI两种通信模式,更加快捷。因此,使用方法与5883几乎没有差别。这里,本人将官方提供的测试程序修改为STC15系列单片机,主要移植I2C通信中时序函数。
本人增加了一个定任意方向为0度的功能,主要为了解决各类机器人竞赛中场地不一定何种角度朝向的问题。不过由于时间仓促没有来的及写滤波。思路就是将坐标系进行转换。贴出程序,仅供参考。
1.电路图
2.所需元件
STC15W408AS x1
HMC5983 x1
1k电阻 x1
独立按键 x1
排针 若干
洞洞板 x1
3.程序结构
4.源码
(1)user_config.h
/*-----------------------------------------用户配置文件-------------------------------------------*/#ifndef _CONFIG_H_#define _CONFIG_H_/* 宏定义 */#define uchar unsigned char#define uint unsigned inttypedef unsigned char BYTE;typedef unsigned short WORD;/* 包含头文件 */#include <STC15F2K60S2.H>#include <math.h> //Keil library #include <stdio.h> //Keil library#include <INTRINS.H>//USER Library#include "HMC5983_Driver.h"#include "HMC5983_Software.h"#include "uart.h"#include "delay.h"#include "interrupt.h"//#include "LQ12864.h"//使用的端口,请按照以下接线sbitSCL=P3^2; //IIC时钟引脚定义sbitSDA=P3^3; //IIC数据引脚定义sbit KEY=P3^6; //按键//sfr INT_CLKO = 0x8f;//外部中断与时钟输出控制寄存器//全局变量引入extern BYTE BUF[8];extern uchar ge,shi,bai,qian,wan; //显示变量extern int dis_data; //变量extern double angle_ch;#endif
(2)HMC5983_Driver.h
/*------------------------------------HMC5983驱动文件-------------------------------------*/#ifndef _HMC5983_DRIVER_H_#define _HMC5983_DRIVER_H_#defineSlaveAddress 0x3C //定义器件5883在IIC总线中的从地址//************//函数//************void Init_HMC5883(void); //初始化5883void Single_Write_HMC5883(uchar REG_Address,uchar REG_data); //单个写入数据//uchar Single_Read_HMC5883(uchar REG_Address); //单个读取内部寄存器数据void Multiple_Read_HMC5883(void); //连续的读取内部寄存器数据//以下是模拟iic使用函数-------------void HMC5883_Start(void);void HMC5883_Stop(void);void HMC5883_SendACK(bit ack);bit HMC5883_RecvACK(void);void HMC5883_SendByte(BYTE dat);BYTE HMC5883_RecvByte(void);void HMC5883_ReadPage(void);void HMC5883_WritePage(void);#endif
(3)interrupt.h
/*--------------------------中断服务头文件---------------------------*/#ifndef _IT_H_#define _IT_H_#define Init_INT2() INT_CLKO |= 0x10#endif
(4)uart.c
/*-----------------------------------串口配置STC15F408AS内置晶振波特率 9600 bps------------------------------------*/#include "user_config.h"BYTE BUF[8]; //接收数据缓存区 //*********************************************//串口初始化//9600 bps @ 11.059 MHz void init_uart(void){SCON = 0x50;AUXR |= 0x04;T2L = 0xa0;T2H = 0xfc;AUXR |= 0x10;TI = 1;EA = 1;}//*********串口数据发送******************void SeriPushSend(uchar send_data){ SBUF = send_data; while(!TI);TI=0; }
(5)interrupt.c
/*-----------------------------中断服务-----------------------------*/#include "user_config.h"double angle_ch = 0;void KEY_DOWN(void) interrupt 10{Delay5ms();if(KEY == 0){while(!KEY);angle_ch = Angle_Update();}}
(6)HMC5983_Driver.c
//***************************************// HMC5883 51串口测试程序// 使用单片机STC89C51 // 晶振:11.0592M// 显示:PC串口// 编译环境 Keil uVision2// 参考宏晶网站24c04通信程序// 时间:2011年3月1日//****************************************#include "user_config.h"#include "HMC5983_Driver.h"int dis_data; //变量//-----------------------------------/**************************************起始信号**************************************/void HMC5883_Start(void){ SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 0; //产生下降沿 Delay5us(); //延时 SCL = 0; //拉低时钟线}/**************************************停止信号**************************************/void HMC5883_Stop(void){ SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时}/**************************************发送应答信号入口参数:ack (0:ACK 1:NAK)**************************************/void HMC5883_SendACK(bit ack){ SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时}/**************************************接收应答信号**************************************/bit HMC5883_RecvACK(void){ SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY;}/**************************************向IIC总线发送一个字节数据**************************************/void HMC5883_SendByte(BYTE dat){ BYTE i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } HMC5883_RecvACK();}/**************************************从IIC总线接收一个字节数据**************************************/BYTE HMC5883_RecvByte(void){ BYTE i; BYTE dat = 0; SDA = 1; //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat;}//***************************************************void Single_Write_HMC5883(uchar REG_Address,uchar REG_data){ HMC5883_Start(); //起始信号 HMC5883_SendByte(SlaveAddress); //发送设备地址+写信号 HMC5883_SendByte(REG_Address); //内部寄存器地址,请参考中文pdf HMC5883_SendByte(REG_data); //内部寄存器数据,请参考中文pdf HMC5883_Stop(); //发送停止信号} /*//********单字节读取内部寄存器*************************uchar Single_Read_HMC5883(uchar REG_Address){uchar REG_data; HMC5883_Start(); //起始信号 HMC5883_SendByte(SlaveAddress); //发送设备地址+写信号 HMC5883_SendByte(REG_Address); //发送存储单元地址,从0开始 HMC5883_Start(); //起始信号 HMC5883_SendByte(SlaveAddress+1); //发送设备地址+读信号 REG_data=HMC5883_RecvByte(); //读出寄存器数据HMC5883_SendACK(1); HMC5883_Stop(); //停止信号 return REG_data; }*///******************************************************////连续读出HMC5883内部角度数据,地址范围0x3~0x5////******************************************************void Multiple_read_HMC5883(void){ uchar i; HMC5883_Start(); //起始信号 HMC5883_SendByte(SlaveAddress); //发送设备地址+写信号 HMC5883_SendByte(0x03); //发送存储单元地址,从0x3开始 HMC5883_Start(); //起始信号 HMC5883_SendByte(SlaveAddress+1); //发送设备地址+读信号 for (i=0; i<7; i++) //连续读取6个地址数据,存储中BUF { BUF[i] = HMC5883_RecvByte(); //BUF[0]存储0x32地址中的数据 if (i == 6) { HMC5883_SendACK(1); //最后一个数据需要回NOACK } else { HMC5883_SendACK(0); //回应ACK } } HMC5883_Stop(); //停止信号 Delay5ms();}//初始化HMC5883,根据需要请参考pdf进行修改****void Init_HMC5883(void){ Single_Write_HMC5883(0x02,0x00); // Single_Write_HMC5883(0x01,0xE0); //}
(7)HMC5983_Software.c
/*---------------------------------HMC5983 角度变换将任意角度变为0度-----------------------------------*/#include "user_config.h"uchar ge,shi,bai,qian,wan; //显示变量double Angle_Update(void){int x,y,z,t;Multiple_Read_HMC5883(); //连续读出数据,存储在BUF中x = BUF[0] << 8 | BUF[1]; z = BUF[2] << 8 | BUF[3]; y = BUF[4] << 8 | BUF[5]; t = atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degreeswhile(abs(t-45) <= 0.001){Multiple_Read_HMC5883(); //连续读出数据,存储在BUF中x = BUF[0] << 8 | BUF[1]; z = BUF[2] << 8 | BUF[3]; y = BUF[4] << 8 | BUF[5]; t = atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degrees}return t;}void conversion(uint temp_data) { wan=temp_data/10000+0x30 ; temp_data=temp_data%10000; //取余运算qian=temp_data/1000+0x30 ; temp_data=temp_data%1000; //取余运算 bai=temp_data/100+0x30 ; temp_data=temp_data%100; //取余运算 shi=temp_data/10+0x30 ; temp_data=temp_data%10; //取余运算 ge=temp_data+0x30; }double Change_Target(void){double angle_now = Angle_Update();if(angle_now >= angle_ch) return angle_now-angle_ch;else return 360-angle_ch+angle_now;}
(8)main.c
/*----------------------------------------------------------基于HMC5983智能电子罗盘2017/10/24Listen C@ 型号:STC15F408AS@ 晶振:内置33.1776MHz@ 通信:IIC@ 显示:0.96 OLED@ 串口:9600 bps------------------------------------------------------------*/#include <STC15F2K60S2.H>#include "user_config.h"//*********************************************************// 主程序//*********************************************************void main(void){ // bit sign_bit; unsigned int i; double angle; delay(100); Init_INT2(); init_uart(); Init_HMC5883(); while(1) //循环 { angle = Change_Target(); conversion(angle); //计算数据和显示Delay5ms(); SeriPushSend(0x0d);SeriPushSend(0x0a);SeriPushSend(bai);SeriPushSend(shi);SeriPushSend(ge); }}
三.QMC5883L在Arduino上使用
在arduino中,I2C address用的是7位地址而不是8位,所以需要对应将address改掉。
比如QMC5883为0x1a,则二进制为0001_1010。而换算为7位,右移一位二进制为0000_1101。
则十六进制为0x0d。
源码如下:
#include <Wire.h> #define address 0x0d void setup() { //put your setup code here, to run once: Serial.begin(9600); delay(500); Wire.begin(); Wire.beginTransmission(address); Wire.write(0x09); Wire.write(0x01); Wire.endTransmission(); } void loop() { //put your main code here, to run repeatedly: intx,y,z; Wire.beginTransmission(address); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(address,6); if(Wire.available() >= 6){ x= Wire.read() << 8; x |= Wire.read(); y = Wire.read() << 8; y |= Wire.read(); z= Wire.read() << 8; z |= Wire.read(); } Serial.print("x: "); Serial.print(x); Serial.print(" y: "); Serial.print(y); Serial.print(" z: "); Serial.println(z); delay(250); }
网盘链接:http://pan.baidu.com/s/1gfEje8r 密码:dbvr
- 【模块学习】关于磁力计HMC5883L型号探索
- HMC5883L磁力计常见问题解答
- HMC5883L 磁力计校准
- HMC5883L 磁力计校准
- HMC5883L 磁力计校准
- HMC5883L
- HMC5883L地磁传感器学习总结
- 磁力计
- 关于HMC5883L驱动书写及调试的总结
- 关于网站搭建的学习探索(
- 关于磁力计和加速度计的融合以及坐标系的对准
- Python学习笔记(七)——自我探索模块
- yate学习--关于yrtpchan模块
- 关于Express模块的学习
- 无人机——磁力计/电子罗盘 学习及校准
- HMC5883L校准
- GY-273 HMC5883L电子指南针罗盘模块 三轴磁场传感器 avr 获取 三维位置
- 分行模块,自动识别英文和型号数
- 泛型dao
- POJ3045 Cow Acrobats 贪心
- chrome控制台的使用
- 深度学习(Deep Learning)
- SpringBoot特性之Actuator
- 【模块学习】关于磁力计HMC5883L型号探索
- 购物车修改排序删除
- Python利用os.walk遍历文件夹
- 欢迎使用CSDN-markdown编辑器
- hdoj 1789
- RecyclerView的瀑布流简单应用
- 英语突击队总结
- Mysql高可用--双主热备+keepalived
- gmock简单实例