I2C连续读写E2PROM例程

本例程主要作为作者的学习记录,意义在于E2PROM使用页缓冲器连续读写,基于STM32,作用51也很好移植,只需改动端口定义

头文件 

#ifndef AT24CXX_H
#define AT24CXX_H


#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "stdio.h"


#define E2PROM_I2C_SDA_RE PBin(11)	
#define E2PROM_I2C_SDA_WR PBout(11)

#define E2PROM_I2C_SCL PBout(10)

#define I2C_SetOut_Mode() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=0X00003000;}
#define I2C_SetIn_Mode() 	{GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=0X00008000;GPIOB->ODR|=0X01<11;}	


#define PROM_device_addr     0xa0
#define AT24cxxpage_size 			8		 //字节页写缓冲器大小
#define AT24CXX_size					256  //E2PROM容量大小 BYTE

void E2PROM_I2C_PORT_Init(void);
void I2C_delay(void);
void E2PROM_I2C_start(void);
void E2PROM_I2C_stop(void);
u8 E2PROM_I2C_check_ack(void);
void E2PROM_I2C_ack(void);
void E2PROM_I2C_NoAck(void);
void E2PROM_I2C_write_char(u8 dat);
u8 E2PROM_I2C_read_char(void);
void AT24CXX_Read(u8 DeviceAddr,u8 *pbuffer,u16 ReadAddr,u16 length,u16 *readed);
void AT24CXX_Write_Page(u8 DeviceAddr,u8 *pbuffer,u8 Write_Addr,u8 length);
void AT24CXX_Write(u8 DeviceAddr,u8 *pbuffer,u8 Write_Addr,u16 length,u16 *written);



#endif

 

 

源文件

#include "at24cxx.h"


void E2PROM_I2C_PORT_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_10);

	
}

void I2C_delay(void)
{
	u16 i;
	/* 
	 	下面的时间是通过逻辑分析仪测试得到的。
    工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  
		循环次数为10时,SCL频率 = 205KHz 
		循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
	 	循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
	*/
	for(i=0;i<3;i++);
}


void E2PROM_I2C_start(void)
{
	
	I2C_SetOut_Mode();	
	E2PROM_I2C_SCL=0;
	E2PROM_I2C_SDA_WR=1;
	E2PROM_I2C_SCL=1;
	I2C_delay();
	E2PROM_I2C_SDA_WR=0;
	E2PROM_I2C_SCL=0;
	I2C_delay();
}

void E2PROM_I2C_stop(void)
{
	
	I2C_SetOut_Mode();
	E2PROM_I2C_SCL=0;
	E2PROM_I2C_SDA_WR=0;
	E2PROM_I2C_SCL=1;
	I2C_delay();
	E2PROM_I2C_SDA_WR=1;
	E2PROM_I2C_SCL=0;
	I2C_delay();
	E2PROM_I2C_SDA_WR=1;//拉高时钟和数据线,降低功耗
	E2PROM_I2C_SCL=1;  

}

u8 E2PROM_I2C_check_ack(void)
{	
	u8 ack_status=0X01;
	
	I2C_SetIn_Mode();
	E2PROM_I2C_SCL=0;
	E2PROM_I2C_SDA_WR=1;
	E2PROM_I2C_SCL=1;
	I2C_delay();
	ack_status=0x01&E2PROM_I2C_SDA_RE;
	E2PROM_I2C_SCL=0;
	I2C_delay();

	return ack_status;
}

void E2PROM_I2C_ack(void)
{
	I2C_SetOut_Mode();
	E2PROM_I2C_SCL=0;
	E2PROM_I2C_SDA_WR=0;
	E2PROM_I2C_SCL=1;
	I2C_delay();
	E2PROM_I2C_SCL=0;
	I2C_delay();
	E2PROM_I2C_SDA_WR=1;
	
}

void E2PROM_I2C_NoAck(void)
{
	I2C_SetOut_Mode();
	E2PROM_I2C_SCL=0;
	E2PROM_I2C_SDA_WR=1;
	I2C_delay();
	E2PROM_I2C_SCL=1;
	I2C_delay();
	E2PROM_I2C_SCL=0;
	I2C_delay();
	
}


void E2PROM_I2C_write_char(u8 dat)
{
	u8 i=0;
	
	E2PROM_I2C_SCL=0;
	I2C_SetOut_Mode();
	for(i=0;i<8;i++)
	{
		
		if(dat&0x80) E2PROM_I2C_SDA_WR=1;
		else E2PROM_I2C_SDA_WR=0;
		I2C_delay();
		E2PROM_I2C_SCL=1;
		I2C_delay();
		E2PROM_I2C_SCL=0;
		dat<<=1;
	}
	
}

u8 E2PROM_I2C_read_char(void)
{
	u8 i=0,dat=0;
	E2PROM_I2C_SCL=0;
	I2C_SetIn_Mode();
	for(i=0;i<8;i++)
	{
	
		dat<<=1;
		E2PROM_I2C_SCL=1;
		I2C_delay();
		if(E2PROM_I2C_SDA_RE) dat|=0x01;
		E2PROM_I2C_SCL=0;
		I2C_delay();
	
	}
	return dat;
}


void AT24CXX_Read(u8 DeviceAddr,u8 *pbuffer,u16 ReadAddr,u16 length,u16 *readed)
{
	
	u16 i=0;
	*readed=0;
	
	if(length>AT24CXX_size) length=AT24CXX_size;									/*避免读数据超出容易*/
	if(length+ReadAddr>AT24CXX_size) length=AT24CXX_size-ReadAddr;
	E2PROM_I2C_start();
	E2PROM_I2C_write_char(DeviceAddr);
	E2PROM_I2C_check_ack();
	E2PROM_I2C_write_char(ReadAddr);
	E2PROM_I2C_check_ack();
	
	E2PROM_I2C_start();
	E2PROM_I2C_write_char(DeviceAddr|0x01);
	E2PROM_I2C_check_ack();
	for(i=0;i=length) break;
		E2PROM_I2C_ack();
	}
	*readed+=length;
	E2PROM_I2C_NoAck();		
	E2PROM_I2C_stop();
	
}

//使用页写缓冲器写入,以提高速度
//在指定地址开始写入最大T24cxxpage_size字节的数据
//pbuffer:数据存储区
//Write_Addr:开始写入的地址
//length:要写入的字节数(最大T24cxxpage_size),该数不应该超过该页的剩余字节数!!!	 
void AT24CXX_Write_Page(u8 DeviceAddr,u8 *pbuffer,u8 Write_Addr,u8 length)
{
	u16 i=0;
										
	E2PROM_I2C_start();
	E2PROM_I2C_write_char(DeviceAddr);
	E2PROM_I2C_check_ack();
	E2PROM_I2C_write_char(Write_Addr);
	E2PROM_I2C_check_ack();
	
	for(i=0;iAT24CXX_size) length=AT24CXX_size;										/*避免写数据超出容量*/
	if(length+Write_Addr>AT24CXX_size) length=AT24CXX_size-Write_Addr;
	
	PageRmain=AT24cxxpage_size-Write_Addr%AT24cxxpage_size;//单页剩余的字节数		 	 
	if(length<=PageRmain) PageRmain=length;
	
	while(1)
	{
		AT24CXX_Write_Page(DeviceAddr,pbuffer,Write_Addr,PageRmain);
		*written+=PageRmain;  //累加被写入的字节数
		if(PageRmain==length) break;
		else
		{
			pbuffer+=PageRmain;
			Write_Addr+=PageRmain;
			length-=PageRmain;
			
			if(length>AT24cxxpage_size) PageRmain=AT24cxxpage_size;
			else PageRmain=length;
		}
	}
}

 

主函数调用测试

#include "stm32f10x.h"
#include "delay.h"
#include "at24cxx.h"
#include "usart.h"



#define USART1_Bound 115200

u8 E2PROM_buffer[256];
u8 E2PROM_buffer2[256];

int main(void)
{
	
	u16 i,j,k;
	u16 timer2_data_us,timer2_data_ms;
	u16 count=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Delay_Init();
	
	
	
	MY_USART1_Init(USART1_Bound);
	E2PROM_I2C_PORT_Init();
	
	for(i=0;i<256;i++)
	{
		
		E2PROM_buffer[i]= i;
	}
	
	
    AT24CXX_Write(PROM_device_addr,E2PROM_buffer,0,256,&e2prom_count);	
    printf("write number:%d\r\n",e2prom_count);

	AT24CXX_Read(PROM_device_addr,E2PROM_buffer_read,0,256,&e2prom_count);
    printf("read number:%d\r\n",e2prom_count);
	
	for(i=0;i<16;i++)
	{
		for(j=0;j<16;j++)
		{
			printf("%d ",E2PROM_buffer2[i*16+j]);
			
		}
		printf("\r\n");
	}
	
	for(i=0;i<255;i++)
	{
		if((E2PROM_buffer_read[i]-E2PROM_buffer_read[i+1]!=1 )&&
				E2PROM_buffer_read[i+1]-E2PROM_buffer_read[i]!=1) 
				break;
	}
	if(i>=255) printf("\r\n E2PROM test OK  \r\n");
	else printf("\r\n E2PROM test error!! %d \r\n",E2PROM_buffer_read[i]);
	

	while(1);
	
	
	
	
}

 

你可能感兴趣的:(单片机,嵌入式STM32应用)