找回密码
 立即注册

QQ登录

只需一步,快速开始

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

key+1602+AD15+MPU9250 - 显示长轴方向相对Z的偏转角度

[复制链接]
跳转到指定楼层
楼主
ID:587705 发表于 2019-7-27 19:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<STC12C5A60S2.h>
#include<lcd1602.h>
#include<MPU9250.H>



unsigned char XS[]="Welcome!";

unsigned char BUF[10];       //接收数据缓存区
signed int T_X,T_Y,T_Z;

unsigned char readkey()
{
   unsigned char keytemp,KEY=0;
   P0=0x0f;
   keytemp=P0;
   if(keytemp==0x0f) return 0xff;
   else   KEY=keytemp;
   P0=0xf0;
   keytemp=P0;
   if(keytemp==0xf0) return 0xff;
   else  KEY=KEY|keytemp;
   switch(KEY)
   {
     case 0xEE: KEY=1;break;
         case 0xDE: KEY=2;break;
         case 0xBE: KEY=3;break;
         case 0x7E: KEY=4;break;
         case 0xED: KEY=5;break;
         case 0xDD: KEY=6;break;
         case 0xBD: KEY=7;break;
         case 0x7D: KEY=8;break;
         case 0xEB: KEY=9;break;
         case 0xDB: KEY=10;break;
         case 0xBB: KEY=11;break;
         case 0x7B: KEY=12;break;
         case 0xE7: KEY=13;break;
         case 0xD7: KEY=14;break;
         case 0xB7: KEY=15;break;
         case 0x77: KEY=16;break;
         default:KEY=0;
         }

   return(KEY);
}

void main()
{        unsigned char i,key,keytemp;
    signed int volt,Angle;  //装AD转换结果
        float  VDF;
    P0M0=0xff;
        P0M1=0x00;   //设置P0口为强上拉输

        P1M1=0x20;
        P1M0=0x00;   //设置P1.5口为高阻输入 AD转换的需求

        P1ASF=0x20; //只将P1.5        设置为AD转换的输入
    AUXR1=AUXR1&0xFB;//只将ADRJ置1,其余各位不变
                         //AD转换的数据高8位在ADC_RES里,低2位在ADC_RESL里

        ADC_CONTR=0xE5;  //给ADC电源,清除ADC_FLAG,指定P1.5为转换输入


    LCD1602_delay_ms(10);                                 //延时
    Init_MPU9250();                     //初始化MPU9250



        Init_LCD1602();                                                                        //初始化LCD1602
        LCD1602_delay_ms(1000);
        LCD1602_POT(5,0);                                                //指针设置到第0行
        i=0;
        while(XS[i]!='\0')
                {
             LCD1602_write_data(XS[i++]);
                 LCD1602_delay_ms(2000);                                 //延时
                  }       
    LCD1602_write_com(0x01);                        //清屏指令
        LCD1602_delay_ms(2000);                                 //延时
        while(1)
        {       
                                          
                key=readkey();                 //调用键盘判断,返回值是0xff,表示没有按键按下,否则返回按键值:1---16
                if(key!=0xff)
                {
                        if(key<10) keytemp=key|0x30;
            else keytemp='A'+key-10;
            LCD1602_POT(0,0);
            LCD1602_write_word("KEY=");
            LCD1602_write_data(keytemp);
                }
                else
                {
                    LCD1602_POT(0,0);
            LCD1602_write_word("KEY=?");
                }

            ADC_CONTR=0xED;  //给ADC电源,清除ADC_FLAG,指定P1.5为转换输入 并且启动转换
                i=5;
                while(i--);  //空等几个时钟,等AD启动命令生效
        while(ADC_CONTR&0x10==0);  //等待判断ADC_FLAG是否为1,为0将原地等待
                volt=ADC_RES*4+(ADC_RESL&0x03);                 //拼装10位转换得到的数据
                VDF=(float)volt*5/1024;           //根据分辨率10位,分辨率就是2的10次方=1024,参考电压是芯片的工作电压(5V),必须定义为浮点型
                VDF=VDF*100;    //将x.yy的电压值扩大100倍,变成xyy
                volt=(unsigned int)VDF;           //再将其转换为整形,为分离各位进行显示做准备
                LCD1602_POT(11,0);
                LCD1602_write_data((volt/100)|0x30);  //将百位数的ASCII码输出(|0x30就是得到数字的ADCII码)
                LCD1602_write_data('.');                //显示小数点
                LCD1602_write_data(((volt%100)/10)|0x30);         //显示十分位
                LCD1602_write_data((volt%10)|0x30);                        //显示百分位
                LCD1602_write_data('V');
                LCD1602_delay_ms(100);                                  

                 MPU9250_Read_Average(&T_X,&T_Y,&T_Z,5,ACCEL); //读5次加速度,求平均值
//                 LCD1602_MPU9250XYZ(T_X,T_Y,T_Z);                //在LCD1602上显示X,Y,Z方向的加速度值
//                 LCD1602_delay_ms(100);

                 Angle=MPU9250_Get_ZAngle(T_X,T_Y,T_Z);           //获得相对于自然Z轴的倾斜角度:4位十进制带符号整数 -1800---+1800度
                                                                                                   //用来显示,自己在第三位后加. 用来比较计算,记得是比实际值大10倍
                 LCD1602_POT(0,1);
                 LCD1602_write_word("Agl_Z:");
                 if(Angle<0)
                   {  
                      LCD1602_write_data('-');
                          Angle=-Angle;                                                 //显示的时候,为了计算方便,负值(补码)要转换为正数来计算
                        }
                 else
                 LCD1602_write_data('+');
                 LCD1602_write_data((Angle/1000)|0x30);  //将千位数的ASCII码输出(|0x30就是得到数字的ADCII码) 实际角度的百位
                 LCD1602_write_data(((Angle%1000)/100)|0x30);         //显示百位                 实际角度的十位
                 LCD1602_write_data((Angle%100)/10|0x30);                        //显示十位           实际角度的个位
                 LCD1602_write_data('.');                     //显示小数点
                 LCD1602_write_data((Angle%10)|0x30);                          //显示个位           实际角度的十分位
                  LCD1602_write_data('\'');
/*                                                                                                                
                 Angle=MPU9250_Get_Angle(T_X,T_Y,T_Z,0);        //计算得到与自然Z轴的角度
                   LCD1602_POT(0,1);
                 LCD1602_write_data((Angle/100)|0x30);  //将百位数的ASCII码输出(|0x30就是得到数字的ADCII码)
                 LCD1602_write_data(((Angle%100)/10)|0x30);         //显示十分位
                 LCD1602_write_data((Angle%10)|0x30);                        //显示百分位
                  
                 Angle=MPU9250_Get_Angle(T_X,T_Y,T_Z,1);           //计算得到与自然X轴的角度
                   LCD1602_POT(4,1);
                 LCD1602_write_data((Angle/100)|0x30);  //将百位数的ASCII码输出(|0x30就是得到数字的ADCII码)
                 LCD1602_write_data(((Angle%100)/10)|0x30);         //显示十分位
                 LCD1602_write_data((Angle%10)|0x30);                        //显示百分位

                 Angle=MPU9250_Get_Angle(T_X,T_Y,T_Z,2);          //计算得到与自然Y轴的角度
                   LCD1602_POT(8,1);
                 LCD1602_write_data((Angle/100)|0x30);  //将百位数的ASCII码输出(|0x30就是得到数字的ADCII码)
                 LCD1602_write_data(((Angle%100)/10)|0x30);         //显示十分位
                 LCD1602_write_data((Angle%10)|0x30);                        //显示百分位
                                                                                                                                                           */
                 
//                  MPU9250_Read_Average(&T_X,&T_Y,&T_Z,10,GYRO); //读10次陀螺仪的值,求平均值
             
                 
         
//             MPU9250_Read_Average(&T_X,&T_Y,&T_Z,10,MAG); //读10次磁场的值,求平均值
               
               


        }
}


#include "LCD1602.h"

//****************************************************
//MS延时函数(12M晶振下测试)
//****************************************************
void LCD1602_delay_ms(unsigned int n)
{
        unsigned int  i,j;
        for(i=0;i<n;i++)
                for(j=0;j<123;j++);
}

//****************************************************
//写指令
//****************************************************
void LCD1602_write_com(unsigned char com)
{
        LCD1602_RS = 0;
        LCD1602_delay_ms(1);
        LCD1602_EN = 1;
        LCD1602_PORT = com;
        LCD1602_delay_ms(1);
        LCD1602_EN = 0;
}

//****************************************************
//写数据
//****************************************************
void LCD1602_write_data(unsigned char dat)
{
        LCD1602_RS = 1;
        LCD1602_delay_ms(1);       
        LCD1602_PORT = dat;
        LCD1602_EN = 1;
        LCD1602_delay_ms(1);
        LCD1602_EN = 0;
}

//****************************************************
//指定位置:x列,y行
//****************************************************
void LCD1602_POT(unsigned char x,unsigned char y)
{
   unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;
    else
        addr = 0x40 + x;

    LCD1602_write_com(addr|0x80);

}

//****************************************************
//连续写字符
//****************************************************
void LCD1602_write_word(unsigned char *s)
{
        while(*s>0)
        {
                LCD1602_write_data(*s);
                s++;
        }
}

void Init_LCD1602()
{
        LCD1602_EN = 0;
        LCD1602_RW = 0;                                                //设置为写状态
        LCD1602_write_com(0x38);                        //显示模式设定
        LCD1602_write_com(0x0c);                        //开关显示、光标有无设置、光标闪烁设置
        LCD1602_write_com(0x06);                        //写一个字符后指针加一
        LCD1602_write_com(0x01);                        //清屏指令
}



#ifndef __MPU9250_H__
#define __MPU9250_H__

#include<STC12C5A60S2.h>

#define  SCL   P10
#define  SDA   P11
#define  SCL_H   SCL=1
#define  SCL_L   SCL=0
#define  SDA_H   SDA=1
#define  SDA_L   SDA=0
#define  SDA_read  SDA

#define  ACCEL   1
#define  GYRO    2
#define  MAG     3



// 定义MPU9250内部地址
//****************************************
#define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
#define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
#define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)

#define        ACCEL_XOUT_H        0x3B
#define        ACCEL_XOUT_L        0x3C
#define        ACCEL_YOUT_H        0x3D
#define        ACCEL_YOUT_L        0x3E
#define        ACCEL_ZOUT_H        0x3F
#define        ACCEL_ZOUT_L        0x40

#define        TEMP_OUT_H                0x41
#define        TEMP_OUT_L                0x42

#define        GYRO_XOUT_H                0x43
#define        GYRO_XOUT_L                0x44       
#define        GYRO_YOUT_H                0x45
#define        GYRO_YOUT_L                0x46
#define        GYRO_ZOUT_H                0x47
#define        GYRO_ZOUT_L                0x48

               
#define MAG_XOUT_L                0x03
#define MAG_XOUT_H                0x04
#define MAG_YOUT_L                0x05
#define MAG_YOUT_H                0x06
#define MAG_ZOUT_L                0x07
#define MAG_ZOUT_H                0x08


#define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
#define        WHO_AM_I                  0x75        //IIC地址寄存器(默认数值0x68,只读)


//****************************

#define        GYRO_ADDRESS   0xD0          //陀螺地址
#define MAG_ADDRESS    0x18   //磁场地址
#define ACCEL_ADDRESS  0xD0          //加速度地址



void Init_MPU9250(void);
void READ_MPU9250_ACCEL(unsigned char *BUF,signed int *T_X,signed int *T_Y,signed int *T_Z);
void READ_MPU9250_GYRO(unsigned char *BUF,signed int *T_X,signed int *T_Y,signed int *T_Z);
void READ_MPU9250_MAG(unsigned char *BUF,signed int *T_X,signed int *T_Y,signed int *T_Z);
void MPU9250_Read_Average(signed int *x,signed int *y,signed int *z,unsigned char times,unsigned char ACCEL_or_GYRO_or_MAG);
unsigned int MPU9250_Get_Angle(float x,float y,float z,unsigned char  Z_or_X_or_Y);
void LCD1602_MPU9250XYZ(signed int T_X,signed int T_Y,signed int T_Z);
signed int MPU9250_Get_ZAngle(float x,float y,float z);
void Delayms(unsigned int n);

#endif

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

使用道具 举报

沙发
ID:1 发表于 2019-7-28 01:58 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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