📄 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)
{
/*--------------------------------------------------------------------------------------
目标器件芯片为 ATmega64 和 ATmega128 的初始化操作,具体对外部扩展随机存储器接口设置为:
①.使能外部扩展随机存储器接口
②.读/写操作插入2个等待周期。输出新地址之前还要插入1个等待周期
③.使能外部扩展随机存储器总线保持功能
--------------------------------------------------------------------------------------*/
#if defined(MCU_TYPE_IS_ATMEGA64) || defined(MCU_TYPE_IS_ATMEGA128)
MCUCR = ((1<<SRE)|(1<<SRW10)) ; // 设置 ①、② 项
XMCRA = ((1<<SRW01)|(1<<SRW00)|(1<<SRW11)) ;// 设置 ② 项
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 空间内
if ((unsigned int)addr==EXTSRAM_ADDR_END) // 本 64KB 页内空间是否写满?
{
addr = (unsigned char *)EXTSRAM_ADDR_START;// 寻址低位指针归零
es_addr_write_h_index++ ; // 寻址高位指针加1
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;// 存进EEPROM中
es_addr_write_h_index_status = 0 ; // 寻址高位指针状态清零
es_addr_write_h_index_status_eep[0]=es_addr_write_h_index_status;// 存进EEPROM中
}
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;// 存进EEPROM中
}
}
}
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)
#error 函数<ExtSRAM_Black_Write>错误!页的起始地址[EXTSRAM_ADDR_START]不等于\
[0x1100],在汇编函数中做相应修改。
#endif
#if (EXTSRAM_ADDR_END != 0xFFFF)
#error 函数<ExtSRAM_Black_Write>错误!页的终止地址[EXTSRAM_ADDR_END]不等于\
[0xFFFF],在汇编函数中做相应修改。
#endif
#if (EXTSRAM_ADDR_H_START != 0x80)
#error 函数<ExtSRAM_Black_Write>错误!高位的起始地址[EXTSRAM_ADDR_H_START]\
不等于[0x80],在汇编函数中做相应修改。
#endif
#if (EXTSRAM_ADDR_H_END != 0xFF)
#error 函数<ExtSRAM_Black_Write>错误!高位的终止地址[EXTSRAM_ADDR_H_END]\
不等于[0xFF],在汇编函数中做相应修改。
#endif
/*--------------------------------------------------------------------------------------
目标器件芯片为 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_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 "); // 置寻址高位[▲:PORTD]在 64KB 空间地址内
asm(" ld r16, Z+ "); // 取下一个写入数据序列中的数据
asm(" out 0x12, r18 "); // 置寻址高位[▲:PORTD]在超过 64KB 空间地址内
asm(" st X+, r16 "); // 将数据写入到超过 64KB 空间内
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -