iic模拟io口
最近用硬件iic发现oled一直不亮,经过测试可能是硬件的问题(卡在一个死循环出不来),于是想办法拿别人的代码来研究软件iic,仅供学习
原文章:软件模拟iic
#define I2C_Speed 100000
#define I2C_EE I2C1
#define uStatus 0x80
#define dTime 5
#define I2C_EE_GPIO GPIOB
#define I2C_EE_SCL GPIO_Pin_5
#define I2C_EE_SDA GPIO_Pin_4
#define I2C_EE_CLK RCC_APB1Periph_I2C1
#define SCL_H GPIOB->BSRR = GPIO_Pin_5
#define SCL_L GPIOB->BRR = GPIO_Pin_5
#define SDA_H GPIOB->BSRR = GPIO_Pin_4
#define SDA_L GPIOB->BRR = GPIO_Pin_4
#define SCL_read GPIOB->IDR & GPIO_Pin_5
#define SDA_read GPIOB->IDR & GPIO_Pin_4
static unsigned int cntForInitial = 0;
static unsigned char fSigStatus = 0;
void I2C_Init()//1
{
GPIO_InitTypeDef GPIO_InitStructure;
//* Configure I2C_EE pins: SCL and SDA
GPIO_InitStructure.GPIO_Pin = I2C_EE_SCL | I2C_EE_SDA;//pb4 5
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开楼输出
GPIO_Init(I2C_EE_GPIO, &GPIO_InitStructure);
}
static void i2c_start()//2开始信号
{
SDA_H;
SCL_H;
DelayUs(dTime);//5us
SDA_L;
DelayUs(dTime);
SCL_L;
DelayUs(dTime);
// LedStatus = !LedStatus;
//f_LCT1(LedStatus);
}
/*
******************************************************************
Fuction:
Stop i2c
******************************************************************
*/
static void i2c_stop()//3结束信号
{
SDA_L;
SCL_H;
DelayUs(dTime);
SDA_H;
DelayUs(dTime);
SCL_H;
DelayUs(dTime);
}
/*
******************************************************************
Fuction:
i2c Master wait for ack等待应答
Only ack
******************************************************************
*/
static unsigned char i2c_rd_ack() // 4等待应答ACK0 NACK1
{
unsigned char flag = 0;
SDA_H;
SCL_H;
DelayUs(dTime/2);
flag = SDA_read;
DelayUs(dTime/2);
SCL_L;
DelayUs(dTime/2);
if(flag == 1)
return 0;
return 1;
}
/*
******************************************************************
Fuction:
i2c Byte transmission
Only Send,no ack,no stop
******************************************************************
*/
static unsigned char i2c_sb(unsigned char Byte) //发送字节 5
{
unsigned char cnt;
SCL_L;
for(cnt=0;cnt<8;cnt++)
{
if(Byte&0x80)
SDA_H;
else
SDA_L;
DelayUs(dTime);
SCL_H;
DelayUs(dTime);
SCL_L;
Byte <<= 1;
DelayUs(dTime);
}
return i2c_rd_ack();
}
/*
******************************************************************
Fuction:
i2c Byte receive
Return Byte
******************************************************************
*/
static unsigned char i2c_rb() ///接收字节 6
{
unsigned char cnt;
unsigned char Byte=0;
SDA_H;
for(cnt=0;cnt<8;++cnt)
{
Byte <<= 1;
DelayUs(dTime);
SCL_H;
DelayUs(dTime);
if(SDA_read)
Byte |= 0x01;
SCL_L;
DelayUs(dTime);
}
return Byte;
}
static void i2c_wr_ack(unsigned char ACK)// 7是否产生应答
{
if(ACK)
SDA_H; //NACK
else //ACK
SDA_L;
SCL_H;
DelayUs(dTime);
SCL_L;
DelayUs(dTime);
}
uint8_t ReadReg(unsigned int addr)
{
uint8_t temp;
i2c_start();
if(!i2c_sb(BRG_DEV_ADDR))
{
i2c_stop();
return 0;
}
if(!i2c_sb((uint8_t)(addr >> 8)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((uint8_t)(addr & 0xFF)))
{
i2c_stop();
return 0;
}
i2c_start();
if(!i2c_sb(BRG_DEV_ADDR |0x01))
{
i2c_stop();
return 0;
}
temp = i2c_rb();
i2c_wr_ack(1);
i2c_stop();
return temp;
}
unsigned char WriteReg8(unsigned int addr,unsigned char wData)
{
i2c_start();
if(!i2c_sb(BRG_DEV_ADDR))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr >> 8)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr & 0xFF)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData)))
{
i2c_stop();
return 0;
}
i2c_stop();
//DelayUs(1);
return 1;
}
unsigned char WriteReg16(unsigned int addr,unsigned char wData1,unsigned char wData2)
{
i2c_start();
if(!i2c_sb(BRG_DEV_ADDR))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr >> 8)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr & 0xFF)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData2)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData1)))
{
i2c_stop();
return 0;
}
i2c_stop();
DelayUs(1);
return 1;
}
unsigned char WriteReg32(unsigned int addr,unsigned char wData1,unsigned char wData2,unsigned char wData3,unsigned char wData4)
{
i2c_start();
if(!i2c_sb(BRG_DEV_ADDR))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr >> 8)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(addr & 0xFF)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData4)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData3)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData2)))
{
i2c_stop();
return 0;
}
if(!i2c_sb((unsigned char)(wData1)))
{
i2c_stop();
return 0;
}
i2c_stop();
DelayUs(1);
return 1;
}