找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1568|回复: 2
打印 上一主题 下一主题
收起左侧

程序烧进单片机以后显示的方向和角度都不会变化,求解答

[复制链接]
跳转到指定楼层
楼主
ID:531097 发表于 2019-5-11 10:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
20黑币
#include <reg52.h>                 //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
#define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535
#include  <math.h>    //Keil library  
#include  <stdio.h>   //Keil library        
#include  <INTRINS.H>

sbit rs=P2^6;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
sbit rw=P2^5;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
sbit e =P2^7;         //片选信号   下降沿触发

sbit SCL=P2^1;      //IIC时钟引脚定义
sbit SDA=P2^0;      //IIC数据引脚定义
sbit drdy=P3^3;

#define        SlaveAddress   0x3C                 //定义器件在IIC总线中的从地址
uchar BUF[8];                        //接收数据缓存区              
uchar ge,shi,bai,qian,wan;           //显示变量
int  dis_data;                       //变量

/******************1ms 延时函数*******************/
void delay_1ms(uint q)
{
        uint i,j;
        for(i=0;i<q;i++)
                for(j=0;j<120;j++);
}


/***********************延时函数************************/
void delay_uint(uint q)
{
        while(q--);
}

/**************************************
延时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_();

}

/***********************lcd1602写命令函数************************/
void write_com(uchar com)
{
        e=0;
        rs=0;
        rw=0;
        P0=com;
        delay_uint(3);
        e=1;
        delay_uint(25);
        e=0;
}

/***********************lcd1602写数据函数************************/
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上显示这字符函数************************/
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初始化设置************************/
void init_1602()         //lcd1602初始化设置
{
        write_com(0x38);        //
        write_com(0x0c);
        write_com(0x06);
        delay_uint(1000);
        //write_string(1,0,"  zhi nan zhen ");               
        write_string(2,0,"               ");        
        write_zifu(2,11,0xdf);  //显示度        
}

/***********************lcd1602上显示两位十进制数************************/
void write_jiaodu(uchar hang,uchar add,uint date)
{
        if(hang==0)   
                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);        
}

/**************************************
起始信号
**************************************/
void HMC5883_Start()
{
    SDA = 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(uchar dat)
{
    uchar i;

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

/**************************************
从IIC总线接收一个字节数据
**************************************/
uchar HMC5883_RecvByte()
{
    uchar i;
    uchar 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~0x8
//
//******************************************************
void Multiple_read_HMC5883()
{   uchar i;
    HMC5883_Start();                          //起始信号
    HMC5883_SendByte(SlaveAddress);           //发送设备地址+写信号
    HMC5883_SendByte(0x03);                   //发送存储单元地址,从0x3开始  
        HMC5883_SendByte(0x3c);      
    HMC5883_Start();                          //起始信号
    HMC5883_SendByte(SlaveAddress+1);         //发送设备地址+读信号
        //HMC5883_SendByte(0x3c);
        for (i=0; i<7; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = HMC5883_RecvByte();          //BUF[0]存储数据
        if (i == 6)
        {
           HMC5883_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          HMC5883_SendACK(0);                //回应ACK
       }
   }
   HMC5883_Stop();
    delay_1ms(5);
}

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

/*****************主函数********************/
void main()
{        
    float x,y,z,jiaodu;
    double angle;
    //P0 = P1 = P2 = P3 = 0xff;      //单片机IO口初始化为1
            Init_HMC5883();
        init_1602();                           //lcd1602初始化
        while(1)
        {   
            Multiple_read_HMC5883();      //连续读出数据,存储在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
                //x=BUF[0] << 8 | BUF[1]; //Combine MSB and LSB of X Data output register  最高有效位
                    //y=BUF[2] << 8 | BUF[3]; //Combine MSB and LSB of Z Data output register
                    //z=BUF[4] << 8 | BUF[5]; //Combine MSB and LSB of Y Data output register
                       
            angle= (atan2(y,x) * (180 / 3.14159265) + 180); // angle in degrees
                jiaodu = 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(300);
                               
        }
}



//void Int1()        interrupt 0                //外部中断1的中断函数
//{
//        delay_1ms(10);         //延时消抖
//        Multiple_read_HMC5883();
//}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:405033 发表于 2019-5-11 21:10 | 只看该作者
可否详细一点,要做什么,用到了什么,这样方便大家解答,不然我们烧了这个程序,不知道角度和方向是用到了什么模块实现变化的,也无法解答你这个问题
回复

使用道具 举报

板凳
ID:531097 发表于 2019-5-12 11:17 | 只看该作者
疯子本人 发表于 2019-5-11 21:10
可否详细一点,要做什么,用到了什么,这样方便大家解答,不然我们烧了这个程序,不知道角度和方向是用到了 ...

要做一个基于单片机的电子罗盘,用到的是HMC5883L
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表