STC 51单片机53——电子指南针HMC5883l
#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相关推荐
- STC 51单片机程序下载失败总结
STC为宏晶公司推出的国产51单片机,其优点在于价格低廉,功能强大,使用方便,尤其是其串口ISP下载程序的方式方便了大量用户,免去了购买昂贵的编程器,非常适合单片机入门学习使用. 但是初学者常会遇到程 ...
- STC 51单片机54——气压水压计HX710B 串口显示均值滤波+滑窗滤波
//气压模块为红色模块,传感器型号未知,其信号放大器型号为HX710B // STC15W408AS 11.0592MHz 波特率9600,串口输出大气压强值 // STC15W408AS没有定时器1 ...
- STC 51单片机 多位数码管动态显示方法
51单片机多位数码管动态显示方法 1.数码管显示原理 2.多位数码管动态显示 3.示例程序 3.结语 1.数码管显示原理 相比学习单片机的同学一定对显示器,屏幕如OLED,LCD并不陌生,而在这些显示 ...
- STC 51单片机56——摇摇棒
主要代码: //增减图像时,需要修改 switch_show()和 H对应参数 //所用单片机:STC15W408S 内部Rc 11.0592MHz #include <STC15.H&g ...
- STC 51单片机42——汇编 定时器 舵机
ORG 0000H HighH EQU 30H; 定义变量,高电平高八位 TimerH EQU 31H; 定义变量,高电平高八位定时值 TimerL EQU ...
- STC 51单片机43——看门狗
看门狗测试,通过修改delay函数的延时长度,可以看到看门狗是否复位系统. #include <reg52.h> sfr WDT_CONTR =0xE1; ...
- STC 51单片机58——旋转LED
STC11F LED部分: #include "STC11.h" #define u8 unsigned char #define u16 unsigned int //全亮 / ...
- STC 51单片机46——看门狗测试
#include <reg52.h> sfr WDT_CONTR =0xE1; //声明WDT_CONTR void delay(void){ / ...
- 单片机如何使用?51单片机C语言编程实例有哪些?
大家好,我是无际单片机编程的徐明,今天和大家一起探讨一下"单片机如何使用?" 单片机如何使用,我们要知道单片机在哪里使用? 单片机是很多电子产品的核心器件,它具有一定的逻辑判断和事 ...
最新文章
- ASP.NET Razor – C# 逻辑条件简介
- LeetCode之 insertion-sort-list insertion-sort-list
- python 把数据 json格式输出
- QT设计UI:QT模式对话框打开文件
- 用Java中的抽象类扩展抽象类
- 站在K2角度审视流程--任务的独占与释放
- 揭开git的神秘面纱
- Mysql支持中文全文检索的插件mysqlcft-应用中的问题
- 将本地SQL Server数据库迁移到Azure SQL数据库
- Windows Azure Storage (1) Windows Azure Storage Service存储服务
- 拼多多的硬核逆生长!
- linux网络配置putty,linux基础:2、网络配置和用使用putty连接
- Java实现经典坦克大战及源代码下载
- MATLAB中的resample函数根本理解,我专栏中有Guitar.MAT资源
- ORACLE 错误 904
- 18款口碑爆棚手机浏览器,被一网打尽了
- live555源码分析(七)播放过程
- 转:高级软件工程师成长秘诀(文末有笔者自己的小评论)
- 7-4 大炮打蚊子 (20分)__C++
- 统一认证中心-auth2.0