鱼C论坛

 找回密码
 立即注册

<stm32系列>I2C接口

已有 796 次阅读2013-11-14 09:11 |个人分类:stm32

同步串行数据传输总线I2C :十分完善的总线协议。只有两根信号线(双向数据线SDA和时钟线SCL),可构成多机系统.

我测试了硬件I2C,总感觉哪里有点问题。索性就选择了模拟I2C来做
这里用到了两个I2C 一个用于控制时钟芯片,一个用于控制铁电
[code]
/****************************************************************
// Summary: 使DA的引脚为输出状态
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
static void SetI2CDAOut(u8 I2Cx)
{
GPIO_InitTypeDef GPIO_InitStructure;

if(SIM_I2C1 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = RXSDA; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_RX8025, &GPIO_InitStructure);
}
else if(SIM_I2C2 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = FM24SDA; //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_FM24, &GPIO_InitStructure);
}
}

/****************************************************************
// Summary: 使DA的引脚为输入状态
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
static void SetI2CDAIn(u8 I2Cx)
{
GPIO_InitTypeDef GPIO_InitStructure;

if(SIM_I2C1 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = RXSDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_RX8025, &GPIO_InitStructure);
}
else if(SIM_I2C2 == I2Cx)
{
GPIO_InitStructure.GPIO_Pin = FM24SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_FM24, &GPIO_InitStructure);
}
}
/****************************************************************
// Summary: 产生I2C START信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Start(u8 I2Cx)
{
SetI2CDAOut(I2Cx);     //sda输出
if(SIM_I2C1 == I2Cx)
{
I2C1_SDA_1;    
I2C1_SCL_1;
Delay_us(4);
I2C1_SDA_0; //CLK is high, DATA change form high to low 
Delay_us(4);
I2C1_SCL_0; //钳住I2C总线, 准备发送或接收数据
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SDA_1;    
I2C2_SCL_1;
Delay_us(4);
I2C2_SDA_0;
Delay_us(4);
I2C2_SCL_0;
}
}  

/****************************************************************
// Summary: 产生I2C STOP信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Stop(u8 I2Cx)
{
SetI2CDAOut(I2Cx);
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
I2C1_SDA_0; //CLK is high DATA change form low to high
Delay_us(4);
I2C1_SCL_1; 
I2C1_SDA_1; //发送I2C总线结束信号
Delay_us(4);
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
I2C2_SDA_0; //CLK is high DATA change form low to high
Delay_us(4);
I2C2_SCL_1; 
I2C2_SDA_1; //发送I2C总线结束信号
Delay_us(4);
}  
}

/****************************************************************
// Summary: 等待应答信号
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [out/u8] 成功与否
****************************************************************/
u8 I2C_WaitAck(u8 I2Cx)
{
u8 u8ErrTime = 0;

SetI2CDAIn(I2Cx);     //SDA设置为输入 
if(SIM_I2C1 == I2Cx)
{
I2C1_SDA_1;
Delay_us(1);   
I2C1_SCL_1;
Delay_us(1);
ResetWatchDog();  
while(READ_I2C1SDA)
{
u8ErrTime ++;
if(u8ErrTime > 250)
{
I2C_Stop(I2Cx);
return 0;
}
}
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SDA_1;
Delay_us(1);   
I2C2_SCL_1;
Delay_us(1);
ResetWatchDog();  
while(READ_I2C2SDA)
{
u8ErrTime ++;
if(u8ErrTime > 250)
{
I2C_Stop(I2Cx);
return 0;
}
}
I2C2_SCL_0;
}  
  
return 1;  

/****************************************************************
// Summary: 主机产生ACK应答
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/
void I2C_Ack(u8 I2Cx)
{
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
SetI2CDAOut(I2Cx);
I2C1_SDA_0;
Delay_us(2);
I2C1_SCL_1;
Delay_us(2);
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
SetI2CDAOut(I2Cx);
I2C2_SDA_0;
Delay_us(2);
I2C2_SCL_1;
Delay_us(2);
I2C2_SCL_0;
}
}

/****************************************************************
// Summary: 主机不产生ACK应答
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
//
// return: [void]
****************************************************************/    
void I2C_NAck(u8 I2Cx)
{
if(SIM_I2C1 == I2Cx)
{
I2C1_SCL_0;
SetI2CDAOut(I2Cx);
I2C1_SDA_1;
Delay_us(2);
I2C1_SCL_1;
Delay_us(2);
I2C1_SCL_0;
}
else if(SIM_I2C2 == I2Cx)
{
I2C2_SCL_0;
SetI2CDAOut(I2Cx);
I2C2_SDA_1;
Delay_us(2);
I2C2_SCL_1;
Delay_us(2);
I2C2_SCL_0;
}
}     
/****************************************************************
// Summary: I2C发送一个字节
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
// [in/u8]u8Data   发送的字节
//
// return: [void]
****************************************************************/  
void I2C_SendByte(u8 I2Cx, u8 u8Data)
{                        
    u8 t; 
 
SetI2CDAOut(I2Cx); 
if(SIM_I2C1 == I2Cx)
{
   I2C1_SCL_0; //拉低时钟开始数据传输
   for(t = 0; t < 8; t ++)
   {    
if((u8Data & 0x80) >> 7)          
        I2C1_SDA_1;
else 
I2C1_SDA_0;

       u8Data <<= 1;  
Delay_us(2);   
I2C1_SCL_1;
Delay_us(2); 
I2C1_SCL_0;
Delay_us(2);
   }
}
else if(SIM_I2C2 == I2Cx)
{
   I2C2_SCL_0;
   for(t = 0; t < 8; t ++)
   {    
if((u8Data & 0x80) >> 7)          
        I2C2_SDA_1;
else 
I2C2_SDA_0;

       u8Data <<= 1;  
Delay_us(2);   
I2C2_SCL_1;
Delay_us(2); 
I2C2_SCL_0;
Delay_us(2);
   }
}      
    
/****************************************************************
// Summary: 读一个字节
// Parameter: [in/u8]I2Cx 针对那个I2C接口 0 / 1
// [in/u8]ack      ack=1时,发送ACK; ack=0,发送nACK  
//
// return: [out/u8]返回得到的字节
****************************************************************/ 
u8 I2C_ReadByte(u8 I2Cx, u8 ack)
{
u8 i, receive = 0;

SetI2CDAIn(I2Cx); //SDA设置为输入
if(SIM_I2C1 == I2Cx)
{
   for(i = 0; i < 8; i ++)
{
       I2C1_SCL_0; 
       Delay_us(2);
I2C1_SCL_1;
       receive <<= 1;
       if(READ_I2C1SDA)
receive ++;   
Delay_us(1); 
   }  
   if(!ack)
       I2C_NAck(I2Cx); //发送nACK
   else
       I2C_Ack(I2Cx); //发送ACK
}
else if(SIM_I2C2 == I2Cx)
{
   for(i = 0; i < 8; i ++)
{
       I2C2_SCL_0; 
       Delay_us(2);
I2C2_SCL_1;
       receive <<= 1;
       if(READ_I2C2SDA)
receive ++;   
Delay_us(1); 
   }  
   if(!ack)
       I2C_NAck(I2Cx); //发送nACK
   else
       I2C_Ack(I2Cx); //发送ACK
}
  
    return receive;
}

[/code]

路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-3 22:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部