新聞中心

8051模擬IIC操作EEPROM

作者: 時(shí)間:2016-12-03 來(lái)源:網(wǎng)絡(luò) 收藏
注:
本篇內(nèi)容和STM32模擬IIC操作EEPROM思路是一樣的,是一個(gè)程序到不同平臺(tái)的移植。

首先是EEPROM.h文件內(nèi)容:

#ifndef _eeprom_h_
#define _eeprom_h_

#include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
#include

#define EEPROM_ADDRESS 0x57

sbit SDA = P1^2; //EEPROM的數(shù)據(jù)線
sbit SCL = P1^1; //EEPROM的時(shí)鐘線
sbit WP = P1^0; //EEPROM的寫保護(hù),給低電平表示讀寫均允許,也就是標(biāo)準(zhǔn)的模式。

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

本文引用地址:http://m.butianyuan.cn/article/201612/325194.htm
再個(gè)就是EEPROM.c文件的內(nèi)容:

#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電路:
* 單片機(jī) EEPROM
* P10--------->WP
* P11--------->SCL
* P12--------->SDA
*
* A0,A1,A2均通過(guò)硬件拉高電平
*
* 我這里將EEPROM的地址按照如下方式規(guī)劃:
* 0101 0(A2)(A1)(A0)
* 因此EEPROM的地址為0x57.
*
* copyright by wit_yuan 2016-09-15 at 龍興園北區(qū)
-------------------------------------------------------------------------------*/
void EEPROM_Init()
{
//將WP設(shè)置為低電平即可
WP = 0;
//將IIC總線置高即可
SCL = 1;
SDA = 1;
}

/*
*
* EEPROM_Start():
* 內(nèi)部函數(shù)
*
*/
static void EEPROM_Start()
{
SDA=1; //由于上一個(gè)SCL狀態(tài)是0或者是1,要讓SDA穩(wěn)定輸出,都可以設(shè)置為1
Delay_us(2);

SCL=1; //讓SCL發(fā)生變化,為0不變,為1則變化,表明數(shù)據(jù)可以變動(dòng)了。
Delay_us(2);

SDA=0; //SDA線數(shù)據(jù)變化,從而可以保證發(fā)出的是start信號(hào)。
Delay_us(2);

SCL=0; //將I2C總線鉗住,下一個(gè)時(shí)間SDA可以輸出高低電平。
Delay_us(4);
}

/*
*
* EEPROM_Send_Byte():
* 內(nèi)部函數(shù)
*
*/
static void EEPROM_Send_Byte( unsigned char txd)
{
unsigned char t;
// SDA_OUT();
SCL=0;//拉低時(shí)鐘開始數(shù)據(jù)傳輸
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():
* 內(nèi)部函數(shù)
*
*/
static unsigned char EEPROM_Read_Byte()
{
unsigned char i,u_receive=0;
// SDA_IN();//SDA設(shè)置為輸入
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():
* 內(nèi)部函數(shù)
* 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():
* 內(nèi)部函數(shù)
*
*/
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; //超時(shí),表明數(shù)據(jù)傳輸有問(wèn)題
}
}
SCL=1;
Delay_us(1);


SCL=0;//時(shí)鐘輸出0
Delay_us(2);

return 0;
}

/*
*
* EEPROM_No_Ack():
* 內(nèi)部函數(shù)
*
*/
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():
* 內(nèi)部函數(shù)
*
*/
static void EEPROM_Stop()
{
SDA=0; //上一個(gè)狀態(tài)的SCL=0,這個(gè)狀態(tài)設(shè)置SDA=0,目的是讓狀態(tài)能反轉(zhuǎn)
Delay_us(2);

SCL=1; //該時(shí)刻設(shè)置SCL=1,然后就可以讓數(shù)據(jù)穩(wěn)定在改狀態(tài)下。
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();//不需要響應(yīng)

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();//不需要響應(yīng)


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;//表示無(wú)響應(yīng)
}
}while(i_ret);


EEPROM_Stop();

return 0;//表示操作序列結(jié)束
}

貼上usart.h文件的內(nèi)容:

#ifndef _usart_h_
#define _usart_h_

#include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
#include


extern void UART_Init(void);

extern void Send_String(unsigned char *u_string);

extern void Send_UHex(unsigned char u_tx);

#endif

然后是usart.c文件的內(nèi)容:

#include "usart.h"

/*------------------------------------------------
串口通訊初始化
------------------------------------------------*/
void UART_Init(void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重裝
TH1 = 0xFD; // TH1: 重裝值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打開
TI = 1;
}

/*
* Send_UChar:
* 發(fā)送單個(gè)字符
*
*
*/
void Send_UChar(unsigned char u_tx)
{
SBUF = u_tx;
while(!TI);
TI = 0;
}

/*
* Send_String:
* 發(fā)送字符串
*
*
*/
void Send_String(unsigned char *u_string)
{
while(*u_string)
{
Send_UChar(*u_string);
u_string++;
}
}

void Send_UHex(unsigned char u_tx)
{
unsigned char u_high;
unsigned char u_low;

u_high = u_tx/16 ;
u_low = u_tx%16 ;

if((u_high >= 10) && (u_high <= 15))
{
u_high = (u_high - 10) + A;
}
else
{
u_high = u_high + 0;
}
if((u_low >= 10) && (u_low <= 15))
{
u_low = (u_low - 10) + A;
}
else
{
u_low = u_low + 0;
}
Send_UChar(u_high);
Send_UChar(u_low);
Send_UChar( );
}


最后就是main.c文件的內(nèi)容:

/*-------------------------------------------------------------------------------
* 名稱:51單片機(jī)控制EEPROM
* 晶振使用11.0592M
*
* I2C電路:
* 單片機(jī) EEPROM
* P10--------->WP
* P11--------->SCL
* P12--------->SDA
*
* A0,A1,A2均通過(guò)硬件拉高電平
*
* copyright by wit_yuan 2016-09-15 at 龍興園北區(qū)
-------------------------------------------------------------------------------*/
#include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
#include
#include
#include "usart.h"

unsigned char g_c_continue_write[16];
unsigned char g_c_continue_read_array[16];

/*------------------------------------------------
主函數(shù)
------------------------------------------------*/
void main (void)
{
unsigned char value,i;



UART_Init();

EEPROM_Init();

Send_String("--------------------app run-----------------n");

#if 0
EEPROM_Write(EEPROM_ADDRESS,0,0x02);

for(i = 0 ; i < 100 ; i ++);
for(i = 0 ; i < 100 ; i ++);
for(i = 0 ; i < 100 ; i ++);

value = EEPROM_Read(EEPROM_ADDRESS,0);

Send_String("n value :");
Send_UHex(value);
Send_String("n ");
#else

#if 1
Send_String("array :n");

for(i = 0 ; i < 16 ; i ++)
{
g_c_continue_write[i] = i + 1;
Send_UHex(g_c_continue_write[i]);
}
Send_String("n");


Send_String("write array : n");
value = eeprom_continue_write(EEPROM_ADDRESS,0,g_c_continue_write,16);


Send_String("read write status : n");
#if 1
value = read_eeprom_status(EEPROM_ADDRESS);

Send_String("n status :");
Send_UHex(value);
Send_String("n ");
#endif
#endif

#if 1
Send_String("read array : n");

eeprom_continue_read(EEPROM_ADDRESS,0,g_c_continue_read_array,16);

Send_String("read:n");
for(i = 0 ; i < 16 ; i ++)
{
Send_UHex(g_c_continue_read_array[i]);
}
Send_String("n");


value = EEPROM_Read(EEPROM_ADDRESS,0x0D);

Send_String("n value :");
Send_UHex(value);
Send_String("n ");
#endif
#endif

Send_String("n ----------app end----------------n");
while (1) //主循環(huán)
{



}
}

更多的具體講解,就參考stm32模擬IIC操作EEPROM那篇文章吧。



關(guān)鍵詞: 8051模擬IIC操作EEPRO

評(píng)論


技術(shù)專區(qū)

關(guān)閉