15回答

1收藏

[分享] GD32空中飞鼠 之 硬件I2C读MPU6050

 

GD32 GD32 13025 人阅读 | 15 人回复 | 2015-07-19

硬件I2C读MPU6050


拿到小红板研究了一段时间,我的方案是做空中飞鼠的实验,那就要使用MPU6050来读取重取X和Y轴的重力加速度,MPU6050模块提供I2C通讯接口。I2C在STM32F1系列MCU上硬件使用上有诸多的问题,所以很多人都使用软件I2C。大家都知道GD32系列MCU是“山寨”STM32,所以可能也会存在同要的问题。但是我想即便是GD32“山寨”STM32,也可能是硬件寄存器和寄存器地址和STM32定义的一样,是为了大家从STM32更容易过渡到GD32上来做开发(这是不是在偷STM32的普及成果!),其硬件实现肯定是不一样的。既然硬件实现不一样,那GD32的硬件I2C就可能比STM32要好用。好了废话不多说,开始吧。


我们使用GD32的I2C1来读MPU6050,查下数据手册pin定义:



PB8,PB9复用I2C1的SCL,SDA
原理图上PB8,PB9在CN5上引出



实际接线图:



为了调试I2C,使用logic8来分析I2C的波形。



花了好几天时间终于调试通过。其实很简单,使用起来了很方便,只是GD没有I2C的例子,走了不少的弯路。特分享给大家,希望对其它人有用,代码我就只贴关键代码,明白人应该一看就知道了。

  1. //配置I2C
  2. void I2cConfig(void)
  3. {
  4.         GPIO_InitPara GPIO_InitStructure;
  5.         I2C_InitPara I2C_InitStructure;
  6.         
  7.         RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB,ENABLE);
  8.         RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_I2C1,ENABLE);
  9.         
  10.         GPIO_DeInit(GPIOB);
  11.         /* Connect pin to Periph */
  12.         GPIO_PinAFConfig(GPIOB,GPIO_PINSOURCE8,GPIO_AF_1);
  13.         GPIO_PinAFConfig(GPIOB,GPIO_PINSOURCE9,GPIO_AF_1);
  14.         
  15.         /* Configure pins as AF pushpull */
  16.         GPIO_InitStructure.GPIO_Pin     = SCL|SDA;
  17.         GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_AF;
  18.         GPIO_InitStructure.GPIO_Speed   = GPIO_SPEED_50MHZ;
  19.         GPIO_InitStructure.GPIO_OType   = GPIO_OTYPE_PP;
  20.         GPIO_InitStructure.GPIO_PuPd    = GPIO_PUPD_PULLUP;
  21.         GPIO_Init( GPIOB , &GPIO_InitStructure);

  22.         I2C_DeInit(I2C1);
  23.         I2C_InitStructure.I2C_AddressingMode = I2C_ADDRESSING_MODE_7BIT;
  24.         I2C_InitStructure.I2C_BitRate = 100000;
  25.         I2C_InitStructure.I2C_DeviceAddress = 0x08;
  26.         I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE_2;
  27.         I2C_InitStructure.I2C_Protocol = I2C_PROTOCOL_I2C;
  28.         I2C_Init(I2C1,&I2C_InitStructure);
  29.         I2C_Enable(I2C1,ENABLE);
  30. }
复制代码
上面的代码是配置I2C,不用太多的解释。下面的就是关键代码了
  1. //**************************************
  2. //向I2C设备写入一个字节数据
  3. //**************************************
  4. void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data)
  5. {
  6.         I2C_StartOnBus_Enable(I2C1,ENABLE);
  7.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_SBSEND) == ERROR);//不能用I2C_GetBitState(I2C1,I2C_FLAG_SBSEND)
  8.         
  9.         //发送从设备地址到i2c总线上
  10.         //I2C_AddressingDevice_7bit(I2C1,0xD0,I2C_DIRECTION_TRANSMITTER);
  11.         I2C_SendData(I2C1,SlaveAddress);
  12.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_TRANSMITTER_ADDSEND) == ERROR);

  13.         I2C_SendData(I2C1,REG_Address);
  14.         I2C_SendData(I2C1,REG_data);
  15.         
  16.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTED) == ERROR);
  17.         //while(!I2C_GetBitState(I2C1,I2C_FLAG_BTC));
  18.         I2C_StopOnBus_Enable(I2C1,ENABLE);
  19. }
  20. //**************************************
  21. //从I2C设备读取一个字节数据
  22. //**************************************
  23. uint8_t Single_ReadI2C(uint8_t REG_Address)
  24. {
  25.         uint8_t data;
  26.         //起始信号
  27.         I2C_StartOnBus_Enable(I2C1,ENABLE);
  28.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_SBSEND) == ERROR);
  29.         
  30.         //发送从设备地址到i2c总线上
  31.         I2C_AddressingDevice_7bit(I2C1,SlaveAddress,I2C_DIRECTION_TRANSMITTER);
  32.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_TRANSMITTER_ADDSEND) == ERROR);
  33.         //发送读地址
  34.         I2C_SendData(I2C1,REG_Address);
  35.         
  36.         //再次发送起始信号
  37.         I2C_StartOnBus_Enable(I2C1,ENABLE);
  38.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_SBSEND) == ERROR);
  39.         //发送读设备信号
  40.         I2C_SendData(I2C1,SlaveAddress+1);
  41.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_RECEIVER_ADDSEND) == ERROR);
  42.         
  43.         while(I2C_StateDetect(I2C1,I2C_PROGRAMMINGMODE_MASTER_BYTE_RECEIVED) == ERROR);
  44.         data = I2C_ReceiveData(I2C1);
  45.         
  46.         I2C_StopOnBus_Enable(I2C1,ENABLE);
  47.         return data;
  48. }
复制代码
刚开始的时候一切安照参考手册上的I2C通讯流程,但总线状态我一直使用I2C_GetBitState来取I2C总线状态,i2c总线上始终只出现一次数据,再写数据已经没有任何反应了,调试了好几天都一样,把参考手册i2c通讯流程都看了好几遍,最后把gd32f1x0_i2c.c文件打开,一个函数一个函数细细看下。看到I2C_StateDetect这个函数,而且注释上有@brief  Detect I2Cx State Machine.想想以前在新唐上的I2C就是用状态机检测,就试试这个来检测状态,大功告成。太坑爹了,在这里真希望官为真的应该出一本函数手册,配以用例,让俺们也少走些变路。。。





点评

推荐大家一个靠谱的论文检测平台。重复的部分有详细出处以及具体修改意见,能直接在文章上做修改,全部改完一键下载就搞定了。他们现在正在...  发表于 2020-5-3 19:21
喜欢在构思妙想,电子产品DIY是工作,也是一种爱好。
分享到:
回复

使用道具 举报

回答|共 15 个

倒序浏览

沙发

若云流风

发表于 2015-7-20 00:02:48 | 只看该作者

我软件模拟的i2c昨天也刚刚调通了。。。。
板凳

奋斗哥

发表于 2015-7-20 08:32:09 | 只看该作者

多谢楼主分享,非常不错 技术贴
地板

自由人-379179

发表于 2015-7-20 09:14:08 | 只看该作者

收藏了  看转到日照传感器上面是什么效果 ,我原来用的是模拟方式实现
5#

魅影迷踪

发表于 2015-7-20 09:39:01 | 只看该作者

不错不错啊,支持
6#

魅影迷踪

发表于 2015-7-20 10:51:37 | 只看该作者

没有这个传感器啊
7#

党国特派员

发表于 2015-7-20 11:12:26 | 只看该作者

魅影迷踪 发表于 2015-7-20 10:51
没有这个传感器啊

只要有I2C的设备,不一定非要用这个传感 器。

喜欢在构思妙想,电子产品DIY是工作,也是一种爱好。
8#

与非朋

发表于 2015-7-20 15:09:48 | 只看该作者

不错!!!支持 楼主我希望看到获得的MPU6050的数据 我也在搞 数据老是不正确
9#

魅影迷踪

发表于 2015-7-21 08:51:23 | 只看该作者

关键是啥都没有
10#

motodefy

发表于 2015-7-21 08:57:44 | 只看该作者

支持下,我也在调i2c,太蛋疼了
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条