#include  <REG51.H>    
#include  <math.h>    //Keil library  
#include  <stdio.h>   //Keil library    
#include  <INTRINS.H>
#define   uchar unsigned char
#define   uint unsigned int    
//使用的端口,请按照以下接线
sbit    SCL=P3^2;      //IIC时钟引脚定义
sbit    SDA=P3^7;      //IIC数据引脚定义

sbit   P33=P3^3;
sbit   P34=P3^4;
sbit   P35=P3^5;

#define    SlaveAddress   0x3C      //定义器件在IIC总线中的从地址

unsigned char BUF[8];                         //接收数据缓存区          
unsigned char w[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void Init_HMC5883(void);            //初始化5883

void  Single_Write_HMC5883(uchar REG_Address,uchar REG_data);   //单个写入数据
void  Read_HMC5883(void);                                  //连续的读取内部寄存器数据
//以下是模拟iic使用函数-------------
void Delay5us();
void Delay5ms();
void HMC5883_Start();
void HMC5883_Stop();
void HMC5883_SendACK(bit ack);
bit  HMC5883_RecvACK();
void HMC5883_SendByte(unsigned char dat);
unsigned char HMC5883_RecvByte();
void HMC5883_ReadPage();
void HMC5883_WritePage();

/**************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
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_();_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_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();

}

/**************************************
延时5毫秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5ms()
{
    unsigned int n ;
    for(n=900;n--;n>0)
      Delay5us();
}

/**************************************
起始信号
**************************************/
void HMC5883_Start()
{
    SDA = 1;                    //拉高数据线
    SCL = 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(unsigned char dat)
{
    unsigned char i;

for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;              //移出数据的最高位
        SDA = CY;               //送数据口
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    HMC5883_RecvACK();
}

/**************************************
从IIC总线接收一个字节数据
**************************************/
unsigned char HMC5883_RecvByte()
{
    unsigned char i;
    unsigned char 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();                   //发送停止信号
}

//******************************************************
//
//连续读出HMC5883内部角度数据,地址范围0x3~0x5
//
//******************************************************
void Read_HMC5883(void)
{   uchar i;
    HMC5883_Start();                          //起始信号
    HMC5883_SendByte(SlaveAddress);           //发送设备地址+写信号
    HMC5883_SendByte(0x03);                   //发送存储单元地址,从0x32开始    
    HMC5883_Start();                          //起始信号
    HMC5883_SendByte(SlaveAddress+1);         //发送设备地址+读信号
     for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = HMC5883_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 5)
        {
           HMC5883_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          HMC5883_SendACK(0);                //回应ACK
       }
   }
    HMC5883_Stop();                          //停止信号
    Delay5ms();
}

//初始化HMC5883,根据需要请参考pdf进行修改****
void Init_HMC5883()
{
     Single_Write_HMC5883(0x02,0x00);  //
}

void show(int angle_xy)
{
  unsigned int a;
  unsigned char b;
 
  a=angle_xy/15;    //360度等分为24份,每份15度 一个强制转换就会多出98个字节
  b=a/8;
  P1=0xff;            //P1口全部关闭
  P3=0xc7;        //NPN低电平关闭    11000111
  switch (b)      //选择哪组灯亮   NPN高电平通
  {
    case 0:
          P33=1; //P3.3高电平
          P34=0;
          P35=0;
          break;
    case 1:
          P33=0; //P3.4高电平
          P34=1;
          P35=0;
          break;
    case 2:
          P33=0; //P3.5高电平
          P34=0;
          P35=1;
          break;
    default:
         break;
  }
  a%=8;
  P1=w[a];
}

//*********************************************************
//主程序********
//*********************************************************
void main()               //原来
{  
   int x,y,z,angle_xy,x_max=0,x_min=0,y_max=0,y_min=0,x_offset,y_offset;
   float p;
     
   Delay5ms();             
   Init_HMC5883();
  while(1)            //循环
  {
    Read_HMC5883();      //连续读出数据,存储在BUF中
 
    x=BUF[0] << 8 | BUF[1]; //Combine MSB and LSB of X Data output register      xyz有符号!!!!
    z=BUF[2] << 8 | BUF[3]; //Combine MSB and LSB of Z Data output register
    y=BUF[4] << 8 | BUF[5]; //Combine MSB and LSB of Y Data output register

if(z<0)           //假如指南针反放,则取相反数
      z=-z;
    if(z>380)       //保证在做xy方向旋转时,垂直方向不能摆动过大,不然就会影响x、y轴的最大小值
    {
      if(x>x_max)
        x_max=x;
      if(x<x_min)                                                     
        x_min=x;
      if(y>y_max)
        y_max=y;
        if(y<y_min)
        y_min=y;
      x_offset=(x_max + x_min) / 2;
      y_offset=(y_max + y_min) / 2;
      p=(float)(x_max - x_min) / (float)(y_max - y_min);
      x=x-x_offset;
      y=p*(y-y_offset);        
    }     
    angle_xy= atan2((float)y,(float)x) * (180.0 /3.14159265) + 180; // angle_xy为0~359

show(angle_xy);
    Delay5ms();                 
  }
}

完整资料打包:

STC51单片机53-电子指南针HMC5883l-单片机文档类资源-CSDN下载

STC 51单片机53——电子指南针HMC5883l相关推荐

  1. STC 51单片机程序下载失败总结

    STC为宏晶公司推出的国产51单片机,其优点在于价格低廉,功能强大,使用方便,尤其是其串口ISP下载程序的方式方便了大量用户,免去了购买昂贵的编程器,非常适合单片机入门学习使用. 但是初学者常会遇到程 ...

  2. STC 51单片机54——气压水压计HX710B 串口显示均值滤波+滑窗滤波

    //气压模块为红色模块,传感器型号未知,其信号放大器型号为HX710B // STC15W408AS 11.0592MHz 波特率9600,串口输出大气压强值 // STC15W408AS没有定时器1 ...

  3. STC 51单片机 多位数码管动态显示方法

    51单片机多位数码管动态显示方法 1.数码管显示原理 2.多位数码管动态显示 3.示例程序 3.结语 1.数码管显示原理 相比学习单片机的同学一定对显示器,屏幕如OLED,LCD并不陌生,而在这些显示 ...

  4. STC 51单片机56——摇摇棒

    主要代码: //增减图像时,需要修改    switch_show()和 H对应参数 //所用单片机:STC15W408S 内部Rc 11.0592MHz #include <STC15.H&g ...

  5. STC 51单片机42——汇编 定时器 舵机

    ORG 0000H        HighH EQU 30H; 定义变量,高电平高八位         TimerH EQU 31H; 定义变量,高电平高八位定时值        TimerL EQU ...

  6. STC 51单片机43——看门狗

    看门狗测试,通过修改delay函数的延时长度,可以看到看门狗是否复位系统. #include <reg52.h>             sfr  WDT_CONTR =0xE1;     ...

  7. STC 51单片机58——旋转LED

    STC11F  LED部分: #include "STC11.h" #define u8 unsigned char #define u16 unsigned int //全亮 / ...

  8. STC 51单片机46——看门狗测试

    #include <reg52.h>             sfr  WDT_CONTR =0xE1;        //声明WDT_CONTR void delay(void){  / ...

  9. 单片机如何使用?51单片机C语言编程实例有哪些?

    大家好,我是无际单片机编程的徐明,今天和大家一起探讨一下"单片机如何使用?" 单片机如何使用,我们要知道单片机在哪里使用? 单片机是很多电子产品的核心器件,它具有一定的逻辑判断和事 ...

最新文章

  1. ASP.NET Razor – C# 逻辑条件简介
  2. LeetCode之 insertion-sort-list insertion-sort-list
  3. python 把数据 json格式输出
  4. QT设计UI:QT模式对话框打开文件
  5. 用Java中的抽象类扩展抽象类
  6. 站在K2角度审视流程--任务的独占与释放
  7. 揭开git的神秘面纱
  8. Mysql支持中文全文检索的插件mysqlcft-应用中的问题
  9. 将本地SQL Server数据库迁移到Azure SQL数据库
  10. Windows Azure Storage (1) Windows Azure Storage Service存储服务
  11. 拼多多的硬核逆生长!
  12. linux网络配置putty,linux基础:2、网络配置和用使用putty连接
  13. Java实现经典坦克大战及源代码下载
  14. MATLAB中的resample函数根本理解,我专栏中有Guitar.MAT资源
  15. ORACLE 错误 904
  16. 18款口碑爆棚手机浏览器,被一网打尽了
  17. live555源码分析(七)播放过程
  18. 转:高级软件工程师成长秘诀(文末有笔者自己的小评论)
  19. 7-4 大炮打蚊子 (20分)__C++
  20. 统一认证中心-auth2.0

热门文章

  1. Unity下如何实现RTMP或RTSP流播放和录制
  2. [架构之路-61]:目标系统 - 平台软件 - 基础中间件 - 远程过程(函数)调用RPC原理与其网络架构
  3. 华为云空间联系人是不是机主_电脑上整理华为云空间联系人数据
  4. 实验四 javaAPI(预习报告)
  5. Select函数的作用和使用
  6. 人力资源分析思维以及有必要学习数据分析吗?
  7. 云计算之路-阿里云上:一夜之间竞价服务器全没了
  8. 通过XMind Update制作思维导图
  9. 求逆序对---学习笔记
  10. Excel 同一单元格显示不同颜色