⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 access_extended_sram.c

📁 本程序是用于访问空间大于 64 KB (即:地址指针数大于两个字节)外部扩展随机存取存储器的源程序文件。
💻 C
📖 第 1 页 / 共 4 页
字号:
不等于[0x80],在汇编函数中做相应修改。
#endif                                        // "(EXTSRAM_ADDR_H_START != 0x80)"条件编译结束
#if (EXTSRAM_ADDR_H_END != 0xFF)              // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译开始
#error 函数<ExtSRAM_Black_Read>错误!高位的终止地址[EXTSRAM_ADDR_H_END]\
不等于[0xFF],在汇编函数中做相应修改。
#endif                                        // "(EXTSRAM_ADDR_H_END != 0xFF)"条件编译结束
/*--------------------------------------------------------------------------------------
目标器件芯片为  ATmega64 和 ATmega128  的本函数在线汇编语言指令代码
--------------------------------------------------------------------------------------*/
#if defined(MCU_TYPE_IS_ATMEGA64) || defined(MCU_TYPE_IS_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                 ");  // 置寻址高位[▲:PORTD]在超过 64KB 空间地址内
  asm("    LD r16, X+                    ");  // 读取下一个读取数据序列中的数据
  asm("    OUT 0x12, r19                 ");  // 置寻址高位[▲:PORTD]在 64KB 空间地址内
  asm("    ST Z+, r16                    ");  // 将读取的数据存储到目标的空间内
  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                     ");  // 将寻址高位指针值赋值回静态变量中
  asm("    LDI r30, LOW(es_addr_read_h_index_eep)");// 将寻址高位指针值存储到EEPROM中
  asm("    LDI r31, HIGH(es_addr_read_h_index_eep)");
  asm("ESBW_EEPROM_READ1:                ");
  asm("    sbic 0x1C,1                   ");  // 如果[▲ :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]
  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                     ");  // 将寻址高位指针值赋值回静态变量中
  asm("    LDI r30, LOW(es_addr_read_h_index_eep)");// 将寻址高位指针值存储到EEPROM中
  asm("    LDI r31, HIGH(es_addr_read_h_index_eep)");
  asm("ESBW_EEPROM_READ2:                ");
  asm("    sbic 0x1C,1                   ");  // 如果[▲ :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                     ");  // 将寻址高位指针状态值赋值回静态变量中
  asm("    LDI r30, LOW(es_addr_read_h_index_status_eep)");// 将寻址高位指针状态值存到EEPROM
  asm("    LDI r31, HIGH(es_addr_read_h_index_status_eep)");
  asm("ESBW_EEPROM_READ3:                ");
  asm("    sbic 0x1C,1                   ");  // 如果[▲ :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                     ");  // 将寻址高位指针状态值赋值回静态变量中
  asm("    LDI r30, LOW(es_addr_read_h_index_status_eep)");// 将寻址高位指针状态值存到EEPROM
  asm("    LDI r31, HIGH(es_addr_read_h_index_status_eep)");
  asm("ESBW_EEPROM_READ4:                ");
  asm("    sbic 0x1C,1                   ");  // 如果[▲ :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                 ");  // 置寻址高位[▲:PORTD]在 64KB 空间地址内
  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                  ");  // 将寻址低位指针值的高字节赋值回静态变量中
  asm("    LDI r30, LOW(es_addr_read_index_eep)");// 将寻址低位指针值存储到EEPROM中
  asm("    LDI r31, HIGH(es_addr_read_index_eep)");
  asm("ESBW_EEPROM_READ5:                ");
  asm("    sbic 0x1C,1                   ");  // 如果[▲ :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                   ");  // 如果[▲ :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_)" 条件编译结束

/*==========================================================================================
函数功能:    本函数用于计算从大于 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,
                                       // 写入操作的访问地址高位指针数值

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -