|
有没有大佬能帮忙看看,我这HMC5883L,做的指南针数值不变是怎末回事啊
[复制链接]
这是程序
#include //调用单片机头文件
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include //Keil library
#include //Keil library
#include
sbit rs=P3^5; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit rw=P3^6; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit e =P3^4; //片选信号 下降沿触发
sbit SCL=P2^7; //IIC时钟引脚定义
sbit SDA=P2^6; //IIC数据引脚定义
#define SlaveAddress 0x3C //定义器件在IIC总线中的从地址
uchar BUF[8]; //接收数据缓存区
uchar ge,shi,bai,qian,wan; //显示变量
int dis_data; //变量
/******************1ms 延时函数*******************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i
for(j=0;j<120;j++);
}
/***********************延时函数************************/
void delay_uint(uint q)
{
while(q--);
}
/**************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5us()
{
unsigned char a;
for(a=1;a>0;a--);
}
/***********************lcd1602写命令函数************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(3);
e=1;
delay_uint(25);
e=0;
}
/***********************lcd1602写数据函数************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(3);
e=1;
delay_uint(25);
e=0;
}
/***********************lcd1602上显示特定的字符************************/
void write_zifu(uchar hang,uchar add,uchar date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(date);
}
/***********************lcd1602上显示这字符函数************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/***********************lcd1602初始化设置************************/
void init_1602() //lcd1602初始化设置
{
write_com(0x38); //
write_com(0x0c);
write_com(0x06);
delay_uint(1000);
write_string(1,0," zhi nan zhen ");
write_string(2,0," ");
write_zifu(2,11,0xdf); //显示度
}
/***********************lcd1602上显示两位十进制数************************/
void write_jiaodu(uchar hang,uchar add,uint date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(0x30+date/1000%10);
write_data(0x30+date/100%10);
write_data(0x30+date/10%10);
write_data('.');
write_data(0x30+date%10);
}
/**************************************
起始信号
**************************************/
void HMC5883_Start()
{
SDA = 1; //拉高数据线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
/**************************************
停止信号
**************************************/
void HMC5883_Stop()
{
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()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void HMC5883_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 0; //拉高时钟线
Delay5us(); //延时
SCL = 1; //拉低时钟线
Delay5us(); //延时
}
HMC5883_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
uchar HMC5883_RecvByte()
{
uchar i;
uchar 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_SendByte(SlaveAddress); //发送设备地址+写信号
HMC5883_SendByte(REG_Address); //内部寄存器地址,请参考中文pdf
HMC5883_SendByte(REG_data); //内部寄存器数据,请参考中文pdf
}
//******************************************************
//
//连续读出HMC5883内部角度数据,地址范围0x3~0x8
//
//******************************************************
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<6; i++) //连续读取6个地址数据,存储中BUF
{
BUF[i] = HMC5883_RecvByte(); //BUF[0]存储数据
if (i == 5)
{
HMC5883_SendACK(0); //最后一个数据需要回NOACK
}
else
{
HMC5883_SendACK(1); //回应ACK
}
}
delay_1ms(5);
}
//初始化HMC5883,根据需要请参考pdf进行修改****
void Init_HMC5883()
{
Single_Write_HMC5883(0x02,0x00); //
}
/*****************主函数********************/
void main()
{
int x,y,z,jiadu;
double angle;
P0 = P1 = P2 = P3 = 0xff; //单片机IO口初始化为1
Init_HMC5883();
init_1602(); //lcd1602初始化
while(1)
{
Multiple_read_HMC5883(); //连续读出数据,存储在BUF中
//---------显示X轴
x=BUF[0] << 8 | BUF[2]; //Combine MSB and LSB of X Data output register
z=BUF[2] << 8 | BUF[4]; //Combine MSB and LSB of Z Data output register
angle= atan2((double)y,(double)x) * (180 / 3.14); // angle in degrees
jiadu = angle;
write_jiaodu(2,6,angle); //显示角度
if((angle >= 3380) || (angle <= 220)) //北 N
write_string(2,0," N ");
if((angle >= 230) && (angle <= 670)) //东 北
write_string(2,0," E N ");
if((angle >= 680) && (angle <= 1120)) //东 E
write_string(2,0," E ");
if((angle >= 1130) && (angle <= 1570)) //东 南
write_string(2,0," E S ");
if((angle >= 1580) && (angle <= 2010)) //南 S
write_string(2,0," S ");
if((angle >= 2020) && (angle <= 2460)) //西 南
write_string(2,0," W S ");
if((angle >= 2470) && (angle <= 2910)) //西 W
write_string(2,0," W ");
if((angle >= 2920) && (angle <= 3360)) //西 北
write_string(2,0," W N ");
delay_1ms(300);
}
}
|
|