|
程序:
#include <reg52.h> //調(diào)用單片機(jī)頭文件
#define uchar unsigned char //無(wú)符號(hào)字符型 宏定義 變量范圍0~255
#define uint unsigned int //無(wú)符號(hào)整型 宏定義 變量范圍0~65535
#include <math.h> //Keil library
#include <stdio.h> //Keil library
#include <INTRINS.H>
sbit rs=P1^0; //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器 L:指令寄存器
sbit rw=P1^1; //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器 L:指令寄存器
sbit e =P1^2; //片選信號(hào) 下降沿觸發(fā)
sbit SCL=P2^1; //IIC時(shí)鐘引腳定義
sbit SDA=P2^0; //IIC數(shù)據(jù)引腳定義
#define SlaveAddress 0x3C //定義器件在IIC總線中的從地址
uchar BUF[8]; //接收數(shù)據(jù)緩存區(qū)
uchar ge,shi,bai,qian,wan; //顯示變量
int dis_data; //變量
/******************1ms 延時(shí)函數(shù)*******************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<120;j++);
}
/***********************延時(shí)函數(shù)************************/
void delay_uint(uint q)
{
while(q--);
}
/**************************************
延時(shí)5微秒(STC90C52RC@12M)
不同的工作環(huán)境,需要調(diào)整此函數(shù),注意時(shí)鐘過(guò)快時(shí)需要修改
當(dāng)改用1T的MCU時(shí),請(qǐng)調(diào)整此延時(shí)函數(shù)
**************************************/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
/***********************lcd1602寫(xiě)命令函數(shù)************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(3);
e=1;
delay_uint(25);
e=0;
}
/***********************lcd1602寫(xiě)數(shù)據(jù)函數(shù)************************/
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上顯示這字符函數(shù)************************/
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初始化設(shè)置************************/
void init_1602() //lcd1602初始化設(shè)置
{
write_com(0x38); //
write_com(0x0c);
write_com(0x06);
write_string(1,0," zhi nan zhen ");
write_string(2,0," ");
write_zifu(2,11,0xdf); //顯示度
}
/***********************lcd1602上顯示兩位十進(jìn)制數(shù)************************/
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);
}
/**************************************
起始信號(hào)
**************************************/
void HMC5883_Start()
{
SDA = 1; //拉高數(shù)據(jù)線
Delay5us(); //延時(shí)
SDA = 0; //產(chǎn)生下降沿
Delay5us(); //延時(shí)
SCL = 0; //拉低時(shí)鐘線
}
/**************************************
停止信號(hào)
**************************************/
void HMC5883_Stop()
{
SDA = 0; //拉低數(shù)據(jù)線
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SDA = 1; //產(chǎn)生上升沿
Delay5us(); //延時(shí)
}
/**************************************
發(fā)送應(yīng)答信號(hào)
入口參數(shù):ack (0:ACK 1:NAK)
**************************************/
void HMC5883_SendACK(bit ack)
{
SDA = ack; //寫(xiě)應(yīng)答信號(hào)
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SCL = 0; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
}
/**************************************
接收應(yīng)答信號(hào)
**************************************/
bit HMC5883_RecvACK()
{
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
CY = SDA; //讀應(yīng)答信號(hào)
SCL = 0; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
return CY;
}
/**************************************
向IIC總線發(fā)送一個(gè)字節(jié)數(shù)據(jù)
**************************************/
void HMC5883_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位計(jì)數(shù)器
{
dat <<= 1; //移出數(shù)據(jù)的最高位
CY = SDA; //送數(shù)據(jù)口
SCL = 0; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SCL = 1; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
}
HMC5883_RecvACK();
}
/**************************************
從IIC總線接收一個(gè)字節(jié)數(shù)據(jù)
**************************************/
uchar HMC5883_RecvByte()
{
uchar i;
uchar dat = 0;
SDA = 1; //使能內(nèi)部上拉,準(zhǔn)備讀取數(shù)據(jù),
for (i=0; i<8; i++) //8位計(jì)數(shù)器
{
dat <<= 1;
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
dat |= SDA; //讀數(shù)據(jù)
SCL = 0; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
}
return dat;
}
//***************************************************
void Single_Write_HMC5883(uchar REG_Address,uchar REG_data)
{
HMC5883_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫(xiě)信號(hào)
HMC5883_SendByte(REG_Address); //內(nèi)部寄存器地址,請(qǐng)參考中文pdf
HMC5883_SendByte(REG_data); //內(nèi)部寄存器數(shù)據(jù),請(qǐng)參考中文pdf
}
//******************************************************
//
//連續(xù)讀出HMC5883內(nèi)部角度數(shù)據(jù),地址范圍0x3~0x5
//
//******************************************************
void Multiple_read_HMC5883(void)
{ uchar i;
HMC5883_Start(); //起始信號(hào)
HMC5883_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫(xiě)信號(hào)
HMC5883_SendByte(0x17); //起始信號(hào)
for (i=0; i<6; i++) //連續(xù)讀取6個(gè)地址數(shù)據(jù),存儲(chǔ)中BUF
{
BUF = HMC5883_RecvByte(); //BUF[0]存儲(chǔ)數(shù)據(jù)
if (i == 5)
{
HMC5883_SendACK(1); //最后一個(gè)數(shù)據(jù)需要回NOACK
}
else
{
HMC5883_SendACK(0); //回應(yīng)ACK
}
}
delay_1ms(5);
}
//初始化HMC5883,根據(jù)需要請(qǐng)參考pdf進(jìn)行修改****
void Init_HMC5883()
{
Single_Write_HMC5883(0x02,0x00); //
}
/*****************主函數(shù)********************/
void main()
{
int x,y,z,jiadu;
double angle;
P0 = P1 = P2 = P3 = 0xff; //單片機(jī)IO口初始化為1
Init_HMC5883();
init_1602(); //lcd1602初始化
while(1)
{
Multiple_read_HMC5883(); //連續(xù)讀出數(shù)據(jù),存儲(chǔ)在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(255);
}
}
就是最后定義東南西北角度的數(shù)值,不知道怎么來(lái)的,求大神幫幫忙,馬上答辯了,難過(guò) |
|