当前位置:网站首页>STM32+MPU6050 Design Portable Mini Desktop Clock (Automatically Adjust Time Display Direction)
STM32+MPU6050 Design Portable Mini Desktop Clock (Automatically Adjust Time Display Direction)
2022-08-02 10:40:00 【InfoQ】
一、环境介绍
二、功能介绍




三、核心代码

3.1 main.c
#include "stm32f10x.h"
#include "beep.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include <string.h>
#include <stdlib.h>
#include "exti.h"
#include "timer.h"
#include "rtc.h"
#include "wdg.h"
#include "ds18b20.h"
#include "oled.h"
#include "fontdata.h"
#include "adc.h"
#include "FunctionConfig.h"
#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
/*
函数功能: 绘制时钟表盘框架
*/
void DrawTimeFrame(void)
{
u8 i;
OLED_Circle(32,32,31);//画外圆
OLED_Circle(32,32,1); //画中心圆
//画刻度
for(i=0;i<60;i++)
{
if(i%5==0)OLED_DrawAngleLine(32,32,6*i,31,3,1);
}
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
}
/*
函数功能: 更新时间框架显示,在RTC中断里调用
*/
char TimeBuff[20];
void Update_FrameShow(void)
{
/*1. 绘制秒针、分针、时针*/
OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-6-90,27,0);//清除之前的秒针
OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-90,27,1); //画秒针
OLED_DrawAngleLine2(32,32,rtc_clock.min*6-6-90,24,0);
OLED_DrawAngleLine2(32,32,rtc_clock.min*6-90,24,1);
OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-6-90,21,0);
OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-90,21,1);
//绘制电子钟时间
sprintf(TimeBuff,"%d",rtc_clock.year);
OLED_ShowString(65,16*0,16,TimeBuff); //年份字符串
OLED_ShowChineseFont(66+32,16*0,16,4); //显示年
sprintf(TimeBuff,"%d/%d",rtc_clock.mon,rtc_clock.day);
OLED_ShowString(75,16*1,16,TimeBuff); //月
if(rtc_clock.sec==0)OLED_ShowString(65,16*2,16," "); //清除多余的数据
sprintf(TimeBuff,"%d:%d:%d",rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
OLED_ShowString(65,16*2,16,TimeBuff); //秒
//显示星期
OLED_ShowChineseFont(70,16*3,16,5); //星
OLED_ShowChineseFont(70+16,16*3,16,6); //期
OLED_ShowChineseFont(70+32,16*3,16,rtc_clock.week+7); //具体的值
}
u8 DS18B20_TEMP_Info[10]; //DS18B20温度信息
/*
函数功能: DS18B20温度显示页面
*/
void DS18B20_ShowPageTable(short DS18B20_temp)
{
char DS18B20_buff[10]; //存放温度信息
unsigned short DS18B20_intT=0,DS18B20_decT=0; //温度值的整数和小数部分
DS18B20_intT = DS18B20_temp >> 4; //分离出温度值整数部分
DS18B20_decT = DS18B20_temp & 0xF; //分离出温度值小数部分
sprintf((char*)DS18B20_TEMP_Info,"%d.%d",DS18B20_intT,DS18B20_decT); //保存DS18B20温度信息,发送给上位机
OLED_ShowString(34,0,16,"DS18B20");
if(DS18B20_temp==0xFF)
{
OLED_ShowString(0,30,16," "); //清除一行的显示
//显示温度错误信息
OLED_ShowString(0,30,16,"DS18B20 Error!");
}
else
{
sprintf(DS18B20_buff,"%sC ",DS18B20_TEMP_Info);
//显示温度
OLED_ShowString(40,30,16,DS18B20_buff);
}
}
int main(void)
{
u8 stat;
u8 key_val;
u32 TimeCnt=0;
u16 temp_data; //温度数据
short aacx,aacy,aacz; //加速度传感器原始数据
short gyrox,gyroy,gyroz; //陀螺仪原始数据
short temp;
float pitch,roll,yaw; //欧拉角
u8 page_cnt=0; //显示的页面
u8 display_state1=0;
u8 display_state2=0;
BEEP_Init(); //初始化蜂鸣器
LED_Init(); //初始化LED
KEY_Init(); //按键初始化
DS18B20_Init(); //DS18B20
USARTx_Init(USART1,72,115200);//串口1的初始化
TIMERx_Init(TIM1,72,20000); //辅助串口1接收.20ms为一帧数据.
RTC_Init(); //RTC初始化
OLED_Init(0xc8,0xa1); //OLED显示屏初始化--正常显示
//OLED_Init(0xc0,0xa0); //OLED显示屏初始化--翻转显示
while(MPU6050_Init()) //初始化MPU6050
{
printf("MPU6050陀螺仪初始化失败!\r\n");
DelayMs(500);
}
// //注意:陀螺仪初始化的时候,必须正常摆放才可以初始化成
// while(mpu_dmp_init())
// {
// printf("MPU6050陀螺仪设置DMP失败!\r\n");
// DelayMs(1000);
// }
OLED_Clear(0x00); //清屏
DrawTimeFrame(); //画时钟框架
while(1)
{
key_val=KEY_GetValue();
if(key_val)
{
page_cnt=!page_cnt;
//时钟页面
if(page_cnt==0)
{
//清屏
OLED_Clear(0);
DrawTimeFrame(); //画时钟框架
RTC->CRH|=1<<0; //开启秒中断
}
else if(page_cnt==1)
{
//清屏
OLED_Clear(0);
RTC->CRH&=~(1<<0); //关闭秒中断
}
}
if(USART1_RX_STATE)
{
//*20200530154322
//通过串口1校准RTC时间
if(USART1_RX_BUFF[0]=='*')
{
rtc_clock.year=(USART1_RX_BUFF[1]-48)*1000+(USART1_RX_BUFF[2]-48)*100+(USART1_RX_BUFF[3]-48)*10+(USART1_RX_BUFF[4]-48)*1;
rtc_clock.mon=(USART1_RX_BUFF[5]-48)*10+(USART1_RX_BUFF[6]-48)*1;
rtc_clock.day=(USART1_RX_BUFF[7]-48)*10+(USART1_RX_BUFF[8]-48)*1;
rtc_clock.hour=(USART1_RX_BUFF[9]-48)*10+(USART1_RX_BUFF[10]-48)*1;
rtc_clock.min=(USART1_RX_BUFF[11]-48)*10+(USART1_RX_BUFF[12]-48)*1;
rtc_clock.sec=(USART1_RX_BUFF[13]-48)*10+(USART1_RX_BUFF[14]-48)*1;
RTC_SetTime(rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
OLED_Clear(0); //OLED清屏
DrawTimeFrame();//画时钟框架
}
USART1_RX_STATE=0;
USART1_RX_CNT=0;
}
//时间记录
DelayMs(10);
TimeCnt++;
if(TimeCnt>=100) //1000毫秒一次
{
TimeCnt=0;
LED1=!LED1;
temp_data=DS18B20_ReadTemp();
// printf("temp_data=%d.%d\n",temp_data>>4,temp_data&0xF);
// stat=mpu_dmp_get_data(&pitch,&roll,&yaw);
// temp=MPU6050_Get_Temperature(); //得到温度值
//MPU6050_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪原始数据
MPU6050_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据
//printf("温度数据:%d\r\n",temp);
// printf("陀螺仪原始数据 :x=%d y=%d z=%d\r\n",gyrox,gyroy,gyroz);
printf("加速度传感器数据:x=%d y=%d z=%d\r\n",aacx,aacy,aacz);
// printf("欧垃角:横滚角=%d 俯仰角=%d 航向角=%d\r\n",(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
//
//正着显示
if(aacz>=15000)
{
printf("正着显示\n");
if(display_state1!=1)
{
display_state2=0;
display_state1=1;
OLED_Init(0xc8,0xa1); //OLED显示屏初始化--正常显示
}
}
//翻转显示
else if(display_state2!=1)
{
printf("反着显示\n");
display_state1=0;
display_state2=1;
OLED_Init(0xc0,0xa0); //OLED显示屏初始化--翻转显示
}
}
if(page_cnt==1) //温度显示页面
{
DS18B20_ShowPageTable(temp_data);
}
}
}
3.2 mpu6050.c
#include "mpu6050.h"
#include "sys.h"
#include "delay.h"
#include <stdio.h>
/*--------------------------------------------------------------------IIC协议底层模拟时序--------------------------------------------------------------------------------*/
/*
硬件接线:
1 VCC 3.3V/5V 电源输入 --->接3.3V
2 GND 地线 --->接GND
3 IIC_SDA IIC 通信数据线 -->PB6
4 IIC_SCL IIC 通信时钟线 -->PB7
5 MPU_INT 中断输出引脚 ---->未接
6 MPU_AD0 IIC 从机地址设置引脚-->未接
AD0引脚说明:ID=0X68(悬空/接 GND) ID=0X69(接 VCC)
*/
/*
函数功能:MPU IIC 延时函数
*/
void MPU6050_IIC_Delay(void)
{
DelayUs(2);
}
/*
函数功能: 初始化IIC
*/
void MPU6050_IIC_Init(void)
{
RCC->APB2ENR|=1<<3; //先使能外设IO PORTB时钟
GPIOB->CRL&=0X00FFFFFF; //PB6/7 推挽输出
GPIOB->CRL|=0X33000000;
GPIOB->ODR|=3<<6; //PB6,7 输出高
}
/*
函数功能: 产生IIC起始信号
*/
void MPU6050_IIC_Start(void)
{
MPU6050_SDA_OUT(); //sda线输出
MPU6050_IIC_SDA=1;
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
/*
函数功能: 产生IIC停止信号
*/
void MPU6050_IIC_Stop(void)
{
MPU6050_SDA_OUT();//sda线输出
MPU6050_IIC_SCL=0;
MPU6050_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_SDA=1;//发送I2C总线结束信号
MPU6050_IIC_Delay();
}
/*
函数功能: 等待应答信号到来
返 回 值:1,接收应答失败
0,接收应答成功
*/
u8 MPU6050_IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
MPU6050_SDA_IN(); //SDA设置为输入
MPU6050_IIC_SDA=1;MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;MPU6050_IIC_Delay();
while(MPU6050_READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
MPU6050_IIC_Stop();
return 1;
}
}
MPU6050_IIC_SCL=0;//时钟输出0
return 0;
}
/*
函数功能:产生ACK应答
*/
void MPU6050_IIC_Ack(void)
{
MPU6050_IIC_SCL=0;
MPU6050_SDA_OUT();
MPU6050_IIC_SDA=0;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
}
/*
函数功能:不产生ACK应答
*/
void MPU6050_IIC_NAck(void)
{
MPU6050_IIC_SCL=0;
MPU6050_SDA_OUT();
MPU6050_IIC_SDA=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
}
/*
函数功能:IIC发送一个字节
返回从机有无应答
1,有应答
0,无应答
*/
void MPU6050_IIC_Send_Byte(u8 txd)
{
u8 t;
MPU6050_SDA_OUT();
MPU6050_IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
MPU6050_IIC_SDA=(txd&0x80)>>7;
txd<<=1;
MPU6050_IIC_SCL=1;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=0;
MPU6050_IIC_Delay();
}
}
/*
函数功能:读1个字节,ack=1时,发送ACK,ack=0,发送nACK
*/
u8 MPU6050_IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
MPU6050_SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
MPU6050_IIC_SCL=0;
MPU6050_IIC_Delay();
MPU6050_IIC_SCL=1;
receive<<=1;
if(MPU6050_READ_SDA)receive++;
MPU6050_IIC_Delay();
}
if(!ack)
MPU6050_IIC_NAck();//发送nACK
else
MPU6050_IIC_Ack(); //发送ACK
return receive;
}
/*--------------------------------------------------------------------MPU6050底层驱动代码--------------------------------------------------------------------------------*/
/*
函数功能:初始化MPU6050
返 回 值:0,成功
其他,错误代码
*/
u8 MPU6050_Init(void)
{
u8 res;
MPU6050_IIC_Init();//初始化IIC总线
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050
DelayMs(100);
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050
MPU6050_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps
MPU6050_Set_Accel_Fsr(0); //加速度传感器,±2g
MPU6050_Set_Rate(50); //设置采样率50Hz
MPU6050_Write_Byte(MPU_INT_EN_REG,0X00); //关闭所有中断
MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭
MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00); //关闭FIFO
MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效
res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);
if(res==MPU6050_ADDR)//器件ID正确
{
MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考
MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作
MPU6050_Set_Rate(50); //设置采样率为50Hz
}else return 1;
return 0;
}
/*
设置MPU6050陀螺仪传感器满量程范围
fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
返回值:0,设置成功
其他,设置失败
*/
u8 MPU6050_Set_Gyro_Fsr(u8 fsr)
{
return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
}
/*
函数功能:设置MPU6050加速度传感器满量程范围
函数功能:fsr:0,±2g;1,±4g;2,±8g;3,±16g
返 回 值:0,设置成功
其他,设置失败
*/
u8 MPU6050_Set_Accel_Fsr(u8 fsr)
{
return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
}
/*
函数功能:设置MPU6050的数字低通滤波器
函数参数:lpf:数字低通滤波频率(Hz)
返 回 值:0,设置成功
其他,设置失败
*/
u8 MPU6050_Set_LPF(u16 lpf)
{
u8 data=0;
if(lpf>=188)data=1;
else if(lpf>=98)data=2;
else if(lpf>=42)data=3;
else if(lpf>=20)data=4;
else if(lpf>=10)data=5;
else data=6;
return MPU6050_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器
}
/*
函数功能:设置MPU6050的采样率(假定Fs=1KHz)
函数参数:rate:4~1000(Hz)
返 回 值:0,设置成功
其他,设置失败
*/
u8 MPU6050_Set_Rate(u16 rate)
{
u8 data;
if(rate>1000)rate=1000;
if(rate<4)rate=4;
data=1000/rate-1;
data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器
return MPU6050_Set_LPF(rate/2); //自动设置LPF为采样率的一半
}
/*
函数功能:得到温度值
返 回 值:返回值:温度值(扩大了100倍)
*/
short MPU6050_Get_Temperature(void)
{
u8 buf[2];
short raw;
float temp;
MPU6050_Read_Len(MPU6050_ADDR,MPU_TEMP_OUTH_REG,2,buf);
raw=((u16)buf[0]<<8)|buf[1];
temp=36.53+((double)raw)/340;
return temp*100;;
}
/*
函数功能:得到陀螺仪值(原始值)
函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
返 回 值:0,成功,其他,错误代码
*/
u8 MPU6050_Get_Gyroscope(short *gx,short *gy,short *gz)
{
u8 buf[6],res;
res=MPU6050_Read_Len(MPU6050_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
if(res==0)
{
*gx=((u16)buf[0]<<8)|buf[1];
*gy=((u16)buf[2]<<8)|buf[3];
*gz=((u16)buf[4]<<8)|buf[5];
}
return res;;
}
/*
函数功能:得到加速度值(原始值)
函数参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
返 回 值:0,成功,其他,错误代码
*/
u8 MPU6050_Get_Accelerometer(short *ax,short *ay,short *az)
{
u8 buf[6],res;
res=MPU6050_Read_Len(MPU6050_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
if(res==0)
{
*ax=((u16)buf[0]<<8)|buf[1];
*ay=((u16)buf[2]<<8)|buf[3];
*az=((u16)buf[4]<<8)|buf[5];
}
return res;;
}
/*
函数功能:IIC连续写
函数参数:
addr:器件地址
reg:寄存器地址
len:写入长度
buf:数据区
返 回 值:0,成功,其他,错误代码
*/
u8 MPU6050_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
u8 i;
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令
if(MPU6050_IIC_Wait_Ack()) //等待应答
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Send_Byte(reg); //写寄存器地址
MPU6050_IIC_Wait_Ack(); //等待应答
for(i=0;i<len;i++)
{
MPU6050_IIC_Send_Byte(buf[i]); //发送数据
if(MPU6050_IIC_Wait_Ack()) //等待ACK
{
MPU6050_IIC_Stop();
return 1;
}
}
MPU6050_IIC_Stop();
return 0;
}
/*
函数功能:IIC连续写
函数参数:
IIC连续读
addr:器件地址
reg:要读取的寄存器地址
len:要读取的长度
buf:读取到的数据存储区
返 回 值:0,成功,其他,错误代码
*/
u8 MPU6050_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令
if(MPU6050_IIC_Wait_Ack()) //等待应答
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Send_Byte(reg); //写寄存器地址
MPU6050_IIC_Wait_Ack(); //等待应答
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令
MPU6050_IIC_Wait_Ack(); //等待应答
while(len)
{
if(len==1)*buf=MPU6050_IIC_Read_Byte(0);//读数据,发送nACK
else *buf=MPU6050_IIC_Read_Byte(1); //读数据,发送ACK
len--;
buf++;
}
MPU6050_IIC_Stop(); //产生一个停止条件
return 0;
}
/*
函数功能:IIC写一个字节
函数参数:
reg:寄存器地址
data:数据
返 回 值:0,成功,其他,错误代码
*/
u8 MPU6050_Write_Byte(u8 reg,u8 data)
{
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR<<1)|0);//发送器件地址+写命令
if(MPU6050_IIC_Wait_Ack()) //等待应答
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Send_Byte(reg); //写寄存器地址
MPU6050_IIC_Wait_Ack(); //等待应答
MPU6050_IIC_Send_Byte(data);//发送数据
if(MPU6050_IIC_Wait_Ack()) //等待ACK
{
MPU6050_IIC_Stop();
return 1;
}
MPU6050_IIC_Stop();
return 0;
}
/*
函数功能:IIC读一个字节
函数参数:
reg:寄存器地址
data:数据
返 回 值:返回值:读到的数据
*/
u8 MPU6050_Read_Byte(u8 reg)
{
u8 res;
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR<<1)|0);//发送器件地址+写命令
MPU6050_IIC_Wait_Ack(); //等待应答
MPU6050_IIC_Send_Byte(reg); //写寄存器地址
MPU6050_IIC_Wait_Ack(); //等待应答
MPU6050_IIC_Start();
MPU6050_IIC_Send_Byte((MPU6050_ADDR<<1)|1);//发送器件地址+读命令
MPU6050_IIC_Wait_Ack(); //等待应答
res=MPU6050_IIC_Read_Byte(0);//读取数据,发送nACK
MPU6050_IIC_Stop(); //产生一个停止条件
return res;
}
3.3 mpu6050.h
#ifndef __MPU6050_H
#define __MPU6050_H
#include "stm32f10x.h"
#define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
#define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
#define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
#define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
#define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
#define MPU_CFG_REG 0X1A //配置寄存器
#define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
#define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器
#define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
#define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
#define MPU_INT_EN_REG 0X38 //中断使能寄存器
#define MPU_INT_STA_REG 0X3A //中断状态寄存器
#define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器
#define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
#define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器
#define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器
#define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器
#define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
#define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
#define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
#define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
#define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
#define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
//重力加速度值,单位:9.5 m/s2
typedef struct
{
float accX;
float accY;
float accZ;
}accValue_t;
//因为模块AD0默认接GND,所以转为读写地址后,为0XD1和0XD0(如果接VCC,则为0XD3和0XD2) 从AD0接地机地址为:0X68
u8 MPU6050_Init(void); //初始化MPU6050
u8 MPU6050_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);//IIC连续写
u8 MPU6050_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf); //IIC连续读
u8 MPU6050_Write_Byte(u8 reg,u8 data); //IIC写一个字节
u8 MPU6050_Read_Byte(u8 reg); //IIC读一个字节
u8 MPU6050_Set_Gyro_Fsr(u8 fsr);
u8 MPU6050_Set_Accel_Fsr(u8 fsr);
u8 MPU6050_Set_LPF(u16 lpf);
u8 MPU6050_Set_Rate(u16 rate);
u8 MPU6050_Set_Fifo(u8 sens);
short MPU6050_Get_Temperature(void);
u8 MPU6050_Get_Gyroscope(short *gx,short *gy,short *gz);
u8 MPU6050_Get_Accelerometer(short *ax,short *ay,short *az);
//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU6050_ADDR 0X68
//IO方向设置
#define MPU6050_SDA_IN() {GPIOB->CRL&=0XF0FFFFFF;GPIOB->CRL|=8<<24;}
#define MPU6050_SDA_OUT() {GPIOB->CRL&=0XF0FFFFFF;GPIOB->CRL|=3<<24;}
//IO操作函数
#define MPU6050_IIC_SCL PBout(7) //SCL
#define MPU6050_IIC_SDA PBout(6) //SDA
#define MPU6050_READ_SDA PBin(6) //输入SDA
//IIC所有操作函数
void MPU6050_IIC_Delay(void); //MPU IIC延时函数
void MPU6050_IIC_Init(void); //初始化IIC的IO口
void MPU6050_IIC_Start(void); //发送IIC开始信号
void MPU6050_IIC_Stop(void); //发送IIC停止信号
void MPU6050_IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 MPU6050_IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 MPU6050_IIC_Wait_Ack(void); //IIC等待ACK信号
void MPU6050_IIC_Ack(void); //IIC发送ACK信号
void MPU6050_IIC_NAck(void); //IIC不发送ACK信号
#endif
边栏推荐
- 多线程(基础) - 4万字总结
- 8年软件测试工程师的感悟:与薪资相匹配的永远是实力
- Rear tube implements breadcrumb function
- LayaBox---TypeScript---Iterator and generator
- R language ggplot2 visualization: use the ggbarplot function of the ggpubr package to visualize the horizontal column chart (bar chart), use the orientation parameter to set the column chart to be tra
- ASP.NET Core 6框架揭秘实例演示[31]:路由&quot;高阶&quot;用法
- 一体化在线政务服务平台,小程序容器技术加速建设步伐
- 神通数据库,批量插入数据的时候失败
- Hello, my new name is "Bronze Lock/Tongsuo"
- Jay Chou's new song is released, crawl the "Mojito" MV barrage, and see what the fans have to say!
猜你喜欢
随机推荐
bgp与mpls综合实验
The R language uses the ggtexttable function of the ggpubr package to visualize the table data (draw the table directly or add the table data to the image), set the theme parameter to customize the fi
R语言ggpubr包的ggline函数可视化分组折线图、add参数为mean_se和dotplot可视化不同水平均值的折线图并为折线图添加误差线(se标准误差)和点阵图、自定义palette设置颜色
【术语科普】关于集成工作台那些难懂的词儿,看这篇秒懂!
ASP.NET Core 6框架揭秘实例演示[31]:路由&quot;高阶&quot;用法
Shell脚本实现多选DNS同时批量解析域名IP地址(新更新)
为什么要使用BGP?
MySQL模糊查询性能优化
LayaBox---TypeScript---命名空间和模块
情景剧《重走长征路》上演
从测试入门到测试架构师,这10年,他是这样让自己成才的
一款优秀的中文识别库——ocr
如何封装微信小程序的 wx.request() 请求
One Summer of Open Source | How to Quickly Integrate Log Modules in GO Language Framework
Geoffery Hinton:深度学习的下一个大事件
如何搭建威纶通触摸屏与S7-200smart之间无线PPI通信?
leetcode: 200. 岛屿数量
字节跳动软件测试岗,收到offer后我却拒绝了~给面试的人一些忠告....
超赞!发现一个APP逆向神器!
List-based queuing and calling system