查看: 734|回复: 0
打印 上一主题 下一主题

访问空间大于 64 KB 外部扩展随机存储器的C和汇编读写程序

[复制链接]
跳转到指定楼层
沙发
发表于 2016-5-20 23:21:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面函数中的C语言和在线汇编语言完成的功能一致,仅效率不对,C语言所用的时间约为在线汇编语言的2倍。





/*

****************************************************************************************

头部文件名:        Access_Extended_SRAM.h

头部文件名称:      访问空间大于 64 KB 外部扩展随机存取存储器的头部文件

文件版本:        1.0

文件功能:

    本文件是对访问空间大于 64 KB 外部扩展随机存取存储器源程序文件的常量、

    数据结构类型进行定义和函数原型声明的头部文件。

文件说明:

    本头部文件不允许用于无扩展并行总线结构的微处理器。

编译工具软件:      IAR Embedded Workbench for Atmel AVR 版本:4.10 以上

链接文件:          目标器件芯片的头部文件



编作者:            

编作者 E-Mail:     PTZSW@163.COM

编制日期:          2005年9月12日

------------------------------------------------------------------------------

头部文件版本历史:

2005年9月12日 -------- 版本 1.0 :发行版本

****************************************************************************************

*/





/*======================================================================================

下面两条指令是本头部文件条件编译的预处理指令,用于防止本头部文件被其他文件重复引用。

======================================================================================*/

#ifndef ACCESS_EXTENDED_SRAM_H        // "ACCESS_EXTENDED_SRAM_H" 条件编译开始

#define ACCESS_EXTENDED_SRAM_H





/*======================================================================================

              本头部文件包括的其他头部文件

======================================================================================*/

#include "MCU_C_Macro_Data_Define.h"  // 包含数据类型和常用指令宏定义的头部文件





/*======================================================================================

下面这三条指令是用于区分编译系统为 C++ 或 C 的预处理指令。

"__cplusplus" 为 C++ 预处理器名字,这三条指令表明接在其下面的那些指令为 C 程序特征。

======================================================================================*/

#ifdef __cplusplus

extern "C" {

#endif





/*======================================================================================

使用 Access_Extended_SRAM.c 源程序文件中的函数声明(使用C或汇编语言编制的函数声明):

======================================================================================*/

#define USE_ASM_EXTSRAM_BLACK_ACCESS  // 使用汇编语言编制的函数声明

                                        // 注:屏蔽此即使用C语言编制的函数





/*======================================================================================

外部扩展随机存取存储器的地址引脚定义:

注:下列这些定义与硬件设计相关,如需改变地址引脚仅在此重新定义即可。

======================================================================================*/

#define EXTSRAM_ADDR_DDR  DDRD        // 扩展随机存储器的地址高位引脚的数据方向寄存器

#define EXTSRAM_ADDR_PORT PORTD       // 扩展随机存储器的地址高位引脚的的数据寄存器





/*======================================================================================

声明外部扩展随机存取存储器访问空间大小:

======================================================================================*/

#define EXTSRAM_ADDR_START    0x1100  // 外部扩展随机存取存储器每页的起始地址

#define EXTSRAM_ADDR_END      0xFFFF  // 外部扩展随机存取存储器每页的终止地址

#define EXTSRAM_ADDR_H_START  0x80    // 外部扩展随机存取存储器寻址高位的起始地址

#define EXTSRAM_ADDR_H_END    0xFF    // 外部扩展随机存取存储器寻址高位的终止地址









/*======================================================================================

源程序文件中使用的全局静态变量定义:

======================================================================================*/

/*----------------------------------------------------------------------------

定义用于储存外部扩展随机存取存储器访问地址的指针数值变量:

----------------------------------------------------------------------------*/

#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_suppress=Pe550           //  禁止编译时产生 Pe550 消息

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束



static unsigned int es_addr_read_index = EXTSRAM_ADDR_START;

                       // 读取数据操作访问地址的寻址低位指针数值变量

static unsigned int es_addr_write_index = EXTSRAM_ADDR_START;

                       // 写入数据操作访问地址的寻址低位指针数值变量

static unsigned char es_addr_read_h_index = (EXTSRAM_ADDR_H_START+1);

                       // 读取数据操作访问地址的寻址高位指针数值变量

static unsigned char es_addr_write_h_index = (EXTSRAM_ADDR_H_START+1);

                       // 写入数据操作访问地址的寻址高位指针数值变量

static unsigned char es_addr_read_h_index_status = 0;

                       // 读取数据操作访问地址的寻址高位指针状态变量

static unsigned char es_addr_write_h_index_status = 0;

                       // 写入数据操作访问地址的寻址高位指针状态变量



#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_default=Pe550            // Pe550 消息复原为默认设置

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束





/*----------------------------------------------------------------------------

定义用于储存上面相应的指针数值变量的EEPROM中的数组变量:

定义这些数组变量的目的,在于防止掉电时丢失操作地址的指针数值。在上电后重新初始化时,

将从这些数组变量中恢复操作地址的指针数值。

----------------------------------------------------------------------------*/

eeprom unsigned int es_addr_read_index_eep[1];

eeprom unsigned int es_addr_write_index_eep[1];

eeprom unsigned char es_addr_read_h_index_eep[1];

eeprom unsigned char es_addr_write_h_index_eep[1];

eeprom unsigned char es_addr_read_h_index_status_eep[1];

eeprom unsigned char es_addr_write_h_index_status_eep[1];





/*======================================================================================

Access_Extended_SRAM.c 源程序文件中的函数原型声明:

======================================================================================*/

/*----------------------------------------------------------------------------

函数功能:    本函数用于本函数用于以块方式访问空间大于 64 KB 外部随机存储器的

              初始化操作。

备注:        本函数仅在主函数中调用一次即可。

----------------------------------------------------------------------------*/

void ExtSRAM_Black_initialization(void);



/*----------------------------------------------------------------------------

函数功能:    本函数用于以块方式访问空间大于 64 KB 外部随机存储器的写入数据操作。

函数入口参数:*first_data_address ------ 写入外部扩展随机存取存储器的首个数据地址指针。

              data_length -------------- 写入的数据长度。

全局静态变量:es_addr_write_h_index ---------- 写入数据操作访问地址的寻址低位指针数值变量

              es_addr_write_index ------------ 写入数据操作访问地址的寻址高位指针数值变量

              es_addr_write_h_index_status --- 写入数据操作访问地址的寻址高位指针状态变量

备注:        ▲.本函数用于外部扩展随机存取存储器寻址指针不超过2个字节。

              ▲.本函数写入的目标存储器空间将循环操作,即到达空间尾部时又返回到起始处,

                  覆盖以前写入的数据继续执行写入操作。

----------------------------------------------------------------------------*/

void ExtSRAM_Black_Write(unsigned char *first_data_address,

                         // 写入外部扩展随机存取存储器的首个数据地址指针

                         unsigned int data_length);

                         // 写入的数据长度



/*----------------------------------------------------------------------------

函数功能:    本函数用于以块方式访问空间大于 64 KB 外部随机存储器的读取数据操作。

函数入口参数:*first_data_address ------ 将读取的数据存储到目标的首个地址指针。

              data_length -------------- 读取的数据长度。

全局静态变量:es_addr_read_h_index ---------- 读取数据操作访问地址的寻址低位指针数值变量

              es_addr_read_index ------------ 读取数据操作访问地址的寻址高位指针数值变量

              es_addr_read_h_index_status --- 读取数据操作访问地址的寻址高位指针状态变量

备注:        ▲.本函数用于外部扩展随机存取存储器寻址指针不超过2个字节。

              ▲.本函数读取的源存储器空间将循环操作,即到达空间尾部时又返回到起始处,

                  继续执行读取数据操作。

----------------------------------------------------------------------------*/

void ExtSRAM_Black_Read(unsigned char *first_data_address,

                        // 将读取的数据存储到目标的首个地址指针

                        unsigned int data_length);

                        // 读取的数据长度



/*----------------------------------------------------------------------------

函数功能:    本函数用于计算从大于 64 KB SRAM 中以固定数据长度访问数据,从

              读取操作的访问地址到写入操作的访问地址之间所需要的次数值。

函数入口参数:read_h -------- 读取操作的访问地址高位指针数值。

              write_h ------- 写入操作的访问地址高位指针数值。

              read ---------- 读取操作的访问地址低位指针数值。

              write --------- 写入操作的访问地址低位指针数值。

              data_size ----- 每次访问操作的地址个数(数据长度)。

              入口参数还包括这些用于表示存储器特征的静态变量:

              IN_all_data_start_size -------- 访问地址低位的起始地址指针数值

              IN_all_data_end_size ---------- 访问地址低位的终止地址指针数值

              IN_all_data_h_start_size ------ 访问地址高位的起始地址指针数值

              IN_all_data_h_end_size -------- 访问地址高位的终止地址指针数值

函数出口参数:所需要的整数次数值(包括余数的次数)。

              出口参数还包括余数的静态变量:

              OUT_data_size_remainder ------- 最后一次访问操作的地址个数(余数)

备注:        ▲.函数出口参数为了其他函数的判断方便,预留次数值=0,给其他

                  函数使用。返回的函数出口参数=实际次数值(包括余数的次数)+1。

                  在其他函数中,当次数值为1时,访问操作已全部完成;当次数值

                  为2时,即执行访问余数操作。

              ▲.本函数实际包括9个入口参数和2个出口参数。

----------------------------------------------------------------------------*/

unsigned int EXTSRAM_Data_Access_Times(unsigned char read_h,

                                       // 读取操作的访问地址高位指针数值

                                       unsigned char write_h,

                                       // 写入操作的访问地址高位指针数值

                                       unsigned int read,

                                       // 读取操作的访问地址低位指针数值

                                       unsigned int write,

                                       // 写入操作的访问地址低位指针数值

                                       const unsigned char data_size);

                                       // 每次访问操作的地址个数(数据长度)





/*======================================================================================

下面这三条指令是用于与上面三条区分编译系统为 C++ 或 C 的预处理指令相对应。用于指定

extern "C" 链接指示符作用域,此处的"}"与上面的"{"相对应,为链接指示符作用结束符。

======================================================================================*/

#ifdef __cplusplus

}

#endif







#endif                                // "ACCESS_EXTENDED_SRAM_H" 条件编译结束







/*

****************************************************************************************

                             本头部文件到此结束

****************************************************************************************

*/



/*

****************************************************************************************

源程序文件名:      Access_Extended_SRAM.c

源程序名称:        访问空间大于 64 KB 外部扩展随机存取存储器的源程序文件

程序版本:        1.0

程序功能:

    本程序是用于访问空间大于 64 KB (即:地址指针数大于两个字节)外部扩展

    随机存取存储器的源程序文件。

程序说明:

    ▲.本源程序文件中的函数不允许用于无扩展并行总线结构的微处理器。

      ▲.注意:本源程序文件中的函数仅可用于外部扩展随机存取存储器空间大小为 64 KB

        的微处理器,即外部扩展随机存取存储器寻址指针不超过2个字节。

函数入口参数:

函数出口参数:



编译工具软件:      IAR Embedded Workbench for Atmel AVR 版本:4.10 以上

链接子程序文件:



编作者:            

编作者 E-Mail:     PTZSW@163.COM

编制日期:          2005年9月12日

------------------------------------------------------------------------------

适用器件芯片类型:   Atmel 公司生产的8位 RISC 单片机

器件芯片时钟频率:

存储器模式:        大存储器模式

外部扩展存储器大小:65536 【字节】

数据堆栈大小:      256 【字节】

------------------------------------------------------------------------------

源程序版本历史:

2005年9月12日 -------- 版本 1.0 :发行版本

****************************************************************************************

*/



/*======================================================================================

              本源程序包括的头部文件

======================================================================================*/

#include "Access_Extended_SRAM.h"    // 本程序的头部文件





/*======================================================================================

                              程序指令代码清单

======================================================================================*/

/*----------------------------------------------------------------------------

函数功能:    本函数用于本函数用于以块方式访问空间大于 64 KB 外部随机存储器的

              初始化操作。

备注:        本函数仅在主函数中调用一次即可。

----------------------------------------------------------------------------*/

void ExtSRAM_Black_initialization(void)

{

  #if defined(MCU_TYPE_IS_ATMEGA64) || defined(MCU_TYPE_IS_ATMEGA128)

      // 目标器件芯片为 ATmega64 和 ATmega128 的条件编译

    MCUCR = ((1<<SRE)|(1<<SRW10)) ;             // 使能外部扩展随机存储器接口、

             // 读/写操作插入2个等待周期。输出新地址之前还要插入1个等待周期

    XMCRA = ((1<<SRW01)|(1<<SRW00)|(1<<SRW11)) ;

             // 读/写操作插入2个等待周期。输出新地址之前还要插入1个等待周期

    XMCRB = (1<<XMBK) ;                         // 使能外部扩展随机存储器总线保持功能

  #else

    #error 函数  " ExtSRAM_Black_initialization "  错误!没有对外部扩展随机存取存储器接口进行设置。

  #endif  // 条件编译结束

  EXTSRAM_ADDR_DDR = 0xFF ;                     // 设置寻址高位的数据端口为输出引脚

  EXTSRAM_ADDR_PORT = EXTSRAM_ADDR_H_START ;    // 置寻址高位在 64KB 空间地址内

  // 从EEPROM中各读入寻址指针的数值到随机存储器,恢复到掉电状态前的数值。

  es_addr_read_h_index = es_addr_read_h_index_eep[0] ;

  es_addr_read_index = es_addr_read_index_eep[0] ;

  es_addr_write_h_index = es_addr_write_h_index_eep[0] ;

  es_addr_write_index = es_addr_write_index_eep[0] ;

  es_addr_read_h_index_status = es_addr_read_h_index_status_eep[0] ;

  es_addr_write_h_index_status = es_addr_write_h_index_status_eep[0] ;

}



/*----------------------------------------------------------------------------

函数功能:    本函数用于以块方式访问空间大于 64 KB 外部随机存储器的写入数据操作。

函数入口参数:*first_data_address ------ 写入外部扩展随机存取存储器的首个数据地址指针。

              data_length -------------- 写入的数据长度。

全局静态变量:es_addr_write_h_index ---------- 写入数据操作访问地址的寻址低位指针数值变量

              es_addr_write_index ------------ 写入数据操作访问地址的寻址高位指针数值变量

              es_addr_write_h_index_status --- 写入数据操作访问地址的寻址高位指针状态变量

备注:        ▲.本函数用于外部扩展随机存取存储器寻址指针不超过2个字节。

              ▲.本函数写入的目标存储器空间将循环操作,即到达空间尾部时又返回到起始处,

                  覆盖以前写入的数据继续执行写入操作。

----------------------------------------------------------------------------*/

#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_suppress=Pe826,Pe940     // 禁止编译时产生 Pe826,Pe940 消息

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束



void ExtSRAM_Black_Write(unsigned char *first_data_address,

                         // 写入外部扩展随机存取存储器的首个数据地址指针

                         unsigned int data_length)

                         // 写入的数据长度

#ifndef USE_ASM_EXTSRAM_BLACK_ACCESS  // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译开始

{

  register unsigned char *addr ;                // 数据指针临时寄存器变量

  register unsigned char data ;                 // 临时寄存器变量

  register unsigned int j ;                     // 临时寄存器变量

  addr = (unsigned char *)es_addr_write_index ; // 赋值寻址低位指针为上一次的尾部地址值

  j = data_length ;                             // 赋值临时寄存器变量为写入的数据长度

  while (j-- != 0)

  {

    EXTSRAM_ADDR_PORT = EXTSRAM_ADDR_H_START ;  // 置寻址高位在 64KB 空间地址内

    data = *(first_data_address++) ;            // 取下一个写入数据序列中的数据

    EXTSRAM_ADDR_PORT = es_addr_write_h_index ; // 置寻址高位在超过 64KB 空间地址内

    *(addr++) = data ;                          // 将数据写入到超过 64KB 空间内

    // 如果本 64KB 页内空间写满,那么将寻址高位加1和将寻址低位指针归零;后将寻址高位

    // 的值存储到EEPROM中(防止掉电时丢失操作地址)。

    if ((unsigned int)addr == EXTSRAM_ADDR_END)

    {

      addr = (unsigned char *)EXTSRAM_ADDR_START ;

      es_addr_write_h_index++ ;

      es_addr_write_h_index_eep[0] = es_addr_write_h_index ;

      // 下面这两条条件判断语句用于执行此操作:如果寻址高位己到扩展存储空间尾部,那么将

      // 寻址高位归零;后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      if (es_addr_write_h_index_status != 0)

      {

        es_addr_write_h_index = (EXTSRAM_ADDR_H_START+1) ;

        es_addr_write_h_index_eep[0] = es_addr_write_h_index ;

        es_addr_write_h_index_status = 0 ;

        es_addr_write_h_index_status_eep[0] = es_addr_write_h_index_status ;

      }

      if (es_addr_write_h_index == EXTSRAM_ADDR_H_END)

      {

        es_addr_write_h_index_status = 0xA9 ;

        es_addr_write_h_index_status_eep[0] = es_addr_write_h_index_status ;

      }

    }

  }

  EXTSRAM_ADDR_PORT = EXTSRAM_ADDR_H_START ;    // 置寻址高位在 64KB 空间地址内

  es_addr_write_index = (unsigned int)addr ;    // 存储本次操作寻址低位指针的尾部地址值

  es_addr_write_index_eep[0] = es_addr_write_index ;// 将寻址低位指针值存储到 EEPROM 中

}

#else  // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译



#if (EXTSRAM_ADDR_START != 0x1100)    // "(EXTSRAM_ADDR_START != 0x1100)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!页的起始地址[EXTSRAM_ADDR_START]不等于[0x1100],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_START != 0x1100)"条件编译结束

#if (EXTSRAM_ADDR_END != 0xFFFF)      // "(EXTSRAM_ADDR_END != 0xFFFF)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!页的终止地址[EXTSRAM_ADDR_END]不等于[0xFFFF],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_END != 0xFFFF)"条件编译结束

#if (EXTSRAM_ADDR_H_START != 0x80)    // "(EXTSRAM_ADDR_H_START != 0x80)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!高位的起始地址[EXTSRAM_ADDR_H_START]不等于[0x80],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_H_START != 0x80)"条件编译结束

#if (EXTSRAM_ADDR_H_END != 0xFF)      // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!高位的终止地址[EXTSRAM_ADDR_H_END]不等于[0xFF],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译结束



#if defined(MCU_TYPE_IS_ATMEGA64) || defined(MCU_TYPE_IS_ATMEGA128)

    // 目标器件芯片为 ATmega64 和 ATmega128 的条件编译

{

      asm("cli") ;                       // 禁止全局中断

      asm("MOV r24, r18") ;              // R24 = 入口参数 data_length 的低字节

      asm("MOV r25, r19") ;              // R25 = 入口参数 data_length 的高字节

      // 赋值寻址低位指针值为上一次的尾部地址值

      asm("LDI r30, LOW(??es_addr_write_index)") ;

      asm("LDI r31, HIGH(??es_addr_write_index)") ;

      asm("LD r26, Z") ;                 // R26 = 寻址低位指针值的低字节

      asm("LDD r27, Z+1") ;              // R27 = 寻址低位指针值的高字节

      // 赋值寻址高位指针值为上一次的尾部地址值

      asm("LDI r30, LOW(??es_addr_write_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index)") ;

      asm("LD r18, Z") ;                 // R18 = 寻址高位指针值

      asm("MOV r30, r16") ;              // R30 = 入口参数 *first_data_address 的低字节

      asm("MOV r31, r17") ;              // R31 = 入口参数 *first_data_address 的高字节

      asm("LDI r19, 0x80") ;             // R19 = [EXTSRAM_ADDR_H_START]的值

      asm("LDI r20, 0xFF") ;             // R20 = [EXTSRAM_ADDR_END]值的低字节

      asm("LDI r21, 0xFF") ;             // R21 = [EXTSRAM_ADDR_END]值的高字节

  asm("ESB_WRITE_ASM1:") ;

      asm("OUT 0x12, r19") ;             // 置寻址高位在 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("LD r16, Z+") ;                // 取下一个写入数据序列中的数据

      asm("OUT 0x12, r18") ;             // 置寻址高位在超过 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("ST X+, r16") ;                // 将数据写入到超过 64KB 空间内

      // 如果本 64KB 页内空间写满,那么将寻址高位加1和将寻址低位指针归零;

      // 后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      asm("CP r26, r20") ;               // 寻址低位指针值是否超过 64KB ?

      asm("CPC r27, r21") ;

      asm("BREQ ESB_WRITE_ASM2") ;       // 是,转至相应处理

      asm("RJMP ESB_WRITE_ASM8") ;       // 否,继续写入下一个数据

  asm("ESB_WRITE_ASM2:") ;

      asm("LDI r26, LOW(0x1100)") ;      // 寻址低位指针值归回每页的起始地址值

      asm("LDI r27, HIGH(0x1100)") ;

                                           // ▲ 注:起始地址值为[EXTSRAM_ADDR_START]

      asm("INC r18") ;                   // 寻址高位指针值加1

      asm("MOV r2, r30") ;               // 暂存寄存器 r30 的数值到 r2 中

      asm("MOV r3, r31") ;               // 暂存寄存器 r31 的数值到 r3 中

      asm("LDI r30, LOW(??es_addr_write_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index)") ;

      asm("ST Z, r18") ;                 // 将寻址高位指针值赋值回静态变量中

      // 将寻址高位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_write_h_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_write_h_index_eep)") ;

  asm("ESBW_EEPROM_WRITE1:") ;



      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE1") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r18") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      // 下面这两条条件判断语句用于执行此操作:如果寻址高位己到扩展存储空间尾部,那么将

      // 寻址高位归零;后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      asm("LDI r30, LOW(??es_addr_write_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index_status)") ;

      asm("LD r16, Z") ;                 // 取寻址高位指针状态的数值

      asm("CPI r16, 0") ;                // 寻址寻址高位指针状态是否为 0 ?

      asm("BRNE ESB_WRITE_ASM3") ;       // 否,转至相应处理

      asm("RJMP ESB_WRITE_ASM4") ;       // 是,继续

  asm("ESB_WRITE_ASM3:") ;

      asm("LDI r30, LOW(??es_addr_write_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index)") ;

      asm("INC r19") ;

      asm("MOV R18, r19") ;              // 寻址高位指针值归回寻址高位的起始地址值

                                           // ▲ 注:起始值为[EXTSRAM_ADDR_H_START+1]

      asm("DEC r19") ;

      asm("ST Z, r18") ;                 // 将寻址高位指针值赋值回静态变量中

      // 将寻址高位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_write_h_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_write_h_index_eep)") ;

  asm("ESBW_EEPROM_WRITE2:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE2") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r18") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("LDI r30, LOW(??es_addr_write_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index_status)") ;

      asm("LDI r16, 0") ;                // 寻址高位指针状态值清为 0

      asm("ST Z, r16") ;                 // 将寻址高位指针状态值赋值回静态变量中

      // 将寻址高位指针状态值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_write_h_index_status_eep)") ;

      asm("LDI r31, HIGH(es_addr_write_h_index_status_eep)") ;

  asm("ESBW_EEPROM_WRITE3:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE3") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r16") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

  asm("ESB_WRITE_ASM4:") ;

      asm("CPI r18, 0xFF") ;             // 寻址高位指针值是否超过终止地址值?

                                           // ▲ 注:终止地址值为[EXTSRAM_ADDR_H_END]

      asm("BRNE ESB_WRITE_ASM6") ;       // 否,转至下一段;是,继续

      asm("LDI r16, 0xA9") ;             // 置寻址高位指针状态值为非0

      asm("LDI r30, LOW(??es_addr_write_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_write_h_index_status)") ;

      asm("ST Z, r16") ;                 // 将寻址高位指针状态值赋值回静态变量中

      // 将寻址高位指针状态值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_write_h_index_status_eep)") ;

      asm("LDI r31, HIGH(es_addr_write_h_index_status_eep)") ;

  asm("ESBW_EEPROM_WRITE4:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE4") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r16") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

  asm("ESB_WRITE_ASM6:") ;

      asm("MOV r30, r2") ;               // 从暂存寄存器 r2 中复原回 r30 的值

      asm("MOV r31, r3") ;               // 从暂存寄存器 r3 中复原回 r31 的值

  asm("ESB_WRITE_ASM8:") ;

      asm("SBIW r24, 1") ;               // 写入的数据长度-1

      asm("BREQ ESB_WRITE_ASM9") ;       // 如果己全部完成写入数据,则转至结束处理;

      asm("RJMP ESB_WRITE_ASM1") ;         // 否则,继续写下一个数据。

  asm("ESB_WRITE_ASM9:") ;

      asm("OUT 0x12, r19") ;             // 置寻址高位在 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("LDI r30, LOW(??es_addr_write_index)") ;

      asm("LDI r31, HIGH(??es_addr_write_index)") ;

      asm("ST Z, r26") ;                 // 将寻址低位指针值的低字节赋值回静态变量中

      asm("STD Z+1, r27") ;              // 将寻址低位指针值的高字节赋值回静态变量中

      // 将寻址低位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_write_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_write_index_eep)") ;

  asm("ESBW_EEPROM_WRITE5:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE5") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r26") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("ADIW r30, 1") ;               // 写入EEPROM的地址+1

  asm("ESBW_EEPROM_WRITE6:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_WRITE6") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r27") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("sei") ;                       // 打开全局中断

}

#else  // 目标器件芯片的条件编译

  #error 函数  " ExtSRAM_Black_Write "  错误!函数体没有可执行部分,无法调用入口参数和返回函数值。

#endif  // 目标器件芯片的条件编译结束



#endif                                // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译结束



#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_default=Pe826,Pe940      // Pe826,Pe940 消息复原为默认设置

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束



/*----------------------------------------------------------------------------

函数功能:    本函数用于以块方式访问空间大于 64 KB 外部随机存储器的读取数据操作。

函数入口参数:*first_data_address ------ 将读取的数据存储到目标的首个地址指针。

              data_length -------------- 读取的数据长度。

全局静态变量:es_addr_read_h_index ---------- 读取数据操作访问地址的寻址低位指针数值变量

              es_addr_read_index ------------ 读取数据操作访问地址的寻址高位指针数值变量

              es_addr_read_h_index_status --- 读取数据操作访问地址的寻址高位指针状态变量

备注:        ▲.本函数用于外部扩展随机存取存储器寻址指针不超过2个字节。

              ▲.本函数读取的源存储器空间将循环操作,即到达空间尾部时又返回到起始处,

                  继续执行读取数据操作。

----------------------------------------------------------------------------*/

#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_suppress=Pe826,Pe940     //  禁止编译时产生 Pe826,Pe940 消息

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束



void ExtSRAM_Black_Read(unsigned char *first_data_address,

                        // 将读取的数据存储到目标的首个地址指针

                        unsigned int data_length)

                        // 读取的数据长度

#ifndef USE_ASM_EXTSRAM_BLACK_ACCESS  // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译开始

{

  register unsigned char *addr ;                // 数据指针临时寄存器变量

  register unsigned char data ;                 // 临时寄存器变量

  register unsigned int j ;                     // 临时寄存器变量

  addr = (unsigned char *)es_addr_read_index ;  // 赋值寻址低位指针为上一次的尾部地址值

  j = data_length ;                             // 赋值临时寄存器变量为写入的数据长度

  while (j-- != 0)

  {

    EXTSRAM_ADDR_PORT = es_addr_read_h_index ;  // 置寻址高位在超过 64KB 空间地址内

    data = *(addr++) ;                          // 在超过 64KB 空间内读取数据

    EXTSRAM_ADDR_PORT = EXTSRAM_ADDR_H_START ;  // 置寻址高位在 64KB 空间地址内

    *(first_data_address++) = data ;            // 将读取的数据存储到目标的空间内

    // 如果本 64KB 页内空间读完,那么将寻址高位加1和将寻址低位指针归零;后将寻址高位

    // 的值存储到EEPROM中(防止掉电时丢失操作地址)。

    if ((unsigned int)addr == EXTSRAM_ADDR_END)

    {

      addr = (unsigned char *)EXTSRAM_ADDR_START ;

      es_addr_read_h_index++ ;

      es_addr_read_h_index_eep[0] = es_addr_read_h_index ;

      // 下面这两条条件判断语句用于执行此操作:如果寻址高位己到扩展存储空间尾部,那么将

      // 寻址高位归零;后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      if (es_addr_read_h_index_status != 0)

      {

        es_addr_read_h_index = (EXTSRAM_ADDR_H_START+1) ;

        es_addr_read_h_index_eep[0] = es_addr_read_h_index ;

        es_addr_read_h_index_status = 0 ;

        es_addr_read_h_index_status_eep[0] = es_addr_read_h_index_status ;

      }

      if (es_addr_read_h_index == EXTSRAM_ADDR_H_END)

      {

        es_addr_read_h_index_status = 0xA9 ;

        es_addr_read_h_index_status_eep[0] = es_addr_read_h_index_status ;

      }

    }

  }

  EXTSRAM_ADDR_PORT = EXTSRAM_ADDR_H_START ;    // 置寻址高位在 64KB 空间地址内

  es_addr_read_index = (unsigned int)addr ;     // 存储本次操作寻址低位指针的尾部地址值

  es_addr_read_index_eep[0] = es_addr_read_index ;// 将寻址低位指针值存储到 EEPROM 中

}

#else  // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译



#if (EXTSRAM_ADDR_START != 0x1100)    // "(EXTSRAM_ADDR_START != 0x1100)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!页的起始地址[EXTSRAM_ADDR_START]不等于[0x1100],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_START != 0x1100)"条件编译结束

#if (EXTSRAM_ADDR_END != 0xFFFF)      // "(EXTSRAM_ADDR_END != 0xFFFF)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!页的终止地址[EXTSRAM_ADDR_END]不等于[0xFFFF],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_END != 0xFFFF)"条件编译结束

#if (EXTSRAM_ADDR_H_START != 0x80)    // "(EXTSRAM_ADDR_H_START != 0x80)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!高位的起始地址[EXTSRAM_ADDR_H_START]不等于[0x80],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_H_START != 0x80)"条件编译结束

#if (EXTSRAM_ADDR_H_END != 0xFF)      // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译开始

  #error 函数  " ExtSRAM_Black_Write "  错误!高位的终止地址[EXTSRAM_ADDR_H_END]不等于[0xFF],在汇编函数中做相应修改。

#endif                                // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译结束



#if defined(MCU_TYPE_IS_ATMEGA64) || defined(MCU_TYPE_IS_ATMEGA128)

    // 目标器件芯片为 ATmega64 和 ATmega128 的条件编译

{

      asm("cli") ;                       // 禁止全局中断

      asm("MOV r24, r18") ;              // R24 = 入口参数 data_length 的低字节

      asm("MOV r25, r19") ;              // R25 = 入口参数 data_length 的高字节

      // 赋值寻址低位指针值为上一次的尾部地址值

      asm("LDI r30, LOW(??es_addr_read_index)") ;

      asm("LDI r31, HIGH(??es_addr_read_index)") ;

      asm("LD r26, Z") ;                 // R26 = 寻址低位指针值的低字节

      asm("LDD r27, Z+1") ;              // R27 = 寻址低位指针值的高字节

      // 赋值寻址高位指针值为上一次的尾部地址值

      asm("LDI r30, LOW(??es_addr_read_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index)") ;

      asm("LD r18, Z") ;                 // R18 = 寻址高位指针值

      asm("MOV r30, r16") ;              // R30 = 入口参数 *first_data_address 的低字节

      asm("MOV r31, r17") ;              // R31 = 入口参数 *first_data_address 的高字节

      asm("LDI r19, 0x80") ;             // R19 = [EXTSRAM_ADDR_H_START]的值

      asm("LDI r20, 0xFF") ;             // R20 = [EXTSRAM_ADDR_END]值的低字节

      asm("LDI r21, 0xFF") ;             // R21 = [EXTSRAM_ADDR_END]值的高字节

  asm("ESB_READ_ASM1:") ;

      asm("OUT 0x12, r18") ;             // 置寻址高位在超过 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("LD r16, X+") ;                // 读取下一个读取数据序列中的数据

      asm("OUT 0x12, r19") ;             // 置寻址高位在 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("ST Z+, r16") ;                // 将读取的数据存储到目标的空间内



      // 如果本 64KB 页内空间读取完毕,那么将寻址高位加1和将寻址低位指针归零;

      // 后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      asm("CP r26, r20") ;               // 寻址低位指针值是否超过 64KB ?

      asm("CPC r27, r21") ;

      asm("BREQ ESB_READ_ASM2") ;       // 是,转至相应处理

      asm("RJMP ESB_READ_ASM8") ;       // 否,继续写入下一个数据

  asm("ESB_READ_ASM2:") ;

      asm("LDI r26, LOW(0x1100)") ;      // 寻址低位指针值归回每页的起始地址值

      asm("LDI r27, HIGH(0x1100)") ;

                                           // ▲ 注:起始地址值为[EXTSRAM_ADDR_START]

      asm("INC r18") ;                   // 寻址高位指针值加1

      asm("MOV r2, r30") ;               // 暂存寄存器 r30 的数值到 r2 中

      asm("MOV r3, r31") ;               // 暂存寄存器 r31 的数值到 r3 中

      asm("LDI r30, LOW(??es_addr_read_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index)") ;

      asm("ST Z, r18") ;                 // 将寻址高位指针值赋值回静态变量中

      // 将寻址高位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_read_h_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_read_h_index_eep)") ;

  asm("ESBW_EEPROM_READ1:") ;



      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ1") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r18") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      // 下面这两条条件判断语句用于执行此操作:如果寻址高位己到扩展存储空间尾部,那么将

      // 寻址高位归零;后将寻址高位的值存储到EEPROM中(防止掉电时丢失操作地址)。

      asm("LDI r30, LOW(??es_addr_read_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index_status)") ;

      asm("LD r16, Z") ;                 // 取寻址高位指针状态的数值

      asm("CPI r16, 0") ;                // 寻址寻址高位指针状态是否为 0 ?

      asm("BRNE ESB_READ_ASM3") ;       // 否,转至相应处理

      asm("RJMP ESB_READ_ASM4") ;       // 是,继续

  asm("ESB_READ_ASM3:") ;

      asm("LDI r30, LOW(??es_addr_read_h_index)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index)") ;

      asm("INC r19") ;

      asm("MOV R18, r19") ;              // 寻址高位指针值归回寻址高位的起始地址值

                                           // ▲ 注:起始值为[EXTSRAM_ADDR_H_START+1]

      asm("DEC r19") ;

      asm("ST Z, r18") ;                 // 将寻址高位指针值赋值回静态变量中

      // 将寻址高位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_read_h_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_read_h_index_eep)") ;

  asm("ESBW_EEPROM_READ2:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ2") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r18") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("LDI r30, LOW(??es_addr_read_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index_status)") ;

      asm("LDI r16, 0") ;                // 寻址高位指针状态值清为 0

      asm("ST Z, r16") ;                 // 将寻址高位指针状态值赋值回静态变量中

      // 将寻址高位指针状态值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_read_h_index_status_eep)") ;

      asm("LDI r31, HIGH(es_addr_read_h_index_status_eep)") ;

  asm("ESBW_EEPROM_READ3:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ3") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r16") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

  asm("ESB_READ_ASM4:") ;

      asm("CPI r18, 0xFF") ;             // 寻址高位指针值是否超过终止地址值?

                                           // ▲ 注:终止地址值为[EXTSRAM_ADDR_H_END]

      asm("BRNE ESB_READ_ASM6") ;       // 否,转至下一段;是,继续

      asm("LDI r16, 0xA9") ;             // 置寻址高位指针状态值为非0

      asm("LDI r30, LOW(??es_addr_read_h_index_status)") ;

      asm("LDI r31, HIGH(??es_addr_read_h_index_status)") ;

      asm("ST Z, r16") ;                 // 将寻址高位指针状态值赋值回静态变量中

      // 将寻址高位指针状态值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_read_h_index_status_eep)") ;

      asm("LDI r31, HIGH(es_addr_read_h_index_status_eep)") ;

  asm("ESBW_EEPROM_READ4:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ4") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r16") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

  asm("ESB_READ_ASM6:") ;

      asm("MOV r30, r2") ;               // 从暂存寄存器 r2 中复原回 r30 的值

      asm("MOV r31, r3") ;               // 从暂存寄存器 r3 中复原回 r31 的值

  asm("ESB_READ_ASM8:") ;

      asm("SBIW r24, 1") ;               // 写入的数据长度-1

      asm("BREQ ESB_READ_ASM9") ;       // 如果己全部完成读取数据,则转至结束处理;

      asm("RJMP ESB_READ_ASM1") ;         // 否则,继续读取下一个数据。

  asm("ESB_READ_ASM9:") ;

      asm("OUT 0x12, r19") ;             // 置寻址高位在 64KB 空间地址内

                                           // ▲ 注:高位地址总线引脚为[PORTD]

      asm("LDI r30, LOW(??es_addr_read_index)") ;

      asm("LDI r31, HIGH(??es_addr_read_index)") ;

      asm("ST Z, r26") ;                 // 将寻址低位指针值的低字节赋值回静态变量中

      asm("STD Z+1, r27") ;              // 将寻址低位指针值的高字节赋值回静态变量中

      // 将寻址低位指针值存储到EEPROM中

      asm("LDI r30, LOW(es_addr_read_index_eep)") ;

      asm("LDI r31, HIGH(es_addr_read_index_eep)") ;

  asm("ESBW_EEPROM_READ5:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ5") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r26") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("ADIW r30, 1") ;               // 写入EEPROM的地址+1

  asm("ESBW_EEPROM_READ6:") ;

      asm("sbic 0x1C,1") ;               // 如果 EEWE 不清除

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("rjmp ESBW_EEPROM_READ6") ;   // 等待,上一次 EEPROM 写操作结束

      asm("out 0x1F,r31") ;              // 输出写入的 EEPROM 地址高位

                                           // ▲ 注:寄存器[EEARH]

      asm("out 0x1E,r30") ;              // 输出写入的 EEPROM 地址低位

                                           // ▲ 注:寄存器[EEARL]

      asm("out 0x1D,r27") ;              // 输出写入的 EEPROM 数据

                                           // ▲ 注:寄存器[EEDR]

      asm("sbi 0x1C,2") ;                // 设置 EEPROM 主机写使能

                                           // ▲ 注:寄存器[EECR]、位[EEMWE]

      asm("sbi 0x1C,1") ;                // 设置 EEPROM 写使能

                                           // ▲ 注:寄存器[EECR]、位[EEWE]

      asm("sei") ;                       // 打开全局中断

}

#else  // 目标器件芯片的条件编译

  #error 函数  " ExtSRAM_Black_Read "  错误!函数体没有可执行部分,无法调用入口参数和返回函数值。

#endif  // 目标器件芯片的条件编译结束



#endif                                // "USE_ASM_EXTSRAM_BLACK_ACCESS"条件编译结束



#if defined(_IAR_EW_AVR_)             // "IAR Embedded Workbench AVR 编译器"条件编译开始

  #pragma diag_default=Pe826,Pe940      // Pe826,Pe940 消息复原为默认设置

#endif                                // "defined(_IAR_EW_AVR_)" 条件编译结束





/*

****************************************************************************************

                           本C语言源程序文件到此结束

****************************************************************************************

*/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表