⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 这是mcs51下的i2c实现
💻 C
字号:
#include <reg52.h>
#include <intrins.h>
#include "sysdef.h"
#include "i2c.h"

/*
***************************************************************************************************
*
* I2C BUS: BEGIN
*
***************************************************************************************************
*/
#define set_sda(x)		(I2C_SDA=x)
#define set_scl(x)		(I2C_SCL=x)
#define get_sda()			(I2C_SDA)

static void i2c_delay(UINT16 us)
{
	while(us--);
}

static void i2c_start(I2C_CONFIG *pConfig)
{
	i2c_delay(pConfig->tBUF);	//Release I2C bus
	set_sda(1);
	i2c_delay(pConfig->tR);
	set_scl(1);
	i2c_delay(pConfig->tR + pConfig->tSU_STA);
	set_sda(0);
	i2c_delay(pConfig->tF + pConfig->tHD_STA);
	set_scl(0);
	i2c_delay(pConfig->tF);
}

static void i2c_stop(I2C_CONFIG *pConfig)
{
	set_sda(0);
	i2c_delay(pConfig->tF);
	set_scl(1);
	i2c_delay(pConfig->tR + pConfig->tSU_STO);
	set_sda(1);
	i2c_delay(pConfig->tR);
}

static BOOL i2c_putc(I2C_CONFIG *pConfig, UINT8 value)
{
	UINT8 i;
	UINT8 mask = 0x80;
	UINT8 retry = 0;
	BOOL bAck;

	//Transfer a byte data(MSB)
	for(i = 0; i < 8; i++){
		i2c_delay(pConfig->tLOW);
		if(value & mask){
			set_sda(1);
		}else{
			set_sda(0);
		}
		i2c_delay(pConfig->tSU_DAT);
		set_scl(1);
		i2c_delay(pConfig->tR + pConfig->tHIGH);
		set_scl(0);
		i2c_delay(pConfig->tF + pConfig->tHD_DAT);
		mask >>= 1;
	}

	//Receive the ACK bit
	i2c_delay(pConfig->tLOW);
	set_sda(1);
	i2c_delay(pConfig->tR + pConfig->tSU_DAT);
	set_scl(1);
	i2c_delay(pConfig->tR);
	
	bAck = FALSE;	//NACK
	retry = 0;
	do{
		i2c_delay(pConfig->tACK);
		if(!get_sda()){
			bAck = TRUE;	//ACK
			break;
		}
	}while(++retry < 5);
	set_scl(0);
	i2c_delay(pConfig->tF + pConfig->tLOW);

	return bAck;
}

static UINT8 i2c_getc(I2C_CONFIG *pConfig, BOOL bAck)
{
	UINT8 i;
	UINT8 value = 0;
	UINT8 mask = 0x80;

	//Receive a byte data(MSB)
	for(i = 0; i < 8; i++){
		i2c_delay(pConfig->tLOW);
		set_scl(1);
		i2c_delay(pConfig->tR + pConfig->tHIGH);
		if(get_sda()){
			value |= mask;
		}
		set_scl(0);
		i2c_delay(pConfig->tF + pConfig->tHD_DAT);
		mask >>= 1;
	}

	//Transfer the ACK bit or not
	i2c_delay(pConfig->tLOW);
	if(bAck){
		set_sda(0);	//ACK
	}else{
		set_sda(1);	//NACK
	}
	i2c_delay(pConfig->tSU_DAT);
	set_scl(1);
	i2c_delay(pConfig->tR + pConfig->tHIGH);
	set_scl(0);
	i2c_delay(pConfig->tF + pConfig->tLOW);
	set_sda(1);
	i2c_delay(pConfig->tR);

	return value;
}

static BOOL i2c_select_device(I2C_CONFIG *pConfig, UINT8 uDevAddr, UINT8 *pSubAddr, UINT8 subAddrLen)
{
	i2c_start(pConfig);
	if(!i2c_putc(pConfig, uDevAddr & 0xfe)) return FALSE;
	while(subAddrLen--){
		if(!i2c_putc(pConfig, *pSubAddr++)) return FALSE;
	}
	return TRUE;
}

BOOL i2c_write(I2C_CONFIG *pConfig, UINT8 uDevAddr, UINT8 *pSubAddr, UINT8 subAddrLen, UINT8 *pData, UINT16 dataLen)
{
	BOOL status = FALSE;

	//OS_ENTER_CRITICAL();
	if(!i2c_select_device(pConfig, uDevAddr, pSubAddr, subAddrLen)) goto exitCatch;
	while(dataLen--){
		if(!i2c_putc(pConfig, *pData++)) goto exitCatch;
	}
	status = TRUE;
	
exitCatch:
	i2c_stop(pConfig);
	//OS_EXIT_CRITICAL();
	return status;
}

BOOL i2c_read(I2C_CONFIG *pConfig, UINT8 uDevAddr, UINT8 *pSubAddr, UINT8 subAddrLen, UINT8 *pData, UINT16 dataLen)
{
	BOOL status = FALSE;

	//OS_ENTER_CRITICAL();
	if(subAddrLen){
		if(!i2c_select_device(pConfig, uDevAddr, pSubAddr, subAddrLen)) goto exitCatch;
	}

	i2c_start(pConfig);
	if(!i2c_putc(pConfig, uDevAddr | 0x01)) goto exitCatch;

	while(dataLen--){
		*pData++ = i2c_getc(pConfig, dataLen ? TRUE : FALSE);	//Transfer the ACK bit(NOT ACK when last byte)
	}
	status = TRUE;

exitCatch:
	i2c_stop(pConfig);
	//OS_EXIT_CRITICAL();
	return status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -