STM32之CubeMX学习笔记(8)软件IIC简述--驱动MPU6050


IIC简述

网上大神的IIC的优质文章不少,大家可以参考他们的对IIC原理的详细解释,这里就简述一下。

IIC通讯协议是由飞利浦公司在1982年开发的,比摩托罗拉的SPI通讯协议还要稍微早一点。1960年,他们两个的祖先Usart/Uart就被创造出来了,但串口通信不适合芯片与芯片间大规模通信,它更多地是用在工业领域,抛开这位老古董不谈,结合我之前写过的SPI文章,我们来看看这两个稍微复杂一点点的芯间通信。

SPI不规定最大传输速率,没有地址方案;SPI也没规定通信应答机制,没有规定流控制规则。事实上,SPI主设备甚至并不知道指定的从设备是否存在。这些通信控制都得通过SPI协议以外自行实现。例如,要用SPI连接一支“命令-响应控制型”解码芯片,则必须在SPI的基础上实现更高级的通信协议(摘自知乎)。归纳来说,SPI的简单自由使其速率不受限制,更多的通讯线也使其可以全双工。而如果需要一个比较严格的通讯协议,来判断从机是否在接收(回应信号ACK),或者只有两个引脚,但是又要接非常多的设备组成总线。这是就需要iic了,但是由于iic在设计的时候对设备的要求比较低,甚至总线需要上拉电阻,来保证驱动力不足的芯片也可以照常通信,总线拉高全靠上拉电阻,所以其速度注定被这个上拉电阻所限制。上拉电阻太小,能耗就会比较高,上拉电阻太大,总线重新拉高的时间就会被延长。当然后续IIC也有对硬件进行提升的方案,最高也能保证IIC运行在Mbps以上的速率。但由于软件上的限制,依然会比SPI要更慢。

软件iic通讯

使用的例子是通信mpu6050。mpu6050是一款六轴陀螺仪,使用IIC与其通信读取数据。

当不接6050时,当呼叫其地址0x68并未受到应答时,后面的数据就不会再继续发送了。

在这里插入图片描述

当接上6050,可以发现在0x68后有一个“1”的ACK信号,但是很快又被拉低了,并开始数据位传输。
在这里插入图片描述

连续写

来看一下IIC和一个设备通信的过程,下面是MPU连续写的代码,也生成了上图的波形。

//IIC连续写
uint8_t MPU_Write_Len(uint8_t addr, uint8_t reg,uint8_t len,uint8_t *buf)
{
    uint8_t i;
    IIC_Start();
    IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
    if(IIC_Wait_Ack())           //等待应答
    {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);         //写寄存器地址
    IIC_Wait_Ack();                //等待应答
    for(i=0;i<len;i++)
    {
        IIC_Send_Byte(buf[i]);  //发送数据
        if(IIC_Wait_Ack())         //等待ACK
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_Stop();
    return 0;
}

可以总结为两条工作线,一条是IIC发送多个数据,开始-发送7位设备地址和写命令-发送寄存器地址-发送len长的字节-结束。

void IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
	  SDA_OUT(); 	    
    IIC_SCL=0;
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		for(int i=0;i<65;i++){__NOP();}  
		IIC_SCL=1;
		for(int i=0;i<65;i++){__NOP();} 
		IIC_SCL=0;	
		for(int i=0;i<65;i++){__NOP();}
    }	 
} 

另一条是每当发送一个8位数据后,总是要等待Ack回应,才进行下一步,不然就直接Stop。

/******************************************************************************
*                         u8 IIC_Wait_Ack(void)
*
*Description : 等待应答信号到来 
*Arguments   : none
*Returns     : 1:接收应答失败    0:接收应答成功
*Notes       : none
*******************************************************************************
*/
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_IN();      
	IIC_SDA=1;for(int i=0;i<30;i++){__NOP();}   
	IIC_SCL=1;for(int i=0;i<30;i++){__NOP();}	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>50)
		{
			IIC_Stop();
			return 1;
		}
//	  Delay_IIC(1);
	}
	IIC_SCL=0;   
	return 0;  
}  

连续读

当读取数据的时候,也需要主机先发送7位的从机地址和读取命令,再发送寄存器地址。随后从机才会根据要求,向主机发送该寄存器地址的数据。

uint8_t MPU_Read_Len(uint8_t addr, uint8_t reg,uint8_t len,uint8_t *buf)
{ 
  IIC_Start();
  IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
  if(IIC_Wait_Ack())          //等待应答
  {
      IIC_Stop();
      return 1;
  }
  IIC_Send_Byte(reg);         //写寄存器地址
  IIC_Wait_Ack();             //等待应答
	IIC_Start();                
  IIC_Send_Byte((addr<<1)|1); //发送器件地址+读命令
  IIC_Wait_Ack();             //等待应答
  while(len)
  {
      if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送nACK 
	else *buf=IIC_Read_Byte(1);		//读数据,发送ACK  
	len--;
	buf++;  
  }
  IIC_Stop();                 //产生一个停止条件
  return 0;  
}

在这里插入图片描述

这样的通讯协议其实也严格规定了在总线上的主从设备关系,需要合理规划才能保证全双工工作,但是由于只需要两个线,在这两根线上可以约定商量的功能非常多,所以被很多工程师称为“最优雅的通讯方式”,可谓是“双线优雅,永不过时”。

总结

由于最近时间安排紧张,这个系列花不了太多时间了,硬件IIC和软件IIC的对比测试可能只能作为番外出了。2023是AI新时代元年,中国的嵌入式行业也重新火热起来了,祝诸君学业兴隆,工作顺利。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值