版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SheepTech/article/details/82696989
文章原始地址:http://feotech.com/?p=98
本程序主要用于使用可编程芯片自身的IO管脚,模拟I2C通信的协议,实现I2C总线数据的传输.
/**
******************************************************************************
* @file Virtual_I2C.C
* @author Ryan Zhao
* @version V1.0.0
* @date 2017-04-20
* @brief 软件I/O模拟I2C总线通讯.
******************************************************************************
* @attention Null
*
******************************************************************************
*/
/**
* @brief I2C引脚初始化.
* @param None.
* @retval None.
*/
void I2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高
}
/**
* @brief 产生I2C开始信号.
* @param None.
* @retval None.
*/
void I2C_Start(void)
{
SDA_OUT(); //SDA引脚设置为输出模式
I2C_SDA_H; //SDA引脚设置为高电平
I2C_SCL_H; //SCL引脚设置为高电平
Delay(); //软件延时
I2C_SDA_L;
Delay(); //软件延时
I2C_SCL_L; //准备发送或接收数据
}
/**
* @brief 产生I2C停止信号.
* @param None.
* @retval None.
*/
void I2C_Stop(void)
{
SDA_OUT();//SDA引脚设置为输出模式
I2C_SCL_l;
I2C_SDA_l;
Delay(); //软件延时
I2C_SCL_H;
I2C_SDA_H;
Delay();
}
/**
* @brief 等待ACK信号.
* @param None.
* @retval 1:接收应答成功;
0:接收应答失败;
*/
unsigned char I2C_Wait_Ack(void)
{
unsigned char ucErrTime=0;
SDA_IN(); //SDA引脚设置为输入模式
I2C_SDA_H;
Delay();
I2C_SCL_H;
Delay();
while(READ_SDA)//读取SDA引脚电平状态
{
ucErrTime++;
if(ucErrTime>250)
{
I2C_Stop();
return 0; //接收应答失败
}
}
I2C_SCL_L;
return 1; //接收应答成功
}
/**
* @brief 产生ACK信号.
* @param None.
* @retval None.
*/
void I2C_Ack(void)
{
I2C_SCL_L;
SDA_OUT(); //SDA引脚设置为输出模式
I2C_SDA_L;
Delay();
I2C_SCL_H;
Delay();
I2C_SCL_L;
}
/**
* @brief 不产生ACK信号.
* @param None.
* @retval None.
*/
void I2C_NAck(void)
{
I2C_SCL_L;
SDA_OUT();
I2C_SDA_H;
Delay();
I2C_SCL_H;
Delay();
I2C_SCL_L;
}
/**
* @brief I2C发送一个字节.
* @param None.
* @retval None.
*/
void I2C_Send_Byte(unsigned char txd)
{
unsigned char i;
SDA_OUT();
I2C_SCL_L;
for(i=0;i<8;i++)
{
if((txd&0x80)>>7)
{
I2C_SDA_H;
}
else
{
I2C_SDA_L;
}
txd = txd<<1;
Delay();
I2C_SCL_H;
Delay();
I2C_SCL_L;
Delay();
}
}
/**
* @brief I2C读取一个字节.
* @param None.
* @retval 读取到的数据
*/
unsigned char I2C_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
I2C_SCL=0;
Delay();
I2C_SCL=1;
receive<<=1;
if(READ_SDA)
{
receive++;
}
Delay();
}
if (!ack)
{
I2C_NAck();//发送nACK
}
else
{
I2C_Ack(); //发送ACK
}
return receive;
}