视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
24C子程序
2025-10-02 15:02:49 责编:小OO
文档
/*24C子程序 */

bit   I2C_Start(void);

void  I2C_Stop(void);

void  I2C_Ack(void);

void  I2C_Nack(void);

bit   I2C_Send_Byte( uchar);

uchar I2C_Receive_Byte(void);

void  AT24C_R(void *mcu_address,uint AT24C_address,uint count);

void  AT24C_W(void *mcu_address,uint AT24C_address,uint count);

void  Delay_10_uS(void)

{

      char i=10;

      while(i--);

}

void Delay_N_mS( uint n_milisecond)  /* n mS delay */

{

         uchar i;

         while(n_milisecond--)

        {

                 i=37;

                 while(i--);

        }

}

bit I2C_Start(void)

{

        Delay_10_uS();

        I2C_SDA =1;

        Delay_10_uS();

        I2C_SCK =1;

        Delay_10_uS();

        if ( I2C_SDA == 0) return 0;

        if ( I2C_SCK == 0) return 0;

        I2C_SDA = 0;

        Delay_10_uS();

        I2C_SCK = 0;

        Delay_10_uS();

        return 1;

}

void  I2C_Stop(void)

{

       Delay_10_uS();

       I2C_SDA = 0;

       Delay_10_uS();

       I2C_SCK = 1;

       Delay_10_uS();

       I2C_SDA = 1;

       Delay_10_uS();

}

void I2C_Ack(void)

{

       Delay_10_uS();

       I2C_SDA=0;

       Delay_10_uS();

       I2C_SCK=1;

       Delay_10_uS();

       I2C_SCK=0;

       Delay_10_uS();

}

void I2C_Nack(void)

{

        Delay_10_uS();

        I2C_SDA=1;

        Delay_10_uS();

        I2C_SCK=1;

        Delay_10_uS();

        I2C_SCK=0;

        Delay_10_uS();

}

bit I2C_Send_Byte( uchar d)

{

         uchar i = 8;

         bit bit_ack;

         while( i-- )

         {

                    Delay_10_uS();

                    if ( d &0x80 )   I2C_SDA =1;

                    else             I2C_SDA =0;

                    Delay_10_uS();

                    I2C_SCK = 1;

                    Delay_10_uS();

                    I2C_SCK = 0;

                     d = d << 1;

        }

        Delay_10_uS();

        I2C_SDA = 1;

        Delay_10_uS();

        I2C_SCK = 1;

        Delay_10_uS();

        bit_ack = I2C_SDA;

        I2C_SCK =0;

        Delay_10_uS();

        return bit_ack;

}

uchar I2C_Receive_Byte(void)

{

           uchar i = 8, d;

            Delay_10_uS();

            I2C_SDA = 1;

            while ( i--)

            {

                       d = d << 1;

                       Delay_10_uS();

                       I2C_SCK =1;

                       if ( I2C_SDA )         d++;

                       Delay_10_uS();

                       I2C_SCK =0;

           }

           return d;

}

void AT24C_W(void *mcu_address,uint AT24C_address,uint count)

{

            DOG_WDI=!DOG_WDI;

            DOGTIME=0;

            while(count--)

            {

                         I2C_Start();

  /*I2C_Send_Byte( 0xa0 + AT24C_address /256 *2);*/  /* 24C16  USE */

                          I2C_Send_Byte( 0xa0 );

                          I2C_Send_Byte(  AT24C_address/256 );

                          I2C_Send_Byte( AT24C_address %256 );

                          I2C_Send_Byte( *(uchar*)mcu_address );

                          I2C_Stop();

                          Delay_N_mS(10);       /* waiting for write cycle to be completed */

                          ((uchar*)mcu_address)++;

                          AT24C_address++;

            }

}

void AT24C_R(void *mcu_address,uint AT24C_address,uint count)

{

                DOG_WDI=!DOG_WDI;

                DOGTIME=0;

                while(count--)

               {

                              I2C_Start();

  /*I2C_Send_Byte( 0xa0 + AT24C_address / 256 *2 );*/   /* 24C16 USE */

                              I2C_Send_Byte( 0xa0 );

                              I2C_Send_Byte( AT24C_address/256 );

                              I2C_Send_Byte( AT24C_address % 256 );

                              I2C_Start();

  /*I2C_Send_Byte( 0xa1 + AT24C_address /256 *2 );*/

                              I2C_Send_Byte( 0xa1 );

                             *(uchar*)mcu_address = I2C_Receive_Byte();

                              I2C_Nack();

                              I2C_Stop();

                              ((uchar*)mcu_address)++;

                              AT24C_address++;

               }

}

// AT24C 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; iTWCR = _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;

}

附录:

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

;STCC51读写AT24C汇编程序

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

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_AT24C

ACALL   DELAY

ACALL   READ_AT24C

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_AT24C:

ACALL           START                     ;发送起始条件

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

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

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_AT24C:                             ;读AT24C

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

MOV             A,    #0A0H

ACALL           SENTBYTE                  ;AT24C总线地址

JB              F0,  RCVRETURN          ;出错返回

MOV             R0,  #SDADR              ;取存储地址

MOV             A,    @R0

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

JB              F0,  SENDRETURN         ;出错返回

INC             R0

MOV             A,    @R0

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

JB              F0,  SENDRETURN

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

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

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下载本文

显示全文
专题