请问STM32最小核心板如何跟mpu6050通讯接口,I2C通讯协议能简单说明一下吗? I2C通讯协

stm32F103 模拟I2C mpu6050收到数据全为0,或者地址为209,104,0x68,0xD0的一些解决办法总结
stm32F103 模拟I2C mpu6050收到数据全为0,或者地址为209,104,0x68,0xD0的一些解决办法总结:
最近在学习模拟I2C,硬件有两套stm32F103C8T6和stm32F103RBT6,网上买的mpu6050套件。用stm32F103RBT6正常读到数据,可是换stm32F103C8T6读到的全是0,读who am I 按道理应该是104 (0x68)。但是读到的有时候 全为0 甚至209,或者255等等。
首先看能否读到who am i 读不到或者读的不正确就,对mpu6050进行一下复位:
IICwriteBit(devAddr,MPU6050_RA_PWR_MGMT_1,7,1);
delay_ms(30);
IICwriteBit(devAddr,MPU6050_RA_PWR_MGMT_1,7,0);
2 狗日的甚至我用不同的线缆读的却都不一样。更不说不同的板子了。不能的板子在keil编译的时候最好选择相应的配置。
3 读不到who am i 也有可能是挂了一个以上的I2C设备,于是我就手工割掉了一个。
4 顺便说个问题 在I2C的时候 PB67 成功了PB56成功了,但是PB45 却一直有问题,最后多亏一位大神相助,STM32的PB3、PB4,分别是JTAG的JTDO和NJTRST引脚,在没关闭JTAG功能之前,在程序中是配置不了这些引脚的功能的。要配置这些引脚,首先要开启AFIO时钟,然后在AFIO的设置中,释放这些引脚。具体看STM32的参考手册中有关AFIO的部分。 选自:
下图为读错的情况:
第一波也读对了,但是数据全为0,这个做了几次试验,应该是上电复位的时候接触不好,导致初始化的时候 还是没有完美。
后面这张为改正来后的测试数据
附上程序源码:
最后本人菜鸟,正在学习中,有问题还请多多交流指正 ,如有侵权立即删除。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!MPU6050使用I2C协议读出X轴原始数据的51单片机程序
单片机&嵌入式
单片机应用
嵌入式操作系统
学习工具&教程
学习和开发单片机的必备工具
(有问必答)
(带你轻松入门)
电子元件&电路模块
当前位置: >>
>> 浏览文章
MPU6050使用I2C协议读出X轴原始数据的51单片机程序
主:STC89C54&&&&下面代码#include &reg51.h&#define uchar unsigned char//#define addr_x 0xae // 写//#define addr_d 0xaf // &读sbit sda = P2^1; //数据管脚sbit scl = P2^0; //时钟管脚//****************************************// 定义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为读取void DelayUs2x(unsigned char t) //延时1{ &&&while(--t);}void DelayMs(unsigned char t) //延时2{& & &&while(t--)&{& & &//大致延时1mS& & &DelayUs2x(245);
DelayUs2x(245);&}}void delay() //延时大于4μs{;;}//*******************I2C操作协议******************************void i2_qs() //起始信号{ sda = 1; //拉高数据 scl = 1; //拉高时钟 delay(); //延时大于 4μs sda = 0; //拉低数据产生起始信号(下降沿) delay(); //延时大于 4μs scl = 0; //拉低时钟 delay(); //延时大于 4μs}void i2_tz() //停止信号{ sda = 0; //拉低数据 scl = 1; //拉高时钟 delay(); //延时大于 4μs sda = 1; //拉高时钟产生结束信号(上升沿) delay(); //延时大于 4μs }void i2_ack(bit _ack) //入口产生 0 ack 1 nak{ sda = _ //ack或者nak scl = 1; //拉高时钟 delay(); //延时大于 4μs scl = 0; //拉低时钟 delay(); //延时大于 4μs}void i2_fs(uchar Data) //发送8位数据{
for(i=0;i&8;i++) //8位计数 {
Data &&= 1; //把最高位移送到进制标志位中(CY)
sda = CY; //把进制位中的数据赋值给数据线
scl = 1; //拉高时钟
delay(); //延时大于 4μs
scl = 0; //拉低时钟
//这里 } //下面代码是接收ACK的代码 delay();//延时大于 4μs sda = 1; //拉高数据准备接收ACK scl = 1; //拉高时钟产生稳定的有效的数据(相对的) if(sda==1) //确认接收的是ACK还是NAK
ack = 0;//ack else
ack = 1;//nak scl = 0; //拉低时钟 delay(); //延时大于 4us }uchar i2_js() //接收8位数据{ uchar i,Data = 0; sda = 1; //使能内部上拉,准备读取数据 for(i=0;i&8;i++) //8位计数器 {
Data &&= 1; //移出数据的最高位
scl = 1; //拉高时钟
delay(); //延时大于 4us
Data |=//接收数据
scl = 0; //拉低时钟
delay(); //延时大于 4us
} return D}void i2_sj_x(uchar addr,uchar Data) //往设备内写入数据(参数 1、寄存器地址 2、写入的数据){ i2_qs();
//起始信号 i2_fs(SlaveAddress); //设备地址+写信号 i2_fs(addr); //寄存器内部地址 i2_fs(Data); //写入设备的数据 i2_tz();
//停止信号}uchar i2_sj_d(uchar addr) //读取数据(参数 寄存器地址){ uchar D i2_qs();
//起始信号 i2_fs(SlaveAddress); //设备地址+写信号 i2_fs(addr); //寄存器内部地址 i2_qs();
//起始信号 i2_fs(SlaveAddress+1); //设备地址+读信号 Data = i2_js(); //读取数据 i2_ack(0);
//ACK应答 i2_tz();
//停止信号 return D //返回读取的数据}//*******************I2C操作协议******************************void mup6050(){ i2_sj_x(PWR_MGMT_1, 0x00); i2_sj_x(SMPLRT_DIV, 0x07); i2_sj_x(CONFIG, 0x06); i2_sj_x(GYRO_CONFIG, 0x18); i2_sj_x(ACCEL_CONFIG, 0x01); /* Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态& Single_WriteI2C(SMPLRT_DIV, 0x07); //陀螺仪采集频率 Single_WriteI2C(CONFIG, 0x06);//低通滤波频率 Single_WriteI2C(GYRO_CONFIG, 0x18);//陀螺仪自检及测量范围 Single_WriteI2C(ACCEL_CONFIG, 0x01);//加速计自检、测量范围及高通滤波频率 */}/**************************************串口**********************************/void CSH &(void) //初始化串口{& & SCON &= 0x50;
& & & &// SCON: 模式 1, 8-bit UART, 使能接收 && & TMOD |= 0x20; & & & & & & & // TMOD: timer 1, mode 2, 8-bit 重装& & TH1 & = 0xFD; & & & & & & & // TH1: &重装值 9600 波特率 晶振 11.0592MHz && & TR1 & = 1; & & & & & & & & &// TR1: &timer 1 打开 & & & & & & & & & & & &&& & EA & &= 1; & & & & & & & & &//打开总中断& & //ES & &= 1; & & & & & & & & &//打开串口中断}void SendByte(unsigned char dat) //发送一个字符{&SBUF = //SBUF 串行数据缓冲器&while(!TI); &//TI发送中断标志位 (当数据发送完毕后由硬件置 1 否则等待硬件置 1)& & & TI = 0;&}/************************************************************************************/void main(void){ uchar dat1,dat2,i; mup6050(); CSH(); /* i2_sj_x(3,0x0f); //数据写入24c02 DelayMs(50); dat = i2_sj_d(3); //从24c02中读取数据 */ //P1 = //使用8个LED显示读出的数据 while(1) {
dat1 = i2_sj_d(GYRO_XOUT_H);
dat2 = i2_sj_d(GYRO_XOUT_H+1);
P1 = dat1;
for(i=0;i&100;i++)
DelayMs(10);
P1 = dat2;
for(i=0;i&100;i++)
DelayMs(10);
SendByte(dat1);
SendByte(dat2); }}
【】【】【】【】
上一篇:下一篇:
CopyRight @
单片机教程网 51hei.com , All Rights Reserved1688.com,阿里巴巴打造的全球最大的采购批发平台
1688/淘宝会员(仅限会员名)请在此登录
cbulogin.et2Server is OK基于 STM32 的硬件 I2C 读取 MPU6050 数据
MPU6050其实就是一个 I2C 器件,里面有很多寄存器(但是我们用到的只有几个),我们通过读写寄存器来操作这个。所以首要问题就是
STM32 和 MPU6050 的 I2C 。1、配置 STM32 (用I2C1:PB6——SCL;PB7——SDA)
1)时钟 RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
2)GPIO 配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
//两个引脚都加 4.7K 上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
3)I2C 配置
void I2C_Configuraon(void)
I2C_InitTypeDef
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 =0xc0; //
STM32 的自身地址,不与从器件相同即可
I2C_InitStructure.I2C_Ack = I2C_Ack_E
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}至此,STM32 已配置完毕,其实不是那么难。2、初始化 MPU6050
void MPU6050_Initialize()
//初始化过程 ,其实就是写 5个寄存器
MPU6050_I2C_ByteWrite(0xd0,0x00,MPU6050_RA_PWR_MGMT_1);
// reg107, 唤醒,8M内部时钟源
MPU6050_I2C_ByteWrite(0xd0,0x07,MPU6050_RA_SMPLRT_DIV);
//采用频率 1000
MPU6050_I2C_ByteWrite(0xd0,0x06,MPU6050_RA_CONFIG);
MPU6050_I2C_ByteWrite(0xd0,0x01,MPU6050_RA_ACCEL_CONFIG);
//加速度量程 2g
MPU6050_I2C_ByteWrite(0xd0,0x18,MPU6050_RA_GYRO_CONFIG);
//角速度量程 2000度/s
}注:0xD0 表示 MPU6050 的地址。我们知道 I2C从器件(在此当然是指 MPU6050)有 8 位的地址,前 7 位由 WHO AM I 确定,第 8 位由 AD0 的电平决定。WHO AM I 默认值是 0x68H(1101000B),AD0 接低电平,所以 MPU6050 的 I2C 地址是 0xD0H(B)。3、I2C 核心程序 ( 读/写)1)写入寄存器一次写操作分为几个步骤: 发送开始信号 -& 起始成功?(可能描述的不太准确) -& 发送 MPU6050 地址、状态(写)-& 写地址成功? -& 发送 MPU6050内部某个待写寄存器地址 -& 发送成功? -& 发送要写入的内容 -& 发送成功? -& 发送结束信号总结:先写 MPU6050 地址,再写 寄存器地址,最后写 内容,且每次都要验证(应该和应答信号有关)。这就像寄快递一样,先写市县地址,再写街道地址,最后写门牌号。再看下面的程序就会更容易理解一些。void MPU6050_I2C_ByteWrite(u8 slaveAddr, u8 pBuffer, u8 writeAddr){
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
//发送开始信号
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send MPU6050 address for write */
I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Transmitter);
// 发送 MPU6050 地址、状态(写)
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* Send the MPU6050's internal address to write to */
I2C_SendData(I2C1, writeAddr);
//发送 MPU6050内部某个待写寄存器地址
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* Send the byte to be written */
I2C_SendData(I2C1, pBuffer);
//发送要写入的内容
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* Send STOP condition */
I2C_GenerateSTOP(I2C1, ENABLE);
//发送结束信号}2)读寄存器因为 加速度值和角速度值都在寄存器里,所以必须读它才能获得数据。附上程序如:MPU6050_I2C_BufferRead(0xd0, receive_data, MPU6050_RA_WHO_AM_I, 1);
//读 WHO_AM_I 寄存器的值(0x68)如:
void MPU6050_GetRawAccelGyro(s16* AccelGyro)
//读加速度值 和 角速度值
u8 tmpBuffer[14],i;
MPU6050_I2C_BufferRead(0xd0, tmpBuffer, MPU6050_RA_ACCEL_XOUT_H, 14);
/* Get acceleration */
for(i=0; i&3; i++)
AccelGyro=((s16)((u16)tmpBuffer[2*i] && 8) + tmpBuffer[2*i+1]);
/* Get Angular rate */
for(i=4; i&7; i++)
//在此跳过温度寄存器,不需要温度值
AccelGyro[i-1]=((s16)((u16)tmpBuffer[2*i] && 8) + tmpBuffer[2*i+1]);
}注:#define MPU6050_RA_ACCEL_XOUT_H
0x3B#define MPU6050_RA_ACCEL_XOUT_L
0x3C#define MPU6050_RA_ACCEL_YOUT_H
0x3D#define MPU6050_RA_ACCEL_YOUT_L
0x3E#define MPU6050_RA_ACCEL_ZOUT_H
0x3F#define MPU6050_RA_ACCEL_ZOUT_L
0x40#define MPU6050_RA_TEMP_OUT_H
0x41#define MPU6050_RA_TEMP_OUT_L
0x42#define MPU6050_RA_GYRO_XOUT_H
0x43#define MPU6050_RA_GYRO_XOUT_L
0x44#define MPU6050_RA_GYRO_YOUT_H
0x45#define MPU6050_RA_GYRO_YOUT_L
0x46#define MPU6050_RA_GYRO_ZOUT_H
0x47#define MPU6050_RA_GYRO_ZOUT_L
0x48I2C 读核心程序:void MPU6050_I2C_BufferRead(u8 slaveAddr, u8* pBuffer, u8 readAddr, u16 NumByteToRead){
/* While the bus is busy */
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send MPU6050 address for write */
I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Transmitter);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* Clear EV6 by setting again the PE bit */
I2C_Cmd(I2C1, ENABLE);
/* Send the MPU6050's internal address to write to */
I2C_SendData(I2C1, readAddr);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));/* Send STRAT condition a second time */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send MPU6050 address for read */
I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Receiver);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* While there is data to be read */
while(NumByteToRead)
if(NumByteToRead == 1)
/* Disable Acknowledgement */
I2C_AcknowledgeConfig(I2C1, DISABLE);
/* Send STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
/* Test on EV7 and clear it */
if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
/* Read a byte from the MPU6050 */
*pBuffer = I2C_ReceiveData(I2C1);
/* Point to the next location where the byte read will be saved */
pBuffer++;
/* Decrement the read bytes counter */
NumByteToRead--;
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(I2C1, ENABLE);}最后,把六个值 printf 出来就行。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!同样的I2C程序用24c02能正常通讯,用MPU6050陀螺仪芯片却一直收不到应答信号是为什么?_百度知道
同样的I2C程序用24c02能正常通讯,用MPU6050陀螺仪芯片却一直收不到应答信号是为什么?
问题如题,我写了一个I2C程序,用24c02测试能正常通讯读写,用MPU6050却收不到应答信号,写一个测试程序值找从器件地址都找不到。6050的地址我目前试过0x68和0xD0不过都收不到应答信号。请问这是什么情况?
我有更好的答案
根据你提供的信息, 请按下面的方法逐步排查:1. 确定物理连接SCL/SDA没有问题 (包括引脚接错, 虚焊等), 万用表量一下两个引脚有没有连接. 还有上拉电阻(我记得I2C总线要接上拉电阻)等外部电路有没有问题.2. 检查MPU6050有没有进入工作状态, 电源, 晶振的配置, 各个引脚(特别是CS, VLogic, AD0等)的连接都是处于正确状态.3. 确保MPU6050的地址应该为0x68和0xE8(AD0=0)或者0x69或者0xE9(AD0=1) 规格书9.2节, 33页4. 读写时序有没有在MPU6050的要求范围内, 可以用示波器观察SCL的频率, 上升沿, 下降沿有没有达到MPU6050的规格书要求. 不过你能读24c02, 速度应该没有问题. 保险起见, 用示波器观察一下, 通讯的波形有没有衰减.
采纳率:79%
为您推荐:
其他类似问题
陀螺仪的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 mt6050i通讯 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信