本帖最后由 湘江旧迹秋心 于 2020-12-5 21:15 编辑
T5L屏能够利用指令通过改变系统变量地址0x81上的.1-.0位,实现显示方向的更改。在有些应用场合下,我们可能更希望利用重力感应实现屏幕显示方向的自动更改。 在这里,限于内容,第一节我主要介绍使用MPU6050芯片实现横竖屏切换的功能的主要原理,下一节将贴上个人写的功能代码。 MPU6050是一种六轴运动传感器,能够输出姿态角(俯仰角,横滚角,偏转角),被大量用于飞行器等需要姿态输出的控制场合中,所以使用MPU6050可以有效帮助没有使用经验的人减少开发时间。关于其详细介绍,我在这里不做过多的概述,网络上非常多,鉴于MPU6050的某些特性,我将介绍两种方案。 方案一:使用MPU6050芯片 图0是mpu6050的原理图,其使用IIC(SCL和 SDA)作为通信接口,鉴于T5L没有IIC口,所以需要用软件模拟的方法,这一点可以参考IIC通信的时序图进行编辑。 //I2C起始信号
void I2C_Start()
{
SDA = 1;
SCL = 1;
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us();
SCL=0; //延时
}
//I2C停止信号
void I2C_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
//I2C发送应答信号,入口参数:ack (0:ACK 1:NAK)
void I2C_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
//I2C接收应答信号
bit I2C_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
//向I2C总线发送一个字节数据
void I2C_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
I2C_RecvACK();
}
//从I2C总线接收一个字节数据
uchar I2C_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;
}
完成了这一步,就可以做MPU605的程序了。 MPU6050的程序可以分为以下几步:
1) 初始化IIC接口 2) 复位 MPU6050 这一步让 MPU6050 内部所有寄存器恢复默认值,通过对电源管理寄存器 1(0X6B)的bit7 写 1 实现。复位后,电源管理寄存器 1 恢复默认值(0X40),然后必须设置该寄存器为0X00,以唤醒 MPU6050,进入正常工作状态。 3) 设置角速度传感器(陀螺仪)和加速度传感器的满量程范围 这一步,我们设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。我们一般设置陀螺仪的满量程范围为±2000dps,加速度传感器的满量程范围为±2g。 4) 设置其他参数 这里,我们还需要配置的参数有:关闭中断、关闭 AUX IIC 接口、禁止 FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)等。我们不用中断方式读取数据,所以关闭中断,然后也没用到 AUX IIC 接口外接其他传感器,所以也关闭这个接口。分别通过中断使能寄存器(0X38)和用户控制寄存器(0X6A)控制。MPU6050 可以使用 FIFO 存储传感器数据,不过我们没有用到,所以关闭所有 FIFO 通道,这个通过 FIFO 使能寄存器(0X23)控制,默认都是 0(即禁止FIFO),所以用默认值就可以了。陀螺仪采样率通过采样率分频寄存器(0X19)控制,这个采样率我们一般设置为 50 即可。数字低通滤波器(DLPF)则通过配置寄存器(0X1A)设置,一般设置 DLPF 为带宽的 1/2 即可。 5) 配置系统时钟源并使能角速度传感器和加速度传感器 系统时钟源同样是通过电源管理寄存器 1(0X1B)来设置,该寄存器的最低三位用于设置系统时钟源选择,默认值是 0(内部 8M RC 震荡),不过我们一般设置为 1,选择 x 轴陀螺 PLL 作为时钟源,以获得更高精度的时钟。同时,使能角速度传感器和加速度传感器,这两个操作通过电源管理寄存器 2(0X6C)来设置,设置对应位为 0即可开启。 至此,MPU6050 的初始化就完成了,可以正常工作了(其他未设置的寄存器全部采用默认值即可),接下来,我们就可以读取相关寄存器,得到加速度传感器、角速度传感器和温度传感器的数据了。 以下是部分代码程序,可以在T5L上运行
//向I2C设备写入一个字节数据
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //内部寄存器地址,
I2C_SendByte(REG_data); //内部寄存器数据,
I2C_Stop(); //发送停止信号
}
//从I2C设备读取一个字节数据
uchar Single_ReadI2C(uchar REG_Address)
{
uchar REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号
REG_data=I2C_RecvByte(); //读出寄存器数据
I2C_SendACK(1); //接收应答信号
I2C_Stop(); //停止信号
return REG_data;
}
//初始化MPU6050
void MPU6050_Init(void)
{
int i=0,j=0;
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++)
{
;
}
}
Single_WriteI2C(MPU6050_RA_PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(MPU6050_RA_SMPLRT_DIV , 0x07); //陀螺仪采样率,1KHz
Single_WriteI2C(MPU6050_RA_CONFIG , 0x06); //低通滤波器的设置,截止频率是1K,带宽是5K
Single_WriteI2C(MPU6050_RA_ACCEL_CONFIG , 0x00); //配置加速度传感器工作在2G模式,不自检
Single_WriteI2C(MPU6050_RA_GYRO_CONFIG, 0x18); //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
}
//获得数据
int GetData(uchar REG_Address)
{
uchar H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L;
}
void MPU6050_ReadData(u8 reg_add,unsigned char*Read,u8 num)
{
unsigned char i;
I2C_Start();
Single_WriteI2C(MPU6050_SLAVE_ADDRESS);
Single_WriteI2C(reg_add);
I2C_Start();
Single_WriteI2C(MPU6050_SLAVE_ADDRESS+1);
for(i=0;i<(num-1);i++){
*Read=IIC_mpu6050_ReadByte(1);
Read++;
}
*Read=Single_ReadI2C(0);
I2C_Stop();
}
void MPU6050ReadAcc(short *accData)
{
u8 buf[6];
Single_ReadI2C(MPU6050_ACC_OUT, buf, 6);
accData[0] = (buf[0] << 8) | buf[1];
accData[1] = (buf[2] << 8) | buf[3];
accData[2] = (buf[4] << 8) | buf[5];
}
void MPU6050ReadGyro(short *gyroData)
{
u8 buf[6];
Single_ReadI2C(MPU6050_GYRO_OUT,buf,6);
gyroData[0] = (buf[0] << 8) | buf[1];
gyroData[1] = (buf[2] << 8) | buf[3];
gyroData[2] = (buf[4] << 8) | buf[5];
}
void MPU6050ReadTemp(short *tempData)
{
u8 buf[2];
Single_ReadI2C(MPU6050_RA_TEMP_OUT_H,buf,2); //读取温度值
*tempData = (buf[0] << 8) | buf[1];
}
void MPU6050_ReturnTemp(float *Temperature)
{
short temp3;
u8 buf[2];
Single_ReadI2C(MPU6050_RA_TEMP_OUT_H,buf,2); //读取温度值,
temp3= (buf[0] << 8) | buf[1];
*Temperature=((double) temp3/340.0)+36.53; //转换温度值为摄氏度
}
下图是我用串口助手将数据进行打印的一个效果。 //以下是部分MPU6050的内部地址
#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 PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
//函数声明
到这一步也就完成MPU6050的工作,下一步就是在T5L屏上的处理了,所以先说一下第二种方案吧。 方案一:使用对MPU6050进行过封装的芯片
对于T5L屏的串口处理程序,论坛里有很多,就不多说了。 到了这儿,姿态数据的获取已经完成了,接下来就是屏幕的配合了,这儿我们需要提前准备两张背景图,横屏和竖屏的,并且用DGUS做好工程,注意,两张背景图上必须是一模一样的控件,即他们的地址,功能要相同,然后我们利用页面切换+方向更改命令或者在T5L上进行编程处理。
|