STM32F1 uses I/0 to simulate the I2C interface

Publisher:喜从中来Latest update time:2018-05-20 Source: eefocusKeywords:STM32F1  I Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Compared with the hardware I2C interface, the use of simulated timing will inevitably lead to some declines in real-time performance and transmission speed, but the I2C bus itself is not a very fast bus (according to relevant information, the highest speed is 400KHZ), and it does not need to have very high real-time performance.
Therefore, the simulated I2C timing can fully meet the requirements of most occasions, and the portability has been greatly improved.
Without further ado, post the code and share it with everyone.

First, post the i2c_soft.h implementation:

/*********************************************************************************** 

 * File name: i2c_soft.h 

 * Description: Use I/0 to simulate I2C interface          

 * Experimental platform: Shenzhou III 

 * Library version: ST3.0.0 


**********************************************************************************/  

#ifndef __I2C_SOFT_H  

#define __I2C_SOFT_H  

      

#include "stm32f10x.h"  

#define SCL_PIN        GPIO_Pin_6  

#define SDA_PIN        GPIO_Pin_7  

#define SCL_PORT       GPIOB  

#define SDA_PORT       GPIOB  

#define SCL_RCC_CLOCK  RCC_APB2Periph_GPIOB  

#define SDA_RCC_CLOCK  RCC_APB2Periph_GPIOB  

      

#define SCL_H         GPIOB->BSRR = GPIO_Pin_6  

#define SCL_L         GPIOB->BRR  = GPIO_Pin_6   

         

#define SDA_H         GPIOB->BSRR = GPIO_Pin_7  

#define SDA_L         GPIOB->BRR  = GPIO_Pin_7  

      

#define SCL_read      GPIOB->IDR  & GPIO_Pin_6  

#define SDA_read      GPIOB->IDR  & GPIO_Pin_7  

      

#define I2C_PageSize 8 //24C02 8 bytes per page  

      

void I2C_GPIO_Config(void);  

bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress);  

bool I2C_BufferWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress);  

void I2C_PageWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress);  

bool I2C_ReadByte(u8* pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress);  

void I2C_Test(void);  

      

#endif  


Then paste the i2c_soft.c implementation:


/*********************************************************************************** 

 * File name: i2c_soft.c 

 * Description: Use I/0 to simulate I2C interface          

 * Experimental platform: Shenzhou III 

 * Library version: ST3.0.0 

 * 

 * Author: xiayufeng xiayufeng90520@163.com  

 * Blog: http://hi.baidu.com/xiayufeng520 

**********************************************************************************/  

#include "i2c_soft.h"  

#include "usart1.h"  

       

extern void Delay_ms(__IO u32 nTime);  

       

/*  

 * Function name: void I2C_GPIO_Config(void) 

 * Description: I2C pin initialization 

 * Input: None 

 * Output: None 

 */  

void I2C_GPIO_Config(void)  

{  

    GPIO_InitTypeDef  GPIO_InitStructure;   

           

    RCC_APB2PeriphClockCmd(SCL_RCC_CLOCK | SDA_RCC_CLOCK ,ENABLE);  

           

    //Initialize SCL pin  

    GPIO_InitStructure.GPIO_Pin =  SCL_PIN;  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;    

    GPIO_Init(SCL_PORT, &GPIO_InitStructure);  

           

    //Initialize the SDA pin  

    GPIO_InitStructure.GPIO_Pin =  SDA_PIN;  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  

    GPIO_Init(SDA_PORT, &GPIO_InitStructure);  

}  

       

/*  

 * Function name: void I2C_delay(void) 

 * Description: Short delay 

 * Input : None 

 * Output: None 

 * Note: The internally defined i can optimize the speed. After testing, it can still be written as low as 5. 

 */  

static void I2C_delay(void)  

{     

    u8 i=100;   

    while(i)   

    {   

        i--;   

    }   

}  

       

/*  

 * Function name: bool I2C_Start(void) 

 * Description: Start signal 

 * Input : None 

 * Output: TRUE: Success 

                     FALSE : Failed 

 * illustrate :  

 */  

static bool I2C_Start(void)  

{  

    SDA_H;  

    SCL_H;  

    I2C_delay();  

    if(!SDA_read)  

        return FALSE; //If the SDA line is low, the bus is busy and exit  

    SDA_L;  

    I2C_delay();  

    if(SDA_read)   

        return FALSE; //If the SDA line is high, the bus is wrong and exit  

    SDA_L;  

    I2C_delay();  

    return TRUE;  

}  

/*  

 * Function name: static void I2C_Stop(void) 

 * Description: Termination signal 

 * Input : None 

 * Output: None 

 * illustrate :  

 */  

static void I2C_Stop(void)  

{  

    SCL_L;  

    I2C_delay();  

    SDA_L;  

    I2C_delay();  

    SCL_H;  

    I2C_delay();  

    SDA_H;  

    I2C_delay();  

}  

/*  

 * Function name: static void I2C_Ack(void) 

 * Description: Answer signal 

 * Input : None 

 * Output: None 

 * illustrate :  

 */  

static void I2C_Ack(void)  

{     

    SCL_L;  

    I2C_delay();  

    SDA_L;  

    I2C_delay();  

    SCL_H;  

    I2C_delay();  

    SCL_L;  

    I2C_delay();  

}  

/*  

 * Function name: void I2C_NoAck(void) 

 * Description: No response signal 

 * Input : None 

 * Output: None 

 * illustrate :  

 */  

static void I2C_NoAck(void)  

{     

    SCL_L;  

    I2C_delay();  

    SDA_H;  

    I2C_delay();  

    SCL_H;  

    I2C_delay();  

    SCL_L;  

    I2C_delay();  

}  

/*  

 * Function name: bool I2C_Start(void) 

 * Description: Waiting for response signal 

 * Input : None 

 * Output: TRUE: There is a response 

                     FALSE : No response 

 * illustrate :  

 */  

static bool I2C_WaitAck(void)     

{  

    SCL_L;  

    I2C_delay();  

    SDA_H;            

    I2C_delay();  

    SCL_H;  

    I2C_delay();  

    if(SDA_read)  

    {  

        SCL_L;  

        return FALSE;  

    }  

    SCL_L;  

    return TRUE;  

}  

/*  

 * Function name: static void I2C_SendByte(u8 SendByte)  

 * Description: Send a byte 

 * Input: SendByte: byte data 

 * Output: None 

 * Description: Data from high to low 

 */  

static void I2C_SendByte(u8 SendByte)   

{  

    u8 i=8;  

    while(i--)  

    {  

        SCL_L;  

        I2C_delay();  

        if(SendByte&0x80)  

            SDA_H;    

        else  

            SDA_L;     

        SendByte<<=1;  

        I2C_delay();  

        SCL_H;  

        I2C_delay();  

    }  

    SCL_L;  

}  

/*  

 * Function name: static u8 I2C_ReceiveByte(void)  

 * Description: Read a byte 

 * Input : None  

 * Output: Byte data 

 * Description: ReceiveByte: data from high to low 

 */  

static u8 I2C_ReceiveByte(void)    

{   

    u8 i=8;  

    u8 ReceiveByte=0;  

           

    SDA_H;                

    while(i--)  

    {  

        ReceiveByte<<=1;        

        SCL_L;  

        I2C_delay();  

        SCL_H;  

        I2C_delay();      

        if(SDA_read)  

        {  

            ReceiveByte|=0x01;  

        }  

    }  

    SCL_L;  

    return ReceiveByte;  

}  

       

/*  

 * Function name: bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress) 

 * Description: Write 1 byte of data   

 * Input: SendByte: Data to be written 

                     WriteAddress : write address 

                     DeviceAddress : Device address 

 * Output: TRUE: Success 

                     FALSE : Failed 

 * illustrate :  

 */  

bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)  

{         

    if(!I2C_Start())  

            return FALSE;  

    I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE); //Set high start address + device address   

    if(!I2C_WaitAck())  

        {  

            I2C_Stop();   

            return FALSE;  

        }  

    I2C_SendByte((u8)(WriteAddress & 0x00FF)); //Set low starting address        

    I2C_WaitAck();    

    I2C_SendByte(SendByte);  

    I2C_WaitAck();     

    I2C_Stop();   

           

    Delay_ms(10); //Note: Because we need to wait for the EEPROM to finish writing, we can use query or delay mode (10ms)  

           

        return TRUE;  

}  

/*  

 * Function name: bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress) 

 * Description: Write 1 string of data  

 * Input: pBuffer: pointer to the buffer where data is to be written 

           length: length to be written   

                     WriteAddress : write address 

                     DeviceAddress : Device address 

 * Output: TRUE: Success 

                     FALSE : Failed 

 * Note: Please note that you cannot write across pages. 

 */  

bool I2C_BufferWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress)  

{  

    if(!I2C_Start())  

            return FALSE;  

    I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE); //Set high start address + device address   

    if(!I2C_WaitAck())  

        {  

            I2C_Stop();   

            return FALSE;  

        }  

    I2C_SendByte((u8)(WriteAddress & 0x00FF)); //Set low starting address        

        I2C_WaitAck();    

        while(length--)  

        {  

            I2C_SendByte(* pBuffer);  

            I2C_WaitAck();  

            pBuffer++;  

        }  

        I2C_Stop();  

               

        Delay_ms(10); //Note: Because we need to wait for the EEPROM to finish writing, we can use query or delay mode (10ms)  

               

        return TRUE;  

}  

       

/*  

 * Function name: bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress) 

 * Description: Write 1 string of data  

 * Input: pBuffer: pointer to the buffer where data is to be written 

           length: length to be written   

                     WriteAddress : write address 

                     DeviceAddress : Device address 

 * Output: TRUE: Success 

                     FALSE : Failed 

 * Description: Write a string of data across pages 

 */  

void I2C_PageWrite(  u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress)  

{  

    u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;  

    Addr = WriteAddress % I2C_PageSize; //The write address is the starting page number  

    count = I2C_PageSize - Addr; //Number of pages to be written at the start page  

    NumOfPage = length / I2C_PageSize; //Number of pages to be written  

    NumOfSingle = length % I2C_PageSize; //Number of pages less than one page  

           

    if(Addr == 0) //The write address is the beginning of the page   

    {  

        if(NumOfPage == 0) //The data is less than one page   

        {  

            I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Write less than one page of data  

        }  

        else //The data is greater than or equal to one page    

        {  

            while(NumOfPage) //Number of pages to be written  

            {  

                I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress); //Write a page of data  

                WriteAddress +=  I2C_PageSize;  

                pBuffer += I2C_PageSize;  

                NumOfPage--;  

                Delay_ms(10);  

            }  

            if(NumOfSingle!=0)//The remaining data is less than one page  

            {  

                I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Write less than one page of data  

                Delay_ms(10);  

            }  

        }  

    }  

           

    else //The write address is not the beginning of the page   

    {  

        if(NumOfPage== 0) //The data is less than one page   

        {  

            I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Write less than one page of data  

        }  

        else //The data is greater than or equal to one page  

        {  

            length       -= count;  

            NumOfPage = length / I2C_PageSize; //Recalculate the number of pages to be written  

            NumOfSingle = length % I2C_PageSize; //Recalculate the number of pages less than one page     

                   

            if(count != 0)  

            {    

                I2C_BufferWrite(pBuffer,count,WriteAddress,DeviceAddress); //Write the beginning space to a full page  

                WriteAddress += count;  

                pBuffer      += count;  

            }   

                   

            while(NumOfPage--) //Number of pages to be written  

            {  

                I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress); //Write a page of data  

                WriteAddress +=  I2C_PageSize;  

                pBuffer += I2C_PageSize;   

            }  

            if(NumOfSingle != 0) // The remaining data is less than one page  

            {  

                I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Write less than one page of data   

            }  

        }  

    }   

}  

       

/*  

 * Function name: bool I2C_ReadByte(u8* pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress) 

 * Description: Read out 1 string of data 

 * Input: pBuffer: pointer to the buffer where data is to be read 

           length: length to be read   

                     WriteAddress : Read address 

                     DeviceAddress : Device address 

 * Output: TRUE: Success 

                     FALSE : Failed 

 * Description: Write a string of data across pages 

 */  

bool I2C_ReadByte(u8* pBuffer,   u8 length,     u16 ReadAddress,  u8 DeviceAddress)  

{         

    if(!I2C_Start())return FALSE;  

    I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE); //Set high start address + device address   

    if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}  

    I2C_SendByte((u8)(ReadAddress & 0x00FF)); //Set low start address        

    I2C_WaitAck();  

    I2C_Start();  

    I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress | 0x0001);  

    I2C_WaitAck();  

    while(length)  

    {  

        *pBuffer = I2C_ReceiveByte();  

        if(length == 1)I2C_NoAck();  

        else I2C_Ack();   

        pBuffer++;  

        length--;  

    }  

    I2C_Stop();  

    return TRUE;  

}  

       

/*  

 * Function name: void I2C_Test(void) 

 * Description: Test function 

 * Input : None  

 * Output: None 

 * Description: None 

 */  

void I2C_Test(void)  

{  

       

    u8 I2cVal_Write = 0xFE;  

    u8 I2cVal_Read = 0x00;  

           

    printf("Start IIC test\r\n");  

    printf("The Simulation_IIC has sended data:%d \r\n", I2cVal_Write);  

    I2C_WriteByte(I2cVal_Write, 0X01, 0xa0);  

           

       

    I2C_ReadByte(&I2cVal_Read, 1, 0x01 ,0xa0);  

    printf("The Simulation_IIC has Received data:%d \r\n", I2cVal_Read);  

           

    if(I2cVal_Read == I2cVal_Write)  

    {  

        printf("The Simulation IIC is successful!\r\n");  

    }  

    else  

    {  

        printf("The Simulation IIC is failed!\r\n");  

    }  

       


Keywords:STM32F1  I Reference address:STM32F1 uses I/0 to simulate the I2C interface

Previous article:STM32 simulates I2C program
Next article:STM32F407 analog I2C (Part 2) 24C128

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号