一、MPU6050中的IIC时序

1.1 START和STOP



SDA和SCL在高电平时,SDA拉低表示START。SCL拉低,表示可以传输数据。

SDA和SCL在低电平时,SDA拉高表示STOP。 SCL拉高,表示传输数据结束。

  1. /******************************************
  2. *函数原型: void IIC_Start(void)
  3. *功能: 产生IIC起始信号
  4. ******************************************/
  5. void IIC_Start(void)
  6. {
  7. SDA_OUT();
  8. IIC_SDA=1;
  9. IIC_SCL=1;
  10. delay_us(4);
  11. IIC_SDA=0; //START:when CLK is high,SDA change from hig to low
  12. delay_us(4);
  13. IIC_SCL=0; //Ready Transmit or Receive
  14. }
  15. /******************************************
  16. *函数原型: void IIC_Start(void)
  17. *功能: 产生IIC结束信号
  18. ******************************************/
  19. void IIC_Stop(void)
  20. {
  21. SDA_OUT();
  22. IIC_SDA=0;
  23. IIC_SCL=0;
  24. delay_us(4);
  25. IIC_SDA=1; //STOP:when CLK is low,SDA change from low to high
  26. IIC_SCL=1; //发送I2C总线结束信号
  27. delay_us(4);
  28. }

一些的宏定义:

  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
  2. #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
  3. #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
  4. #define GPIOB_ODR_Addr (GPIOB_BASE+12)
  5. #define GPIOB_IDR_Addr (GPIOB_BASE+8)
  6. #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
  7. #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
  8. //驱动接口,GPIO模拟IIC
  9. //PB7->I2C_SDA
  10. //PB6->I2C_SCL
  11. #define SDA_IN() {GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=0x80000000;} //上拉输入
  12. #define SDA_OUT() {GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=0x30000000;} //通用推挽输出,不用硬件IIC
  13. //IO操作函数
  14. #define IIC_SCL PBout(6)
  15. #define IIC_SDA PBout(7)
  16. #define READ_SDA PBin(7)

1.2 ACK和NACK时序图



在START信号后,读取8位的数据,STM32需要对MPU6050发出响应以同步。

第九个SCL时,SCL从低电平变成高电平后,SDA如果是低电平则是ACK,如果是高电平则是NACK。

  1. /******************************************
  2. *函数原型: void IIC_Wait_Ack(void)
  3. *功能: 等待应答信号到来
  4. *输出; 1,接收应答失败
  5. 0,接收应答成功
  6. ******************************************/
  7. u8 IIC_Wait_Ack(void)
  8. {
  9. u8 ucErrTime = 0;
  10. SDA_IN();
  11. IIC_SDA=1;
  12. delay_us(1);
  13. IIC_SCL=1;
  14. delay_us(1);
  15. while(IIC_SDA) //最多等待50us
  16. {
  17. ucErrTime++;
  18. if(ucErrTime>50)
  19. {
  20. IIC_Stop();
  21. return 1;
  22. }
  23. delay_us(1);
  24. }
  25. IIC_SCL=0; //时钟输出0
  26. return 0;
  27. }
  28. /******************************************
  29. *函数原型: void IIC_Ack(void)
  30. *功能: 产生ACK应答信号SDA=0
  31. ******************************************/
  32. void IIC_Ack(void)
  33. {
  34. IIC_SCL=0;
  35. SDA_OUT();
  36. IIC_SDA=0;
  37. delay_us(1);
  38. IIC_SCL=1;
  39. delay_us(1);
  40. IIC_SCL=0;
  41. }
  42. /******************************************
  43. *函数原型: void IIC_Ack(void)
  44. *功能: 产生ACK应答信号SDA=0
  45. ******************************************/
  46. void IIC_NAck(void)
  47. {
  48. IIC_SCL=0;
  49. SDA_OUT();
  50. IIC_SDA=1;
  51. delay_us(1);
  52. IIC_SCL=1;
  53. delay_us(1);
  54. IIC_SCL=0;
  55. }

1.3 MPU6050写入时序







写时序的步骤:START+(MPU6050地址+W)+等待ACK+寄存器地址+等待ACK+写入的数据+等待ACK+STOP。

读时序的步骤:START+(MPU6050地址+W)+等待ACK+寄存器地址+START+读取数据+ACK响应+STOP。

  1. /****************************************************
  2. *函数原型: u8 IICwriteBytes(u8 dev, u8 reg, u8 length, u8 *data)
  3. *功能: 将多个字节写入指定设备 指定寄存器
  4. *输入: dev 目标设备地址
  5. * reg 寄存器地址
  6. * length 要写的字节数
  7. * *data 将要写的数据的首地址
  8. *返回: 返回是否成功,1成功
  9. ****************************************************/
  10. u8 IICwriteBytes(u8 dev, u8 reg, u8 length, u8 *data)
  11. {
  12. u8 count = 0;
  13. IIC_Start();
  14. IIC_Send_Byte(dev); //发送写命令
  15. IIC_Wait_Ack();
  16. IIC_Send_Byte(reg); //发送写入的地址
  17. IIC_Wait_Ack();
  18. for(count=0;count<length;count++)
  19. {
  20. IIC_Send_Byte(data[count]);
  21. IIC_Wait_Ack();
  22. }
  23. IIC_Stop(); //发送停止信号
  24. return 1;
  25. }
  26. /******************************************
  27. *函数原型: u8 IIC_Read_Byte(unsigned char ack)
  28. *功能: 读取一个Byte的字节
  29. *输入: 读取一个字节,ack=1,发送ACK,ack=0,发送nACK
  30. *返回: 读取到的Byte
  31. ******************************************/
  32. u8 IIC_Read_Byte(unsigned char ack)
  33. {
  34. unsigned char i, receive = 0;
  35. SDA_IN(); //设置为输入
  36. for(i=0;i<8;i++)
  37. {
  38. IIC_SCL=0;
  39. delay_us(1);
  40. IIC_SCL=1;
  41. receive<<=1;
  42. if(READ_SDA) receive++;
  43. delay_us(1);
  44. }
  45. if(ack)
  46. IIC_Ack(); //发送ACK
  47. else
  48. IIC_NAck(); //发送NACK
  49. return receive;
  50. }

留下了一个不太清楚的内容,按位,位长度写数据:

  1. /****************************************************
  2. *函数原型: u8 IICwriteBits(u8 dev, u8 reg, u8 bitStart, u8 length, u8 data)
  3. *功能: 读、修改、写指定设备、指定寄存器一个字节中的多个位
  4. *输入: dev 目标设备地址
  5. * reg 寄存器地址
  6. * bitStart 目标字节的起始位,自左向右?
  7. * length 位长度
  8. * data 存放改变目标字节位的值
  9. *返回: 返回是否成功,1成功
  10. ****************************************************/
  11. u8 IICwriteBits(u8 dev, u8 reg, u8 bitStart, u8 length, u8 data)
  12. {
  13. u8 b;
  14. u8 mask;
  15. if(IICreadByte(dev, reg, &b) != 0)
  16. {
  17. mask = (0xFF << (bitStart +1))| 0xFF >> ((8 - bitStart) + length -1);
  18. data >>= (7 - bitStart);
  19. b &= mask;
  20. b |= data;
  21. return IICwriteByte(dev, reg, b);
  22. } else {
  23. return 0;
  24. }
  25. }

GPIO软件模拟IIC时序的更多相关文章

  1. stm32软件模拟IIC读取PX4FLOW光流传感器数据

    这段时间在做全国光电设计大赛,用到了px4的px4flow光流传感器,用软件模拟iic读取数据不定期会导致px4flow死机,查了资料和光流的源码,发现这个光流用了stm32的硬件iic,所以对软件模 ...

  2. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

     版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...

  3. STM32 软件模拟 IIC 代码,标准库、HAL库可用

    #ifndef _IIC_H #define _IIC_H #include "stdio.h" #include "stm32f1xx_hal.h" /* 定 ...

  4. 使用软件模拟spi 时序时注意点

    软件模拟 spi 时序有以下几个点需要注意: cs 使能后到第一个 sck 边沿需要延时. 最后一个sck 边沿到下一个 cs 需要延时. sck 的高电平和低电平本身需要维持时间. mosi 需要先 ...

  5. GPIO软件模拟I2C

    /***************************************************************************** * * Filename: * ----- ...

  6. 51单片机下实现软件模拟IIC通信

    1.IIC协议简易概述 IIC全称Inter-Integrated Circuit (集成电路总线),是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备.IIC属于半双 ...

  7. 软件模拟IIC实现EEPROM

    ....妈的太难.    反正就是控制引脚的高低电平 实现数据的读取....参考 I2C的协议层和物理层的那个几个图,个个信号产生的电平 自己看源码去把. 头疼

  8. C51—模拟IIC总线实现EEPROM存取数据

    a - 什么是IIC总线 -什么是EEPROM -IIC总线的通信格式 模块化设计注解 整体代码 - 什么是IIC总线 IIC总线是同步通信的一种特殊形式,具有接线口少.控制简单.器件封装形式小.通信 ...

  9. GPIO模拟IIC接口信号质量分析

    信号质量有问题的波形001: 信号质量有问题的波形002: 从上图可以看出,GPIO口模拟的I2C接口,电平都存在半高的情况. 因为I2C的接口是通过GPIO模拟实现的,该时钟信号线SCL内部默认为下 ...

随机推荐

  1. commons-fileupload-1.2.1.jar 插件上传与下载

    1:首先在页面上写个文本域: <%@ page language="java" import="java.util.*" pageEncoding=&qu ...

  2. python中join()函数的用法

    join()函数 语法:  'sep'.join(s) 参数说明 sep:分隔符.可以为空 s:要连接的元素序列.字符串.元组.字典 上面的语法即:以sep作为分隔符,将s所有的元素合并成一个新的字符 ...

  3. SQL:REGEXP

    作为一个更为复杂的示例,正则表达式B[an]*s匹配下述字符串中的任何一个:Bananas,Baaaaas,Bs,以及以B开始.以s结束.并在其中包含任意数目a或n字符的任何其他字符串. 以下是可用于 ...

  4. CSS-美化checkbox

    注意:css3 的用: checked 伪类选择器会去检查元素属性(`input[checked]`),而不是 dom 节点上的属性( ``).所以要使用 jquery 的 prop 而非 attr ...

  5. 关于css3 Animation动画

    在介绍animation之前有必要先来了解一个东西,那就是“keyframes”,我们把他叫做“关键帧”: 在使用transition制作一个简单的transition效果时,包括了初始属性,最终属性 ...

  6. linux svn 服务器搭建问题

    我的svn版本 svn, version 1.7.14 (r1542130) compiled Nov 20 2015, 19:25:09 Copyright (C) 2013 The Apache ...

  7. 在使用bat 批处理 时将运行结果显示并保存到文件中 echo

    实现原理: 因为要输出到文本,所以可以使用call将结果输出到临时文件,完成之后做3件事: 1. 将临时文本内容显示,实现窗口显示的本次运行结果的功能,可先清屏. 2. 将临时文本内容追加到日志文件用 ...

  8. Java迭代器模式

    迭代器模式是Java和.Net编程环境中非常常用的设计模式.此模式用于以顺序方式访问集合对象的元素,而不需要知道其底层表示. 迭代器模式属于行为模式类别. 实现实例 在这个实例中,将创建一个Itera ...

  9. 转 LoadRunner错误处理函数

    在脚本的Run-time Settings中,可以设置在脚本运行过程中发生错误的处理方式.进入到Run-time Settings中,切换到Miscellaneous标签页,可以看到Error Han ...

  10. (4.10)sql server导入导出

    SQL Server快速导入数据分享 核心参考:官网~~https://docs.microsoft.com/zh-cn/sql/relational-databases/import-export/ ...