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