📄 access_extended_sram.c
字号:
不等于[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 + -