基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)

1.硬件准备

STM32F103核心板 AT24C02
SCL线连PB6,SDA线连PB7

2.理论部分

2.1 I2C简介

I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实
现简单,可扩展性强,不需要 USART、 CAN 等通讯协议的外部收发设备,现在被广泛地
使用在系统内多个集成电路(IC)间的通讯。以下分为物理层与协议层两部分讲解

2.2 I2C物理层

基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第1张图片一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。

2.3 I2C协议层

基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第2张图片以上的格子都表示SDA线发送的数据包,S表示start信号,P表示stop信号,A表示ack信号,SLAVE ADDRESS表示从机地址。其他的都能看懂
STM32自带了I2C的外设,可以通过自带的库函数与其他外设进行I2C通信,也可以模拟I2C时序实现软件I2C。模拟I2C首先要用SDA与SCL表示出上面的各种信号

基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第3张图片基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第4张图片I2C 使用 SDA 信号线来传输数据,使用 SCL信号线进行数据同步。 SDA 数据线在 SCL的每个时钟周期传输一位数据。传输时, SCL为高电平的时候 SDA表示的数据有效,即此时的 SDA为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL为低电平时,SDA的数据无效,一般在这个时候 SDA 进行电平切换,为下一次表示数据做好准备。
也就是说,SCL低电平时SDA进行电平的转换,在SCL为高电平时将SDA发送出去。
基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第5张图片

3.代码部分

soft_I2C.h

#define EEPROM_GPIO_PORT	GPIOB
#define PIN_SCL			GPIO_Pin_6
#define PIN_SDA		  GPIO_Pin_7

#define WRITE_ADDR	0XA0
#define READ_ADDR		0XA1
#define READ_SDA		GPIO_ReadInputDataBit(EEPROM_GPIO_PORT,PIN_SDA)
#define SCL_H			    GPIO_SetBits(EEPROM_GPIO_PORT,PIN_SCL)
#define SDA_H				GPIO_SetBits(EEPROM_GPIO_PORT,PIN_SDA)
#define SCL_L				GPIO_ResetBits(EEPROM_GPIO_PORT,PIN_SCL)
#define SDA_L				GPIO_ResetBits(EEPROM_GPIO_PORT,PIN_SDA)

void I2C_GPIO_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NAck(void);
void I2C_Wait_Ack(void);
uint8_t I2C_Send_Byte(uint8_t txd);
uint8_t I2C_ReadByte(void);
uint8_t EEPROM_WRITEBYTE(uint8_t addr,uint8_t data);
uint8_t EEPROM_READBYTE(uint8_t addr);
void SDA_Out(void);
void SDA_In(void);

soft_I2C.C


```c
#include "soft_I2C.h"
#include "bsp_systick.h"

void I2C_GPIO_Init(void)
{
     
	GPIO_InitTypeDef 	GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = PIN_SCL;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStruct);	
	
	GPIO_InitStruct.GPIO_Pin = PIN_SDA;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStruct);
}

void SDA_In(void)
{
     
	GPIO_InitTypeDef 	GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = PIN_SDA;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStruct);	
}

void SDA_Out(void)
{
     
	GPIO_InitTypeDef 	GPIO_InitStruct;	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = PIN_SDA;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStruct);	
}

void I2C_Start(void)
{
     
	SDA_Out();
	SCL_H;
	SDA_H;
	SysTick_Delay_us(5);
	SDA_L;
	SysTick_Delay_us(5);
	SCL_L;
}

void I2C_Stop(void)
{
     
	SDA_Out();
	SCL_L;
	SDA_L;
	SCL_H;
	SysTick_Delay_us(5);
	SDA_H;
	SysTick_Delay_us(5);
}

void I2C_Ack(void)
{
     
	SCL_L;
	SDA_Out();
	SDA_L;
	SysTick_Delay_us(5);
	SCL_H;
	SysTick_Delay_us(5);
	SCL_L;
}

void I2C_NAck(void)
{
     
	SCL_L;
	SDA_Out();
	SDA_H;
	SysTick_Delay_us(5);
	SCL_H;
	SysTick_Delay_us(5);
	SCL_L;
}

void I2C_Wait_Ack()
{
     
	uint8_t time;
	SDA_H;//释放SDA控制权
	SysTick_Delay_us(3);
	SDA_In();
	SCL_H;
	SysTick_Delay_us(5);
	if(READ_SDA==1)
	{
     
		I2C_Stop();
	}
	SCL_L;	   
}

uint8_t I2C_Send_Byte(uint8_t txd)
{
     
	uint8_t i;
	SDA_Out();
	SCL_L;
	for(i=0;i<8;i++)
    {
                   
      if(txd&0x80) //0x80=b(1000 0000)
		SDA_H;
	  else
	    SDA_L;
    txd<<=1; 	  
	SysTick_Delay_us(5);   
	SCL_H;		
	SysTick_Delay_us(5); 
	SCL_L;	
	SysTick_Delay_us(5);
    }	 
}

uint8_t I2C_ReadByte(void)
{
     
	u8 i,rxd=0;
	SDA_In();
  	for(i=0;i<8;i++ )
	{
     
   		SCL_L; 
   		SysTick_Delay_us(5);
	 	SCL_H;
   		rxd<<=1;
   		if(READ_SDA)
			rxd++;   
	 	SysTick_Delay_us(1); 
   }					 
   return rxd;
}

4.总结

以上就是代码部分,包含了start stop ack nack 还有读、写一个字节的代码块。通过和AT24C02的硬件手册可以实现对EEPROM的读写。请自行探索。附AT24C02单个字节读写的时序图(请忽略我的笔记。。)
其实在我写这个的过程中还是遇到很多问题 比如对SCL信号的控制不当导致程序出错 还有些地方需要delay却没有delay导致程序出错的
这些在写的过程中都需要多加注意
基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第6张图片基于STM32F103的模拟I2C时序读写EEPROM(AT24C02)_第7张图片

你可能感兴趣的:(stm32)