//========基于A Tmega8的HMC5883L测试程序============= //** 模块:3-轴数字罗盘
//** 用途:测磁场强度
//** 协议:IIC 详细读写协议,请参考相关资料
#include
#include
#include
#include
typedef unsigned char uchar;
typedef unsigned int uint;
/*LCD引脚定义*/
#define CS_set PORTD |=BIT(6)
#define CS_clr PORTD &=~BIT(6)
#define SID_set PORTD |=BIT(7)
#define SID_clr PORTD &=~BIT(7)
#define CLK_set PORTB |=BIT(0)
#define CLK_clr PORTB &=~BIT(0)
/*IIC端口定义*/
#define SCL_set PORTC |=(1<<5)
#define SCL_clr PORTC &=~(1<<5)
#define SDA_set PORTC |=(1<<4)
#define SDA_clr PORTC &=~(1<<4)
#define SDA_in DDRC &=~(1<<4)
#define SDA_out DDRC |=(1<<4)
#define SlaveAddress 0x3c //定义器件在IIC总线中的从地址uchar Rec_Data[6];
/*延时函数*/
void Delay(uint t)
{
while(t--)
{}
}
/*LCD12232端口初始化*/
void PORT_Init(void)
{ //LCD端口设置为输出,且为高电平DDRD |=(1<<6)|(1<<7);
DDRB |=(1<<0);
PORTD |=(1<<6)|(1<<7);
PORTB |=(1<<0);
DDRC |=(1<<5);//SCL设置为输出
}
/*LCD12232写数据*/
void Send_DATA(uchar Data,uchar O_Z) {
uchar i,Order;
CS_clr;
switch(O_Z)
{
case 0 : Order=0xf8;break;//写指令
case 1 : Order=0xfa;break;//写数据
default : break;
}
CLK_clr;
CS_set;
for(i=0;i<8;i++)
{
if(Order&0x80)
SID_set;
else
SID_clr;
CLK_clr;
CLK_set;
Order<<=1;
}
Order=Data;
Order &=0xf0;
for(i=0;i<8;i++)
{
if(Order&0x80)
SID_set;
else
SID_clr;
CLK_clr;
CLK_set;
Order<<=1;
}
Order=Data;
Order<<=4;
for(i=0;i<8;i++)
{
if(Order&0x80)
SID_set;
else
SID_clr;
CLK_clr;
CLK_set;
Order<<=1;
}
CS_clr;
Delay(20);
}
/*显示一字符串*/
void Dis_str(uchar Addr,uchar *str)
{
Send_DATA(Addr,0);
Delay(30);
while(*str!='\0')
{
Send_DATA(*str,1);
str++;
Delay(20);
}
}
/*LCD12232初始化*/
void Init_LCD(void)
{
Delay(20000);
Send_DATA(0x06,0);
Delay(200);
Send_DATA(0x02,0);
Delay(200);
Send_DATA(0x0c,0);
Delay(200);
Send_DATA(0x80,0);
Delay(200);
Send_DATA(0x30,0);
Delay(200);
Send_DATA(0x01,0);
Delay(5000);
}
/*******************************************
** HMC5883L程序部分
*******************************************/ /*起始信号*/
void IIC_Start(void)
{
SDA_out;
SDA_set;
SCL_set;
Delay(35);
SDA_clr;
Delay(35);
SCL_clr;
}
/*停止信号*/
void IIC_Stop(void)
{
SDA_out;
SDA_clr;
SCL_set;
Delay(35);
SDA_set;
Delay(35);
}
/*接收应答信号*/
uchar IIC_RecAck(void)
{
uchar A;
SDA_in;
SCL_set;
Delay(35);
if(PINC & (1<<4))
A=1;
else
A=0;
SCL_clr;
Delay(35);
return A ? 1:0;
}
/*向IIC总线发送一个字节数据*/
void HMC5883_Send_Byte(uchar Dat)
{
uchar i;
SDA_out;
for(i=0;i<8;i++)
{
if(Dat & 0x80)
SDA_set;
else
SDA_clr;
SCL_set;
Delay(35);
SCL_clr;
Delay(35);
Dat<<=1;
}
IIC_RecAck();
}
/*从IIC总线接收一个字节数据*/
uchar HMC5883_Rec_Byte(void)
{
uchar i,Dat=0;
SDA_in;
SDA_set;
for(i=0;i<8;i++)
{
Dat<<=1;
SCL_set;
Delay(35);
if(PINC & (1<<4))
Dat |=0x01;
SCL_clr;
Delay(35);
}
return Dat;
}
/*单字节写HMC5833*/
void Single_Write_HMC5883(uchar Address,uchar Dat) {
IIC_Start();
HMC5883_Send_Byte(SlaveAddress);
HMC5883_Send_Byte(Address);
HMC5883_Send_Byte(Dat);
IIC_Stop();
}
/*单字节读HMC5833*/
/*uchar Single_Read_HMC5883(uchar Addr)
{
uchar Value;
IIC_Start();
HMC5883_Send_Byte(SlaveAddress);
HMC5883_Send_Byte(Addr);
IIC_Start();
HMC5883_Send_Byte(SlaveAddress+1);
V alue=HMC5883_Rec_Byte();
IIC_SendAck(1);
IIC_Stop();
return Value;
}*/
//初始化HMC5883,根据需要请参考pdf进行修改****
void HMC5883_Init(void)
{
Single_Write_HMC5883(0x02,0x00);
}
/*************************************************
**主函数
*************************************************/
void main(void)
{
uchar N;
int X,Y,Z;
double Angle;
uint Acr;
Delay(60000);
PORT_Init();
Init_LCD();
//Dis_str(0x80,"HMC5883L");
HMC5883_Init();//HMC5883初始化
do
{
Multiple_Read_HMC5883();//连续读出数据,存储在Rec_Data[]中
X=Rec_Data[0]<<8 | Rec_Data[1];//Combine MSB and LSB of X Data output register
Z=Rec_Data[2]<<8 | Rec_Data[3];//Combine MSB and LSB of Z Data output register
Y=Rec_Data[4]<<8 | Rec_Data[5];//Combine MSB and LSB of Y Data output register
Angle= atan2((double)Y,(double)X)*(180/3.14159265)+180;//单位:角度(0~360)
Angle*=10;
Acr=(uint)Angle;
Send_DATA(0x82,0);
Send_DATA(0x20,1);
Send_DATA(Acr%10000/1000+0x30,1);
Send_DATA(Acr%1000/100+0x30,1);
Send_DATA(Acr%100/10+0x30,1);
//Send_DATA('.',1);
//Send_DATA(Acr%10+0x30,1);
Send_DATA(0xa1,1);
Send_DATA(0xe3,1);
if((Acr>=0 && Acr<=300) || (Acr>=3300))
Dis_str(0x92,"【东】");
if(Acr>=600 && Acr<=1200)
Dis_str(0x92,"【南】");
if(Acr>=1500 && Acr<=2100)
Dis_str(0x92,"【西】");
if(Acr>=2400 && Acr<=3000)
Dis_str(0x92,"【北】");
for(N=12;N>0;N--)
Delay(50000);
}
while(1);
}