STM32之I2C

来源:互联网 发布:海军知耻 陆军马鹿 编辑:程序博客网 时间:2024/05/23 01:16

对于STM32,说道I2C都比较头疼。有人说硬件有缺陷,有的人说不稳定。总之就是不好用。

但是对于某些情况,又必须要使用I2C,无奈之余,只能凑合用了。


I2C从模式上分为主发,主收,从发,从收。

主发送模式:

I2C_ERR_E    I2C_Send(BYTE*    data, BYTE        addr, int   len)
{
    int   count, cycle = 0,err;
    u32   event;
    I2C_ERR_E   error = I2C_ERR_OK;
    
    
     I2C_AcknowledgeConfig(I2C2, ENABLE);
     /* Send START condition */
    if(I2C2->SR2 & 0x02)                                                  //检测busy位,如果为“1”,则I2C不能正常使用,重启I2C
        {
            goto I2C_RESET;
        }

     I2C_GenerateSTART(I2C2, ENABLE);
    
     count = I2C_TIMEOUT;                                               //设置超时时限
     while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));

    if(count == 0)                                                                 //发送开始条件失败(总线忙),可能因为总线被占用,重启I2C
    {
        I2C_GenerateSTOP(I2C2, ENABLE);
        error = I2C_ERR_TIMEOUT;
        goto I2C_RESET;

    }
    count = I2C_TIMEOUT;
    I2C_Send7bitAddress(I2C2,addr,I2C_Direction_Transmitter);

    while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


    if(count == 0)                                                                 //发送地址无应答,直接返回。此处不需要重启,可能是因为地址没有匹配。
    {
        error = I2C_ERR_TIMEOUT;
        return error;
    }
        while(len -- ){
            count = I2C_TIMEOUT;
            I2C_SendData(I2C2, *data);
            data++;
            while(--count  && !(I2C2->SR1 & 0x80));
            if(count == 0)                                                     //发送失败,退出发送
            {
                error = I2C_ERR_TIMEOUT;                        
                break;
            }
        }

   
    I2C_GenerateSTOP(I2C2, ENABLE);       

    count=       I2C_TIMEOUT;

     while (--count && I2C2->SR2 & 0x02);                //检测停止条件是否发送成功

     if(count == 0)
     {
         goto I2C_RESET;
     }
    
     return I2C_ERR_OK;

I2C_RESET:                                                                 //对于异常,重启I2C(对于主机的I2C异常,重启能解决,但是若从机占用了I2C,那么需要重启从机I2C才能解决)           
    I2C_SoftwareResetCmd(I2C2, ENABLE);
    I2C_SoftwareResetCmd(I2C2, DISABLE);
    I2C_Config();
    return I2C_ERR_TIMEOUT;
}


主接受模式:


I2C_ERR_E    I2C_Recv(BYTE        addr, I2C_frame_t *frame)
{
    int   count = I2C_TIMEOUT;
    int   index = 0 ,len;
    u32   event;
    u8      crc;
    
    I2C_ERR_E   error = I2C_ERR_OK;
    
    I2C_Lock();
    
    if(I2C2->SR2 & 0x02)
        {
            error =  I2C_ERR_FAIL;
            goto i2c_recv_ret;
        }

    I2C_AcknowledgeConfig(I2C2,ENABLE);
    I2C_GenerateSTART(I2C2, ENABLE);
    while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));

    if(count == 0)
    {
        error = I2C_ERR_TIMEOUT;
        goto  end;
    }
    count = I2C_TIMEOUT;
    I2C_Send7bitAddress(I2C2,addr,I2C_Direction_Receiver);

    while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    if(count == 0)
    {
        error = I2C_ERR_TIMEOUT;
        goto  end;
    }
    
    count = I2C_TIMEOUT;

    while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));

        if(count == 0)
        {
            error = I2C_ERR_TIMEOUT;
            goto  end;
        }
        frame->cmd  = I2C_ReceiveData(I2C2);            //cmd
        
        
        count = I2C_TIMEOUT;
        while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));

        if(count == 0)
        {
            error = I2C_ERR_TIMEOUT;
            goto  end;
        }
        frame->len = len  = I2C_ReceiveData(I2C2);            //len
        if(len > 0 && len <= 64){
            while(len -- ){
                count = I2C_TIMEOUT;
                while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));

                if(count == 0)
                {
                    error = I2C_ERR_TIMEOUT;
                    goto  end;
                }
                frame->data[index] = I2C_ReceiveData(I2C2);
                index ++;

            }
        }
        I2C_AcknowledgeConfig(I2C2,DISABLE);
        I2C_GenerateSTOP(I2C2, ENABLE);

        count = I2C_TIMEOUT;
        while(--count  && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
    
            if(count == 0)
            {
                error = I2C_ERR_TIMEOUT;
                goto  end;
            }
            frame->crc = I2C_ReceiveData(I2C2);            //len
            crc = CRC8_Table(frame->data, frame->len);
            if(frame->crc != crc)
            {
                error = I2C_ERR_CRC;
            }
       
        goto  i2c_recv_ret;
end:
    I2C_GenerateSTOP(I2C2, ENABLE);

    count=       I2C_TIMEOUT;

     while (count-- && I2C2->SR2 & 0x02);

     if(count == 0)
     {
        return I2C_ERR_TIMEOUT;
     }
i2c_recv_ret:
    return  error;
}

从发,从収使用中断来响应:

    void I2C2_EV_IRQHandler(void)
     {        

    u32 SR1Register,SR2Register;

    SR1Register = I2C2->SR1;
       SR2Register = I2C2->SR2;

    /* If I2C1 is slave (MSL flag = 0) */
    if ((SR2Register &0x0001) != 0x0001)
    {
        /* If ADDR = 1: EV1 */
        if ((SR1Register & 0x0082) == 0x0082)
        {
            /* Clear SR1Register and SR2Register variables to prepare for next IT */
            SR1Register = 0;
            SR2Register = 0;
            /* Initialize the transmit/receive counters for next transmission/reception
            using Interrupt  */
            Tx_Counter = 0;
            status = 2;
            
            Time5_Init();
        }else if((SR1Register & 0x0082) == 0x0002)
           {
            SR1Register = 0;
            SR2Register = 0;
            /* Initialize the transmit/receive counters for next transmission/reception
            using Interrupt  */
            Rx_Counter = 0;
            status = 1;
            Time5_Init();
        }
        /* If TXE = 1: EV3 */
        if ((SR1Register & 0x0080) == 0x0080)
        {
            /* Write data in data register */
            I2C2->DR = I2C1_Buffer_Tx[Tx_Counter++];
            SR1Register = 0;
            SR2Register = 0;
        }
        /* If RXNE = 1: EV2 */
        if ((SR1Register & 0x0040) == 0x0040)
        {
            /* Read data from data register */
            I2C1_Buffer_Rx[Rx_Counter++] = I2C2->DR;
            SR1Register = 0;
            SR2Register = 0;

        }
        /* If STOPF =1: EV4 (Slave has detected a STOP condition on the bus */
        if (( SR1Register & 0x0010) == 0x0010)
        {    

            //处理帧
            SR1Register = 0;
            SR2Register = 0;
        }
     } /* End slave mode */

     }

0 0