📄 access_extended_sram.c
字号:
/*
****************************************************************************************
源程序文件名: 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)") ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -