1. 程式人生 > >STM32 模擬I2C (STM32F051)

STM32 模擬I2C (STM32F051)

/**
  ******************************************************************************
  * @file      i2c simu.c
  * @brief     simulation function
  * @CPU       STM32F051
  * @compiler  Keil uVision V4.74
  * @author    MetalSeed
  * @copyright WSHHB
  * @version   V1.0.0
  * @date      18-Sept-2014
  * @modifydate20-Sept-2014
  ******************************************************************************
  * @attention
  */

#include "boardAPI.h"
#include "i2cSimu.h"
#include "delay.h"
#include "uart.h"

GPIO_InitTypeDef        GPIO_InitStructure;  
   
  
/**
  * @brief  IIC Init
  * @param  A:
  * @retval None
  */
void IIC_Init(void)
{					     
	RCC_AHBPeriphClockCmd(	RCC_AHBPeriph_GPIOF, ENABLE );	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;   //ÍÆÍìÊä³ö
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	GPIO_SetBits(GPIOF,GPIO_Pin_6|GPIO_Pin_7); 	//PB10,PB11 Êä³ö¸ß
}

/**
  * @brief  Set SDA Pin as Output Mode
  * @retval None
  */
void SDA_OUT()  
{  
  GPIO_StructInit(&GPIO_InitStructure);  
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;  
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;  
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  GPIO_Init(GPIOF, &GPIO_InitStructure);  
}  

/**
  * @brief  Set SDA Pin as Input Mode
  * @retval None
  */
void SDA_IN()  
{  
  GPIO_StructInit(&GPIO_InitStructure);  
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;  
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;// !!!
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  GPIO_Init(GPIOF, &GPIO_InitStructure);  
} 

/**
  * @brief  read input voltage from SDA pin
  * @retval None
  */
BYTE SDA_READ()
{
  return GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output high form SDA pin
  * @retval None
  */
void IIC_SDA_1()
{
  GPIO_SetBits(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output low form SDA pin
  * @retval None
  */
void IIC_SDA_0()
{
  GPIO_ResetBits(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output high form SCL pin
  * @retval None
  */
void IIC_SCL_1()
{
GPIO_SetBits(GPIOF, GPIO_Pin_6);
}

/**
  * @brief  output LOW form SCL pin
  * @retval None
  */
void IIC_SCL_0()
{
GPIO_ResetBits(GPIOF, GPIO_Pin_6);  
}


/**
* @brief  Simulate IIC conmunication :Create Start signal
  * @retval None
  */
void IIC_Start(void)
{
	SDA_OUT();     //sda output
	IIC_SDA_1();	  	  
	IIC_SCL_1();
	delayus(4);
 	IIC_SDA_0();   //START:when CLK is high,DATA change form high to low 
	delayus(4);
	IIC_SCL_0();   //hold scl line, prepare to transmit data
}	  

/**
  * @brief  Simulate IIC conmunication : Create Stop signal
  * @retval None
  */
void IIC_Stop(void)
{
	SDA_OUT();    //sda output mode 
	IIC_SCL_0();
	IIC_SDA_0();  //STOP:when CLK is high DATA change form low to high
 	delayus(4);
	IIC_SCL_1(); 
	IIC_SDA_1();  //indicate transmit over
	delayus(4);							   	
}

/**
* @brief  Simulate IIC conmunication : wait for target device's ACK
* @retval ACK (0) : receive success
* @retval NACK(1) : receive unsuccess
  */
BYTE IIC_Wait_Ack(void)
{
	BYTE ucErrTime = 0;
	SDA_IN();      //set as input mode
	IIC_SDA_1();
  delayus(1);	   
	IIC_SCL_1();
  delayus(1);	 
	while(SDA_READ())
	{
		ucErrTime++;
		if(ucErrTime > 250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL_0(); //release scl line
	return 0;  
} 

/**
  * @brief  Simulate IIC conmunication : make an ACK
  * @retval None
  */
void IIC_Ack(void)
{
	IIC_SCL_0();
	SDA_OUT();
	IIC_SDA_0();
	delayus(2);
	IIC_SCL_1();
	delayus(2);
	IIC_SCL_0();
}

/**
  * @brief  Simulate IIC conmunication : don't make an ACK
  * @retval None
  */
void IIC_NAck(void)
{
	IIC_SCL_0();
	SDA_OUT();
	IIC_SDA_1();
	delayus(2);
	IIC_SCL_1();
	delayus(2);
	IIC_SCL_0();
}					 				     


/**
  * @brief  Simulate IIC conmunication : Transmit one byte Data
  * @param  txd: data to be transmit
  * @retval None
  */
void IIC_Send_Byte(BYTE txd)
{                        
  BYTE i;   
  SDA_OUT(); 	    
  IIC_SCL_0();//push down scl  to start transmit data
  for(i = 0; i < 8; ++i)
  {              
    if(txd & 0x80)
    {
      IIC_SDA_1();
    }
    else
    {
      IIC_SDA_0();
    }
    txd <<= 1; 	  
    delayus(2);   
    IIC_SCL_1();
    delayus(2); 
    IIC_SCL_0();	
    delayus(2);
  }	 
} 	  

//¶Á1¸ö×Ö½Ú£¬ack=1ʱ£¬·¢ËÍACK£¬ack=0£¬·¢ËÍnACK   
/**
  * @brief  Simulate IIC conmunication : Receive one byte Data
  * @param  ack: Whether transmit ACK
  * @retval the data have been receive
  */
BYTE IIC_Read_Byte(unsigned char ack)
{
	unsigned char i, res = 0;
	SDA_IN();               //SDA input mode
  for(i = 0; i < 8; ++i )
	{
    IIC_SCL_0(); 
    delayus(2);
    IIC_SCL_1();
    res <<= 1;
    if(SDA_READ())
    {
      res++; 
    }      
		delayus(1); 
  }					 
  if (!ack)
  {
    IIC_NAck();//make NACK
  }
  else
  {
    IIC_Ack(); //make ACK
  }
  return res;
}


/*JUST SOME TEST FUNTION DEMO*/
BYTE ReadData()
{				  
	BYTE temp=0;		  	    																 
  IIC_Start();  
	
  IIC_Send_Byte(0x80); 
	IIC_Wait_Ack(); 
  
  IIC_Send_Byte(0xf5); 
	IIC_Wait_Ack();	    
	
  IIC_Start();  	 	   
	IIC_Send_Byte(0XA1); 
	IIC_Wait_Ack();	 
  
  temp=IIC_Read_Byte(0);		   
  IIC_Stop();
	return temp;
}

void WriteData(BYTE DataToWrite)
{				   	  	    																 
  IIC_Start();  
  IIC_Send_Byte(0x80);
  if( IIC_Wait_Ack() == 0)
  {
     printf("Recieve ACK \n");
  }    
  
  IIC_Send_Byte(0xf5);
	IIC_Wait_Ack(); 	 										  		   
	
  IIC_Send_Byte( DataToWrite ); 
	IIC_Wait_Ack();  		    	   
  
  IIC_Stop();
	delayms(10);	 
}