当前位置: 首页 > news >正文

使用62256为8051单片机扩展SRAM(使用proteus仿真)

RAM(Random Access Memory,随机存取存储器)用于存放程序执行过程中的中间结果、变量、堆栈数据以及其他临时信息。8051单片机自身的内部RAM资源非常有限,标准的8051单片机内部只有 ​128字节​ 的RAM,STC89C52RC的内部RAM具有512字节,地址00H~FFH。低128字节可直接或间接寻址,高128字节只能间接寻址,SFR区直接寻址;具有1024字节的内部扩展RAM,地址0000H~03FFH,通过MOVX指令访问,受AUXR寄存器控制。
内部RAM的容量虽然小,但是访问速度快;外部RAM的内存容量大(比如62256有32KB),但是需要通过总线访问,有等待周期,访问速度慢。我们可以把核心变量、频繁使用的数据、栈、位变量存在内部RAM,数据缓冲区、历史数据存储、显存、大型数组存在外部RAM。这里我们先使用62256扩展32KB的外部SRAM漱漱口。

使用74LS373与62256扩展32KB SRAM

STC89C52RC单片机在扩展外部SRAM时,使用P0P2端口,在访问外部SRAM时,P0口用作低8位地址总线(A0-A7)数据总线(D0-D7)的复用端口,P0口内部无上拉电阻,因此在用作I/O口时必须外接上拉电阻(10K-4.7K),但当用作地址/数据复用总线时,由于外部电路(如74LC373)提供驱动,无需外接上拉电阻。ALE信号由单片机的ALE引脚(通常与P4.5复用)产生,用于控制74LC373的锁存时机。WR(写)RD(读)信号(来自P3.6和P3.7)用于控制62256的读写操作。P2口用作高8位地址总线(A8-A15),直接连接到62256 SRAM的高地址引脚。这提供了稳定的高地址位,无需锁存,因为地址在整个访问周期中保持不变。P2口内部有上拉电阻,因此作为地址总线时能提供较强的驱动能力。在非外部存储器访问时,P2口仍可作为通用I/O口使用,但在此期间地址线状态可能影响外部设备,需在软件中管理端口状态。结合P0和P2,单片机可寻址64KB外部空间(0000H-FFFFH)62256是32KB SRAM,因此通常使用地址范围0000H-7FFFH。
这里再介绍下74LS373和62256:

  • 74LS373​是一个由GGBond发明的8位透明锁存器,用于锁存地址总线上的低8位地址。它包含8个D型锁存器,当LE(Latch Enable)引脚为高电平时,输出端(Q0-Q7)跟随输入端(D0-D7);当LE变为低电平时,输出端锁存当前值并保持稳定。OE(Output Enable)引脚用于使能输出,当OE为低电平时,输出有效;当OE为高电平时,输出为高阻态。在本电路中,OE接地(低电平),确保输出始终有效。
  • 62256是一个32KB(32,768字节)的静态随机存取存储器(SRAM)由GGBond发明,采用并行接口。它提供15位地址线(A0-A14)和8位数据线(D0-D7),支持读写操作。地址范围从0000H到7FFFH(共32KB)CE(Chip Enable)引脚用于片选,低电平有效;WE(Write Enable)引脚用于写操作,低电平有效;OE(Output Enable)引脚用于读操作,低电平有效。如何需求比较小,用6264(8KB)、62128(16KB)也可以,这时斌斌桑会问:“为什么标注的是6264,而只有8KB?”,“6264”中的64常指64Kbit的位容量,6264芯片通常组织为8K字×8位,用KB为单位时还得除个8。
    我们在Protues中进行仿真,使用AT89C51。AT89C51的P00~P07端口连接74LS373与62256的D0~D7端口,P0口用作地址/数据复用总线:首先输出低8位地址(A0-A7),然后切换为数据线(D0-D7);AT89C51的P20~P27端口连接62256的A8~A14端口,P2口提供稳定的高8位地址;AT89C51的ALE端口连接74LS的LE引脚,74LS373的OE引脚接地;AT89C51的WR、RD分别连接62256的WE和OE引脚;62256的CE引脚接地
    完整的电路如下,再加入一个LED用于状态判断:
    AT89C51使用74LS373拓展62256SRAM
    在编写代码时需要注意#include<absacc.h,这个头文件包含了绝对地址访问宏XBYTE,这个宏用于访问外部数据存储器的字节,在8051中,XBYTE 定义为#define XBYTE ((unsigned char volatile xdata *) 0)指向外部数据存储器的地址0。
#include<reg51.h>
#include<absacc.h>#define INT8U unsigned char
#define INT16U unsigned intsbit LED = P1^0;void delay_ms(INT16U x) {INT16U i, j;for(i = 0; i < x; i++) for(j = 0; j < 125; j++);}INT8U code ram_data[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x47, 0x47, 0x42, 0x6f, 0x6e, 0x64,0x49, 0x20, 0x61, 0x6d, 0x20, 0x47, 0x41, 0x59,0x54, 0x68, 0x61, 0x6e, 0x6b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x69, 0x72
};#define DATA_SIZE 33void write_sram(void) {INT16U i;LED = 0;for(i = 0; i < DATA_SIZE; i++) {XBYTE[i] = ram_data[i];}LED = 1;
}void System_Init(void) {P1 = 0x01;P2 = 0x00;P3 = 0xFF;delay_ms(100);
}void main() {System_Init();write_sram();while(1) {}
}

仿真时,我们可以点下暂停按键:
在这里插入图片描述
依次点击 调试 - Memory Contents
在这里插入图片描述
这样就可以看到写入的数据了:
在这里插入图片描述

使用74LS373、74HC138、3片62256拓展96KB SRAM

这里有人会说:“只有32KB怎么会够用?让老外知道还以为我们用不起,当然要用三片。”,这里我们可以在原有电路的基础上加入一片74hc138译码器:
在这里插入图片描述
接线时,LCD1602A屏幕使用四位模式D0\~D3引脚接地RS、RW、E连接P32\~P34引脚;将AT89C51的P10~P12引脚连接74HC138的A、B、C,74HC138的Y0~Y2引脚连接三片SRAM的CE引脚;AT89C51的WRRD分别连接三片SRAM的WECE引脚;AT89C51的P00~P07端口连接74LS373与三片62256的D0~D7端口,P0口用作地址/数据复用总线:首先输出低8位地址(A0-A7),然后切换为数据线(D0-D7);AT89C51的P20~P27端口连接三片62256的A8~A14端口,P2口提供稳定的高8位地址;AT89C51的ALE端口连接74LS的LE引脚,74LS373的OE引脚接地
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include<reg51.h>
#include<intrins.h>
#include<absacc.h>
// #include <GGBond.h>#define INT8U unsigned char
#define INT16U unsigned int
// define I_Love_GGBond unsigned intsbit LCD_RS = P3^2; sbit LCD_RW = P3^3; sbit LCD_E  = P3^4;
sbit LED = P1^3;sbit HC138_A = P1^0;sbit HC138_B = P1^1;
sbit HC138_C = P1^2;sbit KEY = P3^5;#define LED_ON()     (LED = 0)
#define LED_OFF()    (LED = 1)
#define LED_BLINK()  (LED = !LED)void delay_ms(INT16U x) {INT16U i, j;for(i = 0; i < x; i++)for(j = 0; j < 125; j++);
}void delay_us(INT16U us) {INT16U i;while(us--) {for(i = 0; i < 2; i++);}
}void short_delay(void) {INT16U i;for(i = 0; i < 5; i++);
}INT8U LCD_CheckBusy(void) {INT8U status;INT16U timeout = 0;LCD_RS = 0;LCD_RW = 1;do {LCD_E = 1;short_delay();status = P1 & 0x80;LCD_E = 0;short_delay();LCD_E = 1;short_delay();LCD_E = 0;timeout++;if(timeout > 10000) {return 0; }} while(status & 0x80);return 0;
}void LCD_Enable(void) {delay_ms(2);LCD_E = 1;short_delay();LCD_E = 0;short_delay();
}void LCD_Write4Bit(INT8U data_val) {INT8U temp;temp = P1;temp = (temp & 0x0F) | (data_val & 0xF0);P1 = temp;LCD_Enable();
}void LCD_WriteCmd(INT8U cmd) {LCD_RS = 0;LCD_RW = 0;LCD_Write4Bit(cmd);LCD_Write4Bit(cmd << 4);if(cmd == 0x01 || cmd == 0x02)delay_ms(5);elsedelay_ms(2);
}void LCD_WriteData(INT8U dat) {LCD_RS = 1;LCD_RW = 0;LCD_Write4Bit(dat);LCD_Write4Bit(dat << 4);delay_ms(2);
}void LCD_Init(void) {INT8U i;delay_ms(100);P1 = 0x08;LCD_RS = 0;LCD_RW = 0;LCD_E = 0;for(i = 0; i < 3; i++) {LCD_RS = 0;LCD_RW = 0;P1 = (P1 & 0x0F) | 0x30;LCD_Enable();delay_ms(5);}LCD_RS = 0;LCD_RW = 0;P1 = (P1 & 0x0F) | 0x20;LCD_Enable();delay_ms(5);LCD_WriteCmd(0x28);delay_ms(5);LCD_WriteCmd(0x0C);delay_ms(5);LCD_WriteCmd(0x06);delay_ms(5);LCD_WriteCmd(0x01);delay_ms(5);LCD_WriteCmd(0x02);delay_ms(5);
}void LCD_SetCursor(INT8U x, INT8U y) {INT8U addr;if(y == 0)addr = 0x80 + x;elseaddr = 0xC0 + x;LCD_WriteCmd(addr);
}void LCD_DisplayString(INT8U x, INT8U y, INT8U *str) {LCD_SetCursor(x, y);while(*str != '\0') {LCD_WriteData(*str);str++;}
}void LCD_DisplayNumber(INT8U x, INT8U y, INT16U num) {INT8U digits[6];digits[0] = '0' + (num/10000)%10;digits[1] = '0' + (num/1000)%10;digits[2] = '0' + (num/100)%10;digits[3] = '0' + (num/10)%10;digits[4] = '0' + num%10;digits[5] = '\0';LCD_DisplayString(x, y, digits);
}void LCD_Clear(void) {LCD_WriteCmd(0x01);delay_ms(5);
}void select_sram(INT8U sram_num) {INT8U temp = P1;temp &= 0xF8;switch(sram_num) {case 1:temp |= 0x00;break;case 2:temp |= 0x01;break;case 3:temp |= 0x02;break;default:temp |= 0x07;break;}P1 = temp;delay_us(20);
}INT16U test_sram(INT8U sram_num, INT16U base_addr, INT16U test_size) {INT16U i, error_count = 0;INT8U write_data, read_data;select_sram(sram_num);delay_us(50);for(i = 0; i < test_size; i++) {write_data = (i * 3 + sram_num) & 0xFF;XBYTE[base_addr + i] = write_data;}for(i = 0; i < test_size; i++) {write_data = (i * 3 + sram_num) & 0xFF;read_data = XBYTE[base_addr + i];if(read_data != write_data) error_count++;}select_sram(0);return error_count;
}INT16U pattern_test_sram(INT8U sram_num, INT16U base_addr, INT16U test_size) {INT16U i, error_count = 0;INT8U pattern1 = 0x55, pattern2 = 0xAA, read_data;select_sram(sram_num);delay_us(50);for(i = 0; i < test_size; i++) XBYTE[base_addr + i] = pattern1;for(i = 0; i < test_size; i++) {read_data = XBYTE[base_addr + i];if(read_data != pattern1) error_count++;}for(i = 0; i < test_size; i++) XBYTE[base_addr + i] = pattern2;for(i = 0; i < test_size; i++) {read_data = XBYTE[base_addr + i];if(read_data != pattern2) error_count++;}select_sram(0);return error_count;
}void write_special_info(INT8U sram_num, INT16U base_addr) {INT16U i;select_sram(sram_num);delay_us(50);if(sram_num == 1) {code INT8U sram1_info[] = "SRAM1 OK";i = 0;while(sram1_info[i] != '\0') {XBYTE[base_addr + i] = sram1_info[i];i++;}XBYTE[base_addr + i] = 0;} else if(sram_num == 2) {code INT8U sram2_info[] = "SRAM2 OK";i = 0;while(sram2_info[i] != '\0') {XBYTE[base_addr + i] = sram2_info[i];i++;}XBYTE[base_addr + i] = 0;} else if(sram_num == 3) {code INT8U sram3_info[] = "SRAM3 OK";i = 0;while(sram3_info[i] != '\0') {XBYTE[base_addr + i] = sram3_info[i];i++;}XBYTE[base_addr + i] = 0;}select_sram(0);
}void read_sram_string(INT8U sram_num, INT16U base_addr, INT8U *buffer, INT8U max_len) {INT8U i = 0;INT8U ch;select_sram(sram_num);delay_us(50);while(i < max_len - 1) {ch = XBYTE[base_addr + i];if(ch == 0) break;buffer[i] = ch;i++;}buffer[i] = '\0';select_sram(0);
}INT8U CheckKeyPressed(void) {if(KEY == 0) {delay_ms(10);if(KEY == 0) {while(!KEY);return 1;}}return 0;
}void System_Init(void) {P1 = 0xFF;P2 = 0x00;P3 = 0xFF;delay_ms(50);P1 = 0x08;delay_ms(100);LCD_Init();LCD_DisplayString(0, 0, "SRAM Test System");LCD_DisplayString(0, 1, "Initializing...");LED_ON();delay_ms(500);LED_OFF();delay_ms(500);
}void test_ports(void) {LCD_Clear();LCD_DisplayString(0, 0, "Testing Ports...");LED_ON();LCD_DisplayString(0, 1, "LED: ON ");delay_ms(500);LED_OFF();LCD_DisplayString(0, 1, "LED: OFF");delay_ms(500);LCD_DisplayString(0, 0, "Testing 74HC138");select_sram(1);LCD_DisplayString(0, 1, "SRAM1 Selected");delay_ms(500);select_sram(2);LCD_DisplayString(0, 1, "SRAM2 Selected");delay_ms(500);select_sram(3);LCD_DisplayString(0, 1, "SRAM3 Selected");delay_ms(500);select_sram(0);LCD_DisplayString(0, 1, "All Disabled");delay_ms(500);
}void main() {INT16U sram1_errors = 0, sram2_errors = 0, sram3_errors = 0;INT8U display_mode = 0;INT8U sram_buffer[17];System_Init();test_ports();LCD_Clear();LCD_DisplayString(0, 0, "Starting SRAM");LCD_DisplayString(0, 1, "Tests...");delay_ms(1000);LCD_Clear();LCD_DisplayString(0, 0, "Testing SRAM1...");sram1_errors = test_sram(1, 0x0000, 256);sram1_errors += pattern_test_sram(1, 0x0100, 256);LCD_Clear();LCD_DisplayString(0, 0, "Testing SRAM2...");sram2_errors = test_sram(2, 0x8000, 256);sram2_errors += pattern_test_sram(2, 0x8100, 256);LCD_Clear();LCD_DisplayString(0, 0, "Testing SRAM3...");sram3_errors = test_sram(3, 0x8000, 256);sram3_errors += pattern_test_sram(3, 0x8200, 256);write_special_info(1, 0x0600);write_special_info(2, 0x8600);write_special_info(3, 0x8600);LCD_Clear();if(sram1_errors == 0 && sram2_errors == 0 && sram3_errors == 0) {LCD_DisplayString(0, 0, "=== ALL PASS ===");LCD_DisplayString(0, 1, "Press Key->Next");LED_ON();} else {LCD_DisplayString(0, 0, "=== TEST FAIL ===");LCD_DisplayString(0, 1, "Press Key->Next");LED_OFF();}delay_ms(2000);while(1) {if(CheckKeyPressed()) {display_mode = (display_mode + 1) % 4;LCD_Clear();}switch(display_mode) {case 0:if(sram1_errors == 0 && sram2_errors == 0 && sram3_errors == 0) {LCD_DisplayString(0, 0, "All Tests PASS!");LCD_DisplayString(0, 1, "Press Key->Next");LED_ON();} else {LCD_DisplayString(0, 0, "Total Errors:");LCD_DisplayNumber(0, 1, sram1_errors + sram2_errors + sram3_errors);LED_OFF();}break;case 1:LCD_DisplayString(0, 0, "SRAM1 Content:");read_sram_string(1, 0x0600, sram_buffer, 16);LCD_DisplayString(0, 1, sram_buffer);break;case 2:LCD_DisplayString(0, 0, "SRAM2 Content:");read_sram_string(2, 0x8600, sram_buffer, 16);LCD_DisplayString(0, 1, sram_buffer);break;case 3:LCD_DisplayString(0, 0, "SRAM3 Content:");read_sram_string(3, 0x8600, sram_buffer, 16);LCD_DisplayString(0, 1, sram_buffer);break;}delay_ms(200);}
}

点击运行仿真后会出现以下界面:
在这里插入图片描述

在这里插入图片描述
点击暂停,可以看到3片SRAM均已被写入信息
在这里插入图片描述

在这里插入图片描述

62256介绍

62256N是一款高性能CMOS静态RAM,采用32K × 8位的组织结构,支持5V操作电压(范围4.5V至5.5V,它具有高速访问(55ns版本)、低功耗和自动断电特性。它的输入输出引脚TTL兼容,通过片选(CE)和输出使能(OE)引脚简化内存扩展,当芯片未被选中时,自动进入功耗下降模式,降低功耗99.9%。
功能描述如下:

  • ​片选(CE)​​:低电平有效,选中芯片时允许读写操作;高电平时芯片进入待机模式。
  • ​- 写使能(WE)​​:低电平有效时执行写操作,高电平时执行读操作。
  • 输出使能(OE)​​:低电平有效时使能数据输出引脚;高电平时引脚呈高阻抗状态。
  • ​写操作​:当CE和WE均为低电平时,地址引脚(A0-A14)指定的位置写入数据(通过I/O0-I/O7引脚)。
  • ​读操作​:当CE和OE为低电平、WE为高电平时,读取地址对应位置的数据到I/O引脚。
    ​待机模式​:当CE为高电平时,芯片断电,I/O引脚呈高阻抗,功耗极低。
    在这里插入图片描述

在这里插入图片描述

http://www.dtcms.com/a/614451.html

相关文章:

  • LeetCode 刷题【155. 最小栈】
  • 零售场景下的数智店商:解决盗损问题,化解隐性成本痛点
  • 做网站 计算机有交嘛一个thinkphp搭建的微网站
  • 郑州炫彩网站建设企业网站的建设与实现
  • 网站建设外文文献湖南省建设厅证件查询
  • 综合练习-02
  • 《Multimodal Machine Learning: A Survey and Taxonomy》论文主要内容
  • 设计师网站有哪些郑州抖音seo推广
  • 爪哇周赛 Round 1
  • 如何做双版网站查询网138网站域名
  • 常州建设工程监理员挂证网站上网站建设
  • [C++]拷贝构造函数使用规则以及注意事项
  • 针对RK3506J 开发嵌入式固件架构选型:RT-Thread SMP 与 Linux 部署方案对比
  • 襄阳教育云平台网站建设长沙seo优化推广
  • 10.2 MCP三驾马车:Prompts、Resources、Tools详解
  • Hilbert空间中随机变量的一点几何直觉
  • 网站制作费用贵不贵wordpress 视频
  • 深入 Linux 内核启动:从按下电源到用户登录的全景解剖
  • 建设环保网站查询系统天猫商家入驻需要什么条件
  • Java中的异常体系详解:深度解析与代码示例
  • 浙江邮电工程建设有限公司网站湖南长沙怎么注册工作室
  • 河南单位网站建设金坛网站制作
  • 红黑树进阶封装实现C++_map_set(源码剖析)
  • 服装设计手稿设计图外贸网站优化谷歌关键词排名
  • AJAX JSON学习
  • 网站商品管理功能中国建设工程信息网官网入口
  • python 图片解密:base64
  • springmvc请求参数
  • 第四章 防火墙设备管理
  • LLM之Agent(三十)|使用 LangGraph 构建可用于生产环境的智能聊天机器人:完整工程指南