各总线协议汇总(一)- IIC

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33194301/article/details/87907761

由于学习需要,我总结一下各种通讯协议,方便自己也方便各位朋友。

通讯协议概念:通讯协议又称通信规程,是指通信双方对数据传送控制的一种约定。约定中包括对数据格式,同步方式,传送速度,传送步骤,检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守,它也叫做链路控制规程

一、IIC(Inter-Integrated Circuit)

IIC有两种实现方式:模拟IIC硬件IIC
模拟IIC优点是可以任意选择SDA和SCL,不受管脚限制而比较灵活。它的缺点是不可用DMA,所以不用这功能的时候还是很方便的。
硬件IIC优点是可用DMA减轻CPU负担,速度也比模拟IIC快,但是实际调试时可能会出现BUG(死机)。

感兴趣的话可以看一下 血的经历告诉大家,慎用stm32的硬件iic

说明一下 SDA:双向数据线 SCL:时钟线 (IIC是所有总线协议里面用最少引脚的)

一般100K的通信速率,SCL,SDA都是加4.7K的上拉电阻。通信速率越大,电阻建议越小,这个也跟电路板的分布电容有关。

IIC时序图

(一)模拟IIC

#define uchar   unsigned char
#define uint    unsigned int	

#define SCL_H  GPIO_SetBits(GPIOA, GPIO_Pin_6)
#define SCL_L   GPIO_ResetBits(GPIOA, GPIO_Pin_6)
#define SDA_H   GPIO_SetBits(GPIOA, GPIO_Pin_7)
#define SDA_L   GPIO_ResetBits(GPIOA, GPIO_Pin_7)

#define SCL_read GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
#define SDA_read GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)
		 
/***************************************************************
*	FunctionName:	I2C_delay
*	Function:		DELAY
*	Arguments:		None
*	Return:			None
*	Author			seanOY
****************************************************************/         
void I2C_delay(void)
{	
   uchar i=10;     //可以通过修改i的值提升IIC运行速度
   while(i) 
     i--; 
}

void delayms(void)
{	
   int i=10000;  		//延时一定要够,不然会出BUG
   while(i--); 
}       

/****************************************************************
*	FunctionName:	I2C_GPIO_Config
*	Function:		Configure IIC GPIO
*	Arguments:		None
*	Return:			None
*	Author			seanOY
*****************************************************************/
void I2C_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure; 
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/***************************************************************
*	FunctionName:  I2C_Start
*	Function:     Start Simulate IIC Communication
*	Arguments:    None
*	Return:      bool flag
*	Author:      seanOY
****************************************************************/   
bool I2C_Start(void)
{
	SDA_H;
	SCL_H;
	I2C_delay();
	if(!SDA_read)return false;	//SDA线为低电平则总线忙,退出
	SDA_L;
	I2C_delay();
	if(SDA_read) return false;	//SDA线为高电平则总线出错,退出
	SDA_L;
	I2C_delay();
	return true;
}

/******************************************************************
*	FunctionName:  I2C_Stop
*	Function:     Stop Simulate IIC Communication
*	Arguments:    None
*	Return:      None
*	Author:      seanOY
******************************************************************/   
void I2C_Stop(void)
{
	SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SDA_H;
	I2C_delay();
} 

/*******************************************************************
*	FunctionName:  I2C_Ack
*	Function:     Send Acknowledgement signal
*	Arguments:    None
*	Return:      None
*	Author:      seanOY
********************************************************************/  
void I2C_Ack(void)
{	
	SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
}   

/********************************************************************
*	FunctionName:  I2C_NoAck
*	Function:     Send Not Acknowledgement signal
*	Arguments:    None
*	Return:      None
*	Author:      seanOY
********************************************************************/  
void I2C_NoAck(void)
{	
	SCL_L;
	I2C_delay();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
} 

/**************************************************************************
*	FunctionName:  I2C_WaitAck
*	Function:     Wait for Acknowledgement signal from slave
*	Arguments:    None
*	Return:      bool flag
*	Author:      seanOY
***************************************************************************/  
bool I2C_WaitAck(void) 	 //返回为:=1有ACK,=0无ACK
{
	SCL_L;
	I2C_delay();
	SDA_H;			
	I2C_delay();
	SCL_H;
	I2C_delay();
	if(SDA_read)
	{
     SCL_L;
	  I2C_delay();
      return false;
	}
	SCL_L;
	I2C_delay();
	return true;
}

/**************************************************************************
*	FunctionName:  I2C_SendByte
*	Function:     Send a Byte to Slave
*	Arguments:    None
*	Return:      None
*	Author:      seanOY
***************************************************************************/  
void I2C_SendByte(u8 SendByte) //数据从高位到低位
{
    u8 i=8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
      if(SendByte&0x80) //取最高位
        SDA_H;  
      else 
        SDA_L;   
        SendByte<<=1;//下一位
        I2C_delay();
		SCL_H;
        I2C_delay();
    }
    SCL_L;
}  


/**************************************************************************
*	FunctionName:  I2C_RadeByte
*	Function:     Receive a Byte from Slave
*	Arguments:    None
*	Return:      unsigned char Data
*	Author:      seanOY
***************************************************************************/  
unsigned char I2C_RadeByte(void)  //数据从高位到低位//
{ 
    u8 i=8;
    u8 ReceiveByte=0;

    SDA_H;				
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      I2C_delay();
	  SCL_H;
      I2C_delay();	
      if(SDA_read)
      {
        ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}      

/**************************************************************************
*	FunctionName:  Single_Write
*	Function:     Write a Byte to an address
*	Arguments:    None
*	Return:      bool flag
*	Author:      seanOY
***************************************************************************/  
bool Single_Write(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char REG_data)		    
{
    if(!I2C_Start())return false;
    I2C_SendByte(SlaveAddress);   
    if(!I2C_WaitAck()){I2C_Stop(); return false;}
    I2C_SendByte(REG_Address );   //设置低起始地址      
    I2C_WaitAck();	
    I2C_SendByte(REG_data);
    I2C_WaitAck();   
    I2C_Stop(); 
    delayms();
    return true;
}

/**************************************************************************
*	FunctionName:  Single_Read
*	Function:     Read a Byte from an address
*	Arguments:    None
*	Return:      unsigned char Data 
*	Author:      seanOY
***************************************************************************/  
unsigned char Single_Read(unsigned char SlaveAddress,unsigned char REG_Address)
{   unsigned char REG_data;     	
    if(!I2C_Start())return false;
    I2C_SendByte(SlaveAddress); 
    if(!I2C_WaitAck()){I2C_Stop();test=1; return false;}
    I2C_SendByte((u8) REG_Address);   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(SlaveAddress+1);
    I2C_WaitAck();
    REG_data= I2C_RadeByte();
    I2C_NoAck();
    I2C_Stop();
    return REG_data;
}						      

/**************************************************************************
*	FunctionName:  WriteNByte
*	Function:     Write N Bytes to an address range
*	Arguments:    SlaveAddress:   salve address
             REG_Address:      register address(write/read)
            data[]:                data that ready for write
             NumOfByte:         length of data[]
*	Return:      None
*	Author:      seanOY
***************************************************************************/  
void WriteNByte(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char data[], unsigned char NumOfByte)
{
	uchar i ;
	for(i=0;i<NumOfByte;i++)
	{
		Single_Write(SlaveAddress, REG_Address+i, data[i]);
//		printf("%d ,",data[i]);
	}
}

/**************************************************************************
*	FunctionName:  ReadNByte
*	Function:     Read N Bytes from an address range
*	Arguments:    SlaveAddress:   salve address
             REG_Address:      register address(write/read)
            data[]:                data that ready for write
            NumOfByte:         length of data[]
*	Return:      None
*	Author:      seanOY
***************************************************************************/  
void ReadNByte(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char *data, unsigned char NumOfByte)
{
	int i ;
	for(i=0;i<NumOfByte;i++)
	{
		*(data+i)=Single_Read(SlaveAddress, REG_Address+i);
		delayms();      //大概0.7ms,如果出错稍微加大应该可以
//		printf("%d ,",*(data+i));
	}
}

(二)硬件IIC

ST的STM32F10XX的硬件各种总线协议汇总(IIC)(一)IIC库(可下载)

我根据上面ST的库来修改了一下,所以也可下载我修改过的程序(来支持我)哦!^0^(由于篇幅较长,我将它放到下载了)
硬件IIC可通过选择轮询(Polling),中断(Interrupt)或直接存储器存取(DMA)来进行操作,用的时候可以自行选择!

Polling Interrupt DMA
优点 简易,可改变轮询顺序 省时(相对于polling) 用于高速设备,省时(相对于polling)
缺点 由于速度上CPU>>IO设备,不适合用于高速设备 需要有中断信号和中断服务进程 需要有DMA控制器

猜你喜欢

转载自blog.csdn.net/qq_33194301/article/details/87907761