📄 access_extended_sram.c
字号:
// 目标器件芯片为 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语言源程序文件到此结束
****************************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -