//******************************
//QMC5883L IIC测试程序   
//使用单片机STC15W408ASprintf输出格式用串口助手显示
//晶振频率:11.0592M
//QMC5883是一款国产三轴磁阻传感器
//其内部寄存器设置与霍尼韦尔公司生产的HMC5883
//不尽相同,不能直接套用HMC5883的测试程序,否
//则无法获得角度数据。
//下面给出的测试程序可以通过串口助手
//在PC机上直接读出QMC5883输出的角度数据。
//宜昌三峡电院电子科技创新协会
//******************************
#include "STC15F2K60S2.H"
#include "intrins.h"
#include "math.h"
#include "stdio.h"
#define    Slave_Address  0x1a  //HMC5883为0x3c
typedef unsigned int u16;
typedef unsigned char u8;
u8 BUF[8]=0;
sbit    SCL=P1^2;      //IIC时钟线
sbit    SDA=P1^3;      //IIC数据线
void Delay_5us();
void Delay(u16 t);
void InitUart();
void QMC5883_Start();
void QMC5883_Stop();
void QMC5883_SendACK(bit ack);
bit  QMC5883_RecvACK();//
void QMC5883_SendByte(u8 dat); //
u8 QMC5883_RecvByte();// 
void Single_Write_QMC5883(u8 REG_Address,u8 REG_data);
//u8 Single_Read_QMC5883(u8 REG_Address);
void Multiple_Read_QMC5883(void);
void Init_QMC5883();
//STC15W408AS无定时器1,只能用定时器2作串口波特率发生器
void InitUart()           
{
    SCON = 0x50;       
    AUXR |= 0x01;       
    AUXR &= 0xFB;       
    T2L = 0xE8;       
    T2H = 0xFF;       
    AUXR |= 0x10;       
    ES = 1; 
    EA = 1;
    TI=1;
}
void Delay(u16 t)   
{                       
    u16 i,j;               
    for(i=t;i>0;i--)
    for(j=121;j>0;j--);                       
}
void Delay_5us()
{
    u8 x;
    x = 20;
    while (--x);
}
/**************************************
起始信号
**************************************/
void QMC5883_Start()
{
    SDA = 1;                    //拉高数据线
    SCL = 1;                    //拉高时钟线
    Delay_5us();                //延时
    SDA = 0;                    //产生下降沿
    Delay_5us();                //延时
    SCL = 0;                    //拉低时钟线
}
/**************************************
停止信号
**************************************/
void QMC5883_Stop()
{
    SDA = 0;                    //拉低数据线
    SCL = 1;                    //拉高时钟线
    Delay_5us();                //延时
    SDA = 1;                    //产生上升沿
    Delay_5us();                //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void QMC5883_SendACK(bit ack)
{
    SDA = ack;                  //写应答信号
    SCL = 1;                    //拉高时钟线
    Delay_5us();                //延时
    SCL = 0;                    //拉低时钟线
    Delay_5us();                //延时
}
/**************************************
接收应答信号
**************************************/
bit QMC5883_RecvACK()
{
    SCL = 1;                    //拉高时钟线
    Delay_5us();                //延时
    CY = SDA;                  //进位标志 读应答信号
    SCL = 0;                    //拉低时钟线
    Delay_5us();                //延时
    return CY;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void QMC5883_SendByte(u8 dat)
{
    u8 i;
    for (i=0; i<8; i++)        //8位计数器
    {
        dat <<= 1;              //移出数据的最高位
        SDA = CY;              //送数据口
        SCL = 1;                //拉高时钟线
        Delay_5us();            //延时
        SCL = 0;                //拉低时钟线
        Delay_5us();            //延时
    }
    QMC5883_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
u8 QMC5883_RecvByte()
{
    u8 i;
    u8 dat = 0;
    SDA = 1;                    //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)        //8位计数器
    {
        dat <<= 1;
        SCL = 1;                //拉高时钟线
        Delay_5us();            //延时
        dat |= SDA;            //读数据             
        SCL = 0;                //拉低时钟线
        Delay_5us();            //延时
    }
    return dat;
}
//************************写入单字节数据***************************
void Single_Write_QMC5883(u8 REG_Address,u8 REG_data)
{
    QMC5883_Start();                  //起始信号
    QMC5883_SendByte(Slave_Address);  //发送设备地址+写信号
    QMC5883_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf
    QMC5883_SendByte(REG_data);      //内部寄存器数据,请参考中文pdf
    QMC5883_Stop();                  //发送停止信号
}
//************************读取单字节数据*************************
//u8 Single_Read_QMC5883(u8 REG_Address)
//{ 
//    u8 REG_data;
//    QMC5883_Start();                          //起始信号
//    QMC5883_SendByte(Slave_Address);          //发送设备地址+写信号
//    QMC5883_SendByte(REG_Address);            //发送存储单元地址,从0开始   
//    QMC5883_Start();                          //起始信号
//    QMC5883_SendByte(Slave_Address+1);        //发送设备地址+读信号