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");
}
}
Previous article:STM32 simulates I2C program
Next article:STM32F407 analog I2C (Part 2) 24C128
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- ASML predicts that its revenue in 2030 will exceed 457 billion yuan! Gross profit margin 56-60%
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- Does lighttpd support PHP?
- TI Designs – Precision file question about Bode plots
- Does the boost topology circuit limit the duty cycle?
- Op amp differential amplification problem
- FAQ_How to fill in the BQB certification application form
- HC6800 EM3 V2.0 CD-ROM
- Share the temperature and humidity monitoring of LoRa communication technology
- [TI star product limited time purchase] + AWR6843 purchase experience and unboxing
- EEWORLD University ---- VLSI Testing
- How to test the withstand voltage characteristics of general ceramic capacitors