STM32之模擬I2C通信驅動代碼

/******************************************************************************

  • Name: i2c.c
  • Description: I2C communication function
  • Project: ****
  • Auther: ZW
  • MCU: STM32F103RET6
  • Comment:
    ******************************************************************************/
#include "i2c.h"

#define SCL_H		  (GPIOB->BSRR = GPIO_Pin_6)
#define SCL_L		  (GPIOB->BRR = GPIO_Pin_6)
#define SDA_H		  (GPIOB->BSRR = GPIO_Pin_7)
#define SDA_L		  (GPIOB->BRR = GPIO_Pin_7)
#define SCL_READ	(GPIOB->IDR & GPIO_Pin_6)
#define SDA_READ	(GPIOB->IDR & GPIO_Pin_7)
#define I2C_DELAY	(I2C_delay())

void i2c_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_delay(void)  
{     
	uint8_t i = 7;   

	while(i)   
	{      
		i--;   
	}
}

bool I2C_Start(void)  
{
	SDA_H;
	SCL_H;
	I2C_DELAY;
	if(!SDA_READ)  
	return false;
	
	SDA_L;
	I2C_DELAY;  
	if(SDA_READ)   
	return false;
	
	SDA_L;
	I2C_DELAY;
	return true;  
}  
void I2C_Stop(void)
{
	SCL_L;
	I2C_DELAY;
	SDA_L;
	I2C_DELAY;
	SCL_H;
	I2C_DELAY;
	SDA_H;
	I2C_DELAY;
}

void I2C_Ack(void)  
{     
	SCL_L;
	I2C_DELAY;  
	SDA_L;
	I2C_DELAY;  
	SCL_H;
	I2C_DELAY;  
	SCL_L;
	I2C_DELAY;  
}  

void I2C_NoAck(void)  
{     
	SCL_L;
	I2C_DELAY;  
	SDA_H;
	I2C_DELAY;  
	SCL_H;
	I2C_DELAY;  
	SCL_L;
	I2C_DELAY;  
}  

bool I2C_WaitAck(void)     
{  
	SCL_L;
	I2C_DELAY;  
	SDA_H;
	I2C_DELAY;  
	SCL_H;
	I2C_DELAY;  
	if(SDA_READ)  
	{  
		SCL_L;
		return false;  
	}  
	SCL_L;
	
	return true;  
}  

void I2C_SendByte(uint8_t SendByte)   
{  
	uint8_t 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;
}  
uint8_t I2C_ReceiveByte(void)    
{   
	uint8_t i = 8;  
	uint8_t 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;  
}

int8_t i2cWrite(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
	int i;
	
	if(!I2C_Start())
		return -1;

	I2C_SendByte(addr << 1 | 0x00);
	if(!I2C_WaitAck()) 
	{
		I2C_Stop();
		return -1;
	}
	
	I2C_SendByte(reg);
	I2C_WaitAck();
	
	for(i = 0; i < len; i++) 
	{
		I2C_SendByte(buf[i]);
		if(!I2C_WaitAck()) 
		{
			I2C_Stop();
			return -1;
		}
	}
	
	I2C_Stop();
	
	return 0;
}

int8_t i2cRead(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
	if(!I2C_Start())
		return -1;

	I2C_SendByte(addr << 1 | 0x00);
	if(!I2C_WaitAck()) 
	{
		I2C_Stop();
		return -1;
	}
	
	I2C_SendByte(reg);
	I2C_WaitAck();
	
	I2C_Start();
	I2C_SendByte(addr << 1 | 0x01);
	I2C_WaitAck();

	while(len) 
	{
		*buf = I2C_ReceiveByte();
		if(len == 1)
			I2C_NoAck();
		else
			I2C_Ack();

		buf++;
		len--;
	}
	I2C_Stop();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章