微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 8051模拟IIC操作EEPROM

8051模拟IIC操作EEPROM

时间:12-03 来源:互联网 点击:
注:

本篇内容和STM32模拟IIC操作EEPROM思路是一样的,是一个程序到不同平台的移植。

首先是EEPROM.h文件内容:

#ifndef _eeprom_h_
#define _eeprom_h_

#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include

#define EEPROM_ADDRESS 0x57

sbit SDA = P1^2; //EEPROM的数据线
sbit SCL = P1^1; //EEPROM的时钟线
sbit WP = P1^0; //EEPROM的写保护,给低电平表示读写均允许,也就是标准的模式。

extern void EEPROM_Init();

extern unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_write_arr[],unsigned int len);

extern unsigned char read_eeprom_status(unsigned char c_slave_address7bit);

extern unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_read_arr[],unsigned int len);

extern unsigned char EEPROM_Read(unsigned char c_slave_address7bit,unsigned char c_reg_address);

extern unsigned char EEPROM_Write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data);

#endif

再个就是EEPROM.c文件的内容:

#include "eeprom.h"
#include //头文件的包含
#include

#include "usart.h"

#define _Nop() _nop_() //定义空指令

static void EEPROM_Stop( void );

static void Delay_us(unsigned int i_delay_count)
{
int j = 0,i;
for(j = 0 ; j < 5; j ++)
for(i = 0 ; i < i_delay_count ; i ++)
;
}

/*******************************************************************************
* I2C电路:
* 单片机 EEPROM
* P10--------->WP
* P11--------->SCL
* P12--------->SDA
*
* A0,A1,A2均通过硬件拉高电平
*
* 我这里将EEPROM的地址按照如下方式规划:
* 0101 0(A2)(A1)(A0)
* 因此EEPROM的地址为0x57.
*
* copyright by wit_yuan 2016-09-15 at 龙兴园北区
-------------------------------------------------------------------------------*/
void EEPROM_Init()
{
//将WP设置为低电平即可
WP = 0;
//将IIC总线置高即可
SCL = 1;
SDA = 1;
}

/*
*
* EEPROM_Start():
* 内部函数
*
*/
static void EEPROM_Start()
{
SDA=1; //由于上一个SCL状态是0或者是1,要让SDA稳定输出,都可以设置为1
Delay_us(2);

SCL=1; //让SCL发生变化,为0不变,为1则变化,表明数据可以变动了。
Delay_us(2);

SDA=0; //SDA线数据变化,从而可以保证发出的是start信号。
Delay_us(2);

SCL=0; //将I2C总线钳住,下一个时间SDA可以输出高低电平。
Delay_us(4);
}

/*
*
* EEPROM_Send_Byte():
* 内部函数
*
*/
static void EEPROM_Send_Byte( unsigned char txd)
{
unsigned char t;
// SDA_OUT();
SCL=0;//拉低时钟开始数据传输
Delay_us(2);
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
SDA=1;
else
SDA=0;
txd<=1;
Delay_us(2);
SCL=1;
Delay_us(2);
SCL=0;
Delay_us(2);
}
}

/*
*
* EEPROM_Read_Byte():
* 内部函数
*
*/
static unsigned char EEPROM_Read_Byte()
{
unsigned char i,u_receive=0;
// SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
SCL=0;
Delay_us(4);
SCL=1;
Delay_us(1);
u_receive<=1;
if(SDA)
u_receive++;
}

return u_receive;
}

/*
*
* EEPROM_Ack():
* 内部函数
* 2016-09-16 edited for 8051. by wit_yuan
*/
static void EEPROM_Ack()
{
SCL=0;
Delay_us(2);

//////add 2016-09-16 by wit_yuan///////////
SDA = 1;
Delay_us(1);

SDA=0;
Delay_us(1);

SCL=1;
Delay_us(1);

SCL=0;
Delay_us(4);

//////add 2016-09-16 by wit_yuan///////////
SDA = 1;
Delay_us(1);

}

/*
*
* EEPROM_Wait_Ack():
* 内部函数
*
*/
static unsigned char EEPROM_Wait_Ack()
{
unsigned char ucErrTime=0;

SCL=0;
Delay_us(1);

while(SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
EEPROM_Stop();
return 1; //超时,表明数据传输有问题
}
}
SCL=1;
Delay_us(1);

SCL=0;//时钟输出0
Delay_us(2);

return 0;
}

/*
*
* EEPROM_No_Ack():
* 内部函数
*
*/
static void EEPROM_No_Ack()
{

SCL=0;
Delay_us(2);

SDA=1;
Delay_us(1);

SCL=1;
Delay_us(1);

SCL=0;
Delay_us(4);
}

/*
*
* EEPROM_Stop():
* 内部函数
*
*/
static void EEPROM_Stop()
{
SDA=0; //上一个状态的SCL=0,这个状态设置SDA=0,目的是让状态能反转
Delay_us(2);

SCL=1; //该时刻设置SCL=1,然后就可以让数据稳定在改状态下。
Delay_us(2);

SDA=1;
Delay_us(4);
}

unsigned char EEPROM_Write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data)
{
unsigned char u_wait_err = 0;

EEPROM_Start();
EEPROM_Send_Byte(c_slave_address7bit < 1);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Send_Byte(c_reg_address);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Send_Byte(u_data);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Stop();

if( u_wait_err == 0)
return 0;
return 1;

}

unsigned char EEPROM_Read(unsigned char c_slave_address7bit,unsigned char c_reg_address)
{
unsigned char u_temp;
unsigned char u_wait_err = 0;

EEPROM_Start();
EEPROM_Send_Byte(c_slave_address7bit < 1);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Send_Byte(c_reg_address);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Start();
EEPROM_Send_Byte((c_slave_address7bit < 1)+1);
u_wait_err |= EEPROM_Wait_Ack();

u_temp = EEPROM_Read_Byte( );
EEPROM_No_Ack();//不需要响应

EEPROM_Stop();

return u_temp;

}

unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_read_arr[],unsigned int len)
{
unsigned char u_wait_err = 0;
int i = 0;

EEPROM_Start();
EEPROM_Send_Byte(c_slave_address7bit < 1);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Send_Byte(c_reg_address);
u_wait_err |= EEPROM_Wait_Ack();

EEPROM_Start();
EEPROM_Send_Byte((c_slave_address7bit < 1)+1);
u_wait_err |= EEPROM_Wait_Ack();

for(i = 0 ; i < len - 1 ; i ++)
{
c_continue_read_arr[i] = EEPROM_Read_Byte( );

EEPROM_Ack();
}

c_continue_read_arr[len-1] = EEPROM_Read_Byte( );
//u_wait_err |= EEPROM_Wait_Ack();
EEPROM_No_Ack();//不需要响应

EEPROM_Stop();

if(u_wait_err == 0)
return 0;
return 1;
}

unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_write_arr[],unsigned int len)
{
unsigned int i;
unsigned int i_err = 0;

EEPROM_Start();
EEPROM_Send_Byte(c_slave_address7bit < 1);
i_err |= EEPROM_Wait_Ack();

EEPROM_Send_Byte(c_reg_address);
i_err |= EEPROM_Wait_Ack();

for( i = 0 ; i < len ; i ++ )
{
EEPROM_Send_Byte(c_continue_write_arr[i]);

i_err |= EEPROM_Wait_Ack();
}

EEPROM_Stop();

if(i_err == 0)
return 0;

return 1;
}

unsigned char read_eeprom_status(unsigned char c_slave_address7bit)
{
unsigned int i = 0;
int i_ret = 0;

do
{
EEPROM_Start();
EEPROM_Send_Byte(c_slave_address7bit < 1);

i_ret = EEPROM_Wait_Ack();

i ++;
if(i >= 10000)
{
EEPROM_Stop();
return 1;//表示无响应
}
}while(i_ret);

EEPROM_Stop();

return 0;//表示操作序列结束
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top