1. 首页
  2. 课程学习
  3. 嵌入式
  4. at24c64读写程序

at24c64读写程序

上传者: 2023-01-07 13:56:32上传 TXT文件 8.162 KB 热度 8次

// AT24C64 support functions using ATMEGA's TWI

// pin-WP is hard-wired to GND

// fuctions work better outside interrupt routines

// by MXH, 2003/07/30

#i nclude "DStruct.h"

#i nclude

// CONSTANTS DEFINITION FOR EEPROM

#define EEADDR 0

#define EEWR 0

#define EERD 1

// TWINT *NOT* set after STOP condition is sent

// check status?

// TWSTO is cleared by hardware

#define TwiStop() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO)

#define TwiStart() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA)

#define TWI_STATUS (TWSR & 0xF8)

BYTE byEEWait;

//////////////////////////////////////////////////////////////////////////

// implementation

BOOL EEPStart(BYTE addr, BOOL bWrite)

{

byEEWait = 10; // 90~100ms

poll_ack:

TwiStart();

while (!(TWCR & (1<

if ( byEEWait == 0 ){

return FALSE;

}

}

if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START))

goto poll_ack;

//byEEWait = 3; // 20~30ms

// send SLA+R/W

TWDR = addr | bWrite;

TWCR = (1<

while (!(TWCR & (1<

if( byEEWait == 0 ){

TwiStop();

return FALSE;

}

}

if( EEWR == bWrite ){ // MT mode

//if(TWI_STATUS != TW_MT_SLA_ACK)

switch(TWI_STATUS){

case TW_MT_SLA_ACK:

break;

case TW_MT_SLA_NACK:

goto poll_ack;

default:

TwiStop();

return FALSE;

}

}else{ // MR mode

if(TWI_STATUS != TW_MR_SLA_ACK)

return FALSE;

}

return TRUE;

}

//////////////////////////////////////////////////////////////////////

//

BYTE EEPWrite( WORD uiAddress, WORD uiLen, void *pBuf ) //using 0

{

unsigned int i,j,uiCnt;

if( uiLen == 0 ) return 0;

uiCnt = 0;

// uiEnd = uiAddress + uiLen;

i = uiAddress;

do{

if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in

return 0;

}

TWDR = (BYTE)((i>>8)&0x00ff); // MSB of address

TWCR = (1<

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if(TWI_STATUS != TW_MT_DATA_ACK){

return FALSE;

}

TWDR = (BYTE)(i&0x00ff); // LSB of address

TWCR = (1<

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if(TWI_STATUS != TW_MT_DATA_ACK)

return FALSE;

// write data

for( j=0; j<32; j++ ){

TWDR = ((BYTE*)pBuf)[uiCnt];

TWCR = (1<

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if(TWI_STATUS != TW_MT_DATA_ACK){

return FALSE;

}

i++;

uiCnt++;

if(( 0 == i%32 )||( uiCnt == uiLen )){

TwiStop();

break;

}

}

}while( uiCnt < uiLen );

// while( !PollAck());

return 1;

}

//////////////////////////////////////////////////////////////////////

//

BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf )

{

UINT i;

if ( uiLen == 0 ) return 0;

if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in

return 0; //↑

} // not RD but write device address to the chip

TWDR = (BYTE)(( uiAddress >> 8) & 0x00ff ); //((BYTE*)(&uiAddress))[1]; // MSB of address

TWCR = (1<

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if (TWI_STATUS != TW_MT_DATA_ACK)

return FALSE;

TWDR = (BYTE)( uiAddress & 0x00ff ); //((BYTE*)(&uiAddress))[0]; // LSB of address

TWCR = (1<

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if (TWI_STATUS != TW_MT_DATA_ACK)

return FALSE;

if(!EEPStart(0xA0+EEADDR,EERD)){ //PollAck()){

return 0; //↑

}// ??? how to read?

for ( i=0; i

TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWEA);

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

if (TWI_STATUS != TW_MR_DATA_ACK)

return FALSE;

((BYTE*)pBuf)[i] = TWDR; // EEInByte();

}

TWCR = _BV(TWINT) | _BV(TWEN); // send NACK to indicate final byte

byEEWait = 3; // 20~30ms

while (!(TWCR & (1<

if( byEEWait == 0 )

return FALSE;

}

//if (TWI_STATUS != TW_MR_DATA_ACK)

// return FALSE;

((BYTE*)pBuf)[i] = TWDR;

TwiStop();

return 1;

}

附录:

;============================

;STC89C51读写AT24C64汇编程序

;===========================

BITCNT    EQU       42H

SDADR     EQU       40H

SDA       BIT         P0.1

SCL       BIT         P0.0

ORG       0000H

JMP        MAIN

ORG       0100H

MAIN:

MOV      R7,  #01010101B

ACALL   WRITE_AT24C64

ACALL   DELAY

ACALL   READ_AT24C64

MOV      P3,  A

ACALL   DELAY

;ACALL  显示、键盘子程序

JMP        MAIN    

;=============================

DELAY:

MOV       R6,  #0FFH

DELAY0:

MOV       R5,  #0FFH

DELAY1:              

DJNZ      R5,  DELAY1

DJNZ      R6,  DELAY0

RET

;=============================

WRITE_AT24C64:

ACALL           START                     ;发送起始条件

MOV              A,    #0A0H              ;AT24C64总线地址

ACALL           SENTBYTE                  ;发送AT24C64器件总线地址

JB              F0,  SENDRETURN           ;出错返回

MOV             R0,  #SDADR               ;取存储地址

MOV             A,    @R0

ACALL           SENTBYTE

JB              F0,  SENDRETURN

INC             R0

MOV             A,    @R0

ACALL           SENTBYTE

JB              F0,  SENDRETURN

MOV             A,    R7

ACALL           SENTBYTE                   ;发送一次数据

JB              F0,  SENDRETURN            ;出错返回

ACALL           STOP                       ;发送停止条件

DELAY10:     

MOV             R4,  #30H                  ;延时10mS等待数据写完

DELAY11:

MOV             R3,  #34H

DJNZ            R3,  $

DJNZ            R4,        DELAY11

SENDRETURN:

RET

;=============================

READ_AT24C64:                             ;读AT24C64

ACALL           START                     ;发送IC总线起始条件

MOV             A,    #0A0H

ACALL           SENTBYTE                  ;AT24C64总线地址

JB              F0,  RCVRETURN          ;出错返回

MOV             R0,  #SDADR              ;取存储地址

MOV             A,    @R0

ACALL           SENTBYTE                  ;发送AT24C64器件总线地址

JB              F0,  SENDRETURN         ;出错返回

INC             R0

MOV             A,    @R0

ACALL           SENTBYTE                  ;发送AT24C64器件总线地址

JB              F0,  SENDRETURN

ACALL           START                     ;发送IC总线重复起始条件

MOV              A,    #0A0H              ;AT24C64总线地址

SETB            ACC.0                    ;取总线读操作数

ACALL           SENTBYTE                  ;发送被控制总线地址

JB              F0,  RCVRETURN          ;出错返回

ACALL           RCVBYTE                   ;接收数据

RCVRETURN:

RET

;===============================

START:

SETB            SDA            ;发送起始条件的数据信号

NOP

SETB            SCL            ;发送起始条件的时钟信号

NOP

CLR             SDA            ;发送起始信号

NOP

CLR              SCL           ;准备发送或接收数据

RET

;===============================

STOP:

CLR        SDA                  ;发送停止条件的数据信号

NOP

SETB       SCL                  ;发送停止条件的时钟信号

NOP

SETB       SDA                  ;发送总线停止信号

NOP

RET

;==============================

SENTBYTE:                         ;送数8位

MOV         BITCNT,#08H

SENTB:

RLC        A                     ;要发送的数据左移,发送入位C

MOV        SDA,      C

SETB       SCL                     ;置时钟线为高,通知被控制开始接

收数据位

CLR        SCL                     ;准备接收下一个数据位

DJNZ       BITCNT,SENTB            ;8位没发送完继续发送

SETB       SDA                     ;8位发送完后释放数据线准备收应答位

SETB       SCL                     ;开始接收应答信号

CLR        F0                      ;预先清发送数据出错标志

JNB        SDA,      ACKEND        ;判断是否接收应答信号正常转ACKEND

SETB       F0                      ;未收到应答置位错误标志

ACKEND:

CLR        SCL                     ;发送结束准备下次发送或接收数据

RET

;==============================

RCVBYTE:

SETB        SDA                     ;置数据线为输入方式

MOV         BITCNT,#08H             ;传送的数据长度为8位

RCV:

CLR         SCL                     ;置时钟线为低,准备接收数据

SETB        SCL                     ;置时钟线为高使数据线上数据有效

MOV         C,    SDA

RLC        A                       ;接收的数据位放入ACC

DJNZ        BITCNT,RCV              ;8位没收完继续接收

CLR        SCL                     ;8位接收完置时钟线和数据线

CLR        SDA

SETB        SDA                     ;接收非应答信号

SETB        SCL                     ;置时钟线为高使应答位有效

SETB        SDA

CLR        SCL                     ;清时钟线以便发送停止条件

RET

;============================

;显示、键盘子程序

;===========================

END

下载地址
用户评论