#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
|