关于AVR外部扩展RAM(包括>64KB)的问题
最近几天,发现很多人使用M128、M8515等带有外部并行扩展口的AVR芯片,设计外部扩展RAM的系统。估计这些人不是初次学习单片机,可能具备一些使用51设计系统的经验。需要注意的是,AVR不是51,另外AVR也还是8位的单片机,不能完全满足那些需要大量计算和复杂数据处理的应用。一、正常方式外部扩展RAM
所有带有外部并行扩展口的AVR芯片,其数据存储器空间容量为64k(地址线16根),也就是说整个系统的可直接操作的数据空间为64K。但与51有区别的是,这64K的空间不是全部应用于外部扩展,因为AVR的32个寄存器、I/O寄存器和内部RAM已经占掉了一部分。所以实际上外部扩展RAM仅占60K左右(M128为例)。在我的《M128》一书的第5章中有对正常方式外部扩展RAM的设计和应用的详细介绍,请大家参考。
二、非正常方式外部扩展RAM
这里的非正常是指外部扩展大于64KRAM的应用,如128K、256K等。很明显,这样的扩展方案需要使用其它I/O线作为页选信号才能使用,本人在以前使用51的时候,也做过这样的系统。但对于使用AVR,则由于其内部占用了4K左右的地址,使得每页的RAM前端都实际是内部的RAM地址,所以整个RAM中间出现了“空洞”,所以在使用和处理上比51要复杂。
现在很多低端的32位ARM价格也比较便宜了,个人觉得这样的应用最好选择ARM。如果一定要使用AVR的话,以下几点需要认真的考虑。
1。硬件上地址锁存、译码电路当然是少不了,一定要使用HC系列的,因为AVR的速度比较快。
2。由于所有的C平台是不支持大于64K扩展的,它们只是把数组分配在64K空间内,因此数据定义非常重要。在实际使用中,应该将系统使用的其它各种变量定义在0页中,而把大型的数组定义在其它的页中,还要注意数组最大不能超过60K字节(对于M128,M256则不能超过56K)。
3。在变量定义的时候当然只能是按64K空间处理,在具体操作时用户需要做大量的转换处理,要精心设计,否则肯定会出现问题。
下面用一些简单的例子说明:
假定系统使用M128,需要2个48K字节的数组,那么64KRAM是不够的,扩展成128K,分成0、1页,用PD0控制。
定义变量:
char temp1;
char arr_temp;
.......
char temp2;
union arr{
char a0;
char a1;
} data;
说明:定义只能在64K空间。
temp1、arr_temp必须先定义,最后查看,应该定位在M128内部的4KRAM中。作为交换使用。
a0[],a1[]为共同体,占用同一地址空间。但PD0=0是,操作a0[],在0页;PD0=1时,操作a1[],在1页。
只要变量定位在内部4K的RAM中,那么不管PD0是何值,都可以直接对其操作。!!!!
下面是对数据的典型操作方式:
1。如果只对a0[]操作,那么将PD0置0,一切采用正常操作。
2。从a1[]中读一个数据到temp2:
如果temp2定位在内部RAM:
PD0 = 1;
temp2 = data.a1;
如果temp2定位在外部RAM,且在第0页(只能用户自己确定了)
PD0 = 1;
temp1 = data.a1;
PD0 = 0;
temp2 = temp1; // temp1必须是定位在内部RAM中的变量
3。将a1[]数据导入到a0[]中:两者在不同的页,只能通过定位在内部RAM的arr_temp[]间接处理实现
for // 24次
{
PD0 = 1;
for
{
arr_temp = a1; // 2048个
}
PD0 = 0;
for
{
a0 = arr_temp // 2048个
}
}
哈哈,晕了。其它自己去处理吧。 学习中 马老师,有必要设置一个UNION吗?
char temp1;
char arr_temp;
.......
char temp2;
char a0;
//控制好编译器优化的层次,效果和您原来的union一样的
for // 24次
{ //源页
PD0 = 1;
for
{
arr_temp = a0; // 2048个
}
PD0 = 0;//换目标页
for
{
a0 = arr_temp // 2048个
}
} 效果是一样的,但使用A0、A1在编程上更加明了,看到A0知道是0页的,A1是1页的。 受益不少,使用共用体可以节省很多空间,以前我做的数组切换,就是存在不同的地址单元,浪费了很多空间! 请问马老师,我用CAVR的编译器,定义使用外扩的RAM应该用什么关键字,例如我用典型的m162配32K,有具体的CAVR的例子否?谢谢! 学习了 to 5楼:
不用使用任何关键字.只要在PROJECT的设置中选择使用外部扩展RAM,填上扩展的大小.CVAVR的编译器在需要的时候,会自动将变量分配到外部RAM中,程序中就是简单的读写变量.
需要注意的时,外部扩展的RAM地址必须紧跟在内部RAM后面,中间不能出现"空地址". 需要注意的时,外部扩展的RAM地址必须紧跟在内部RAM后面,中间不能出现"空地址".
这句怎么理解?
另外,我在看m162的DS时,看到:
因为外部存储器在那个图中的内部存储器之后才被映射,所以呢,在外部存储器的头1280字节的空间是不可以寻址的,这就表现为不能存取外部存储器的0X0000-0X04FF。当然有个特殊的情况,当使用的外部存储器小于64K(典型值32K)时,外部存储器的0X0000-0X04FF范围可以通过访问0x8000 to 0x84FF进行存取(想一想为什么?)。因为高位地址线A15没有接入,外部寻址范围只有0X0000-0X7FFF,当访问0x8000 to 0x84FF时,低14位地址线定位在外部0X0000-0X04FF处(或许大家会疑惑,怎么不是访问的内部0X0000-0X04FF?请注意了,我们现在访问的是外部存储器,因为地址范围为0x8000 to 0x84FF,不是内部存储器,所以自然不是定位在内部0X0000-0X04FF范围)。不推荐大家对0x84FF以外的范围进行访问,因为这将改变 0X04FF-0X7FFF的数据,因为低14位地址是重复的。在应用中,地址在0x0500 to 0x84FF范围的存取是连续的线性的,只有0X0000-0X04FF有写特;
上面的这些与你所说的"空地址"有什么联系?
byte a @0x0500;
我这样的定义可以否,
另外附上一此在CAVR上的截图,请马老师看一下如何设置?
http://cache.amobbs.com/bbs_upload782111/files_8/ourdev_187705.jpg
http://cache.amobbs.com/bbs_upload782111/files_8/ourdev_187706.jpg
我现在是用M162配32K,一般A15接62256的CS脚,在程序中要对A15脚进行编程吗?
谢谢~! 》外部扩展的RAM地址必须紧跟在内部RAM后面,中间不能出现"空地址".
通常为
0X0000-0X04FF====》32个通用寄存器、I/O寄存器、内部RAM
0X0500--0X7FFF====》外部RAM(此时共32KB)
0X8000--0X84FF====》外部RAM的低位空间(1280个)用足33KB多一点。
0X8500--0XFFFF====》可以分配给其它并行接口芯片,中间可以出现“空地址”。
而下面则中间出现“空地址”情况。最好不要这样分配设计
0X0000-0X04FF====》32个通用寄存器、I/O寄存器、内部RAM
0X8000--0XFFFF =====》外部RAM
》我现在是用M162配32K,一般A15接62256的CS脚,在程序中要对A15脚进行编程吗?
为什么使用A15接CS?
如果这样分配:
0X0000-0X04FF====》32个通用寄存器、I/O寄存器、内部RAM
0X0500--0X7FFF====》外部RAM(此时共32KB)
够的话,那么A15可以作为一个I/O口使用,CS直接接地。
另外,第一张图中的外部SRAM的大小没有填。CVAVR会自动分配变量到外部RAM中的,不必特别的声明。
()
在我的《M128》一书的第5章中有对正常方式外部扩展RAM的设计和应用的详细介绍,请参考。 第一张图里SRAM大小如果是扩32K,就写,32*1024 byte,然后将下面勾上,第二张图就直接按这样的分法,可是我在测试的时候外部没有接上任何的SRAM,程序就不能正常的运行了,这是什么原因呢??谢谢马老师! 图中的设置,是告诉编译器,你使用了外部RAM,以及外部RAM的地址分配,对外部RAM操作是否需要加上等待节拍等.
编译器根据你的设置,将变量分配在外部RAM中了.
可是你外部根本不接RAM,程序能正常么?你在骗编译器? 谢谢马潮老师,基本上已经明白了,现在等硬件搞好后再测试一下,另外,我看到一些51的程序,62256的CS脚接到A15脚,可是程序里根本找不到它对A15脚的编程,这是硬件自动生成的控制吗?谢谢! 学习了 研究学习 用union不错.得到一些启发.
我公司做的一个产品就是128k的sram.但是那些ram地址在程序中都用的绝对地址不是通过编译器分配的.
所以使用起来还是比较可靠的. 学习一下,支持! 能不能推荐几个能够用的SRAM具体型号呢?我看了那些传统的62256好像速度都够不到啊!!
如果mega128的时钟是16MHz那么单个周期是62.5ns,然后再看看ram的datasheet后面有个什么70ns
哎,感觉好像不能用,就算用上了可能也会出问题的。
锁存器用74AHC的,这个好像还能够达到要求的
求助?求助?啊啊啊~~~~~~ avr读外部SRAM最少需要2个时钟周期。
16MHz,单个周期是62.5ns,2个是125ns,所以70ns的SDRAM可以正常使用。注意PCB的走线。 标记,学习,马老师。 mark 回复【楼主位】machao
-----------------------------------------------------------------------
你好马老师我用的是ATMEGA128。里面介绍有128k的程序空间。可是我无法定义超过4K的数组。看了你上面的操作在我这里不成功,我用的ICCAVR编译器? mark以后可能用到 学习 学习。。。 学习了, 学习~~ MARK MARK 我测试过一块LED屏控制卡,上面使用的是Atmega162和HM628512,RAM的A16~A19连接在别的端口上,CS=~A15。 #include <iom128v.h>
#include <macros.h>
#define uchar unsigned char
#define OFFEST 0x8000
void W_U6CNT2(uchar ctrl)
{
uchar *p=(uchar *)(OFFEST+0xcf);
*p=ctrl;
}
void W_U6(uchar ctrl)
{
uchar *p=(uchar *)(OFFEST+0xdf);
*p=ctrl;
}
void main()
{
MCUCR|=0x80;//PA、PG、PC口作为总线功能
XMCRA=0x00;
XMCRB=0x80;
W_U6(0x54); //写控制字
W_U6CNT2(0x0a);//写低八位计数初值
}
这是我没事用M128的的扩展总线,控制8253的用作分频器的一个测试。但是好像硬件端口出不来波形!求帮助!!!!!!!!!! 受益不少,谢谢。收藏。 【楼主位】 machao
说明:定义只能在64K空间。
temp1、arr_temp必须先定义,最后查看,应该定位在M128内部的4KRAM中。作为交换使用。
-----------------------------------------------------------------------
【7楼】 machao
不用使用任何关键字.只要在PROJECT的设置中选择使用外部扩展RAM,填上扩展的大小.CVAVR的编译器在需要的时候,会自动将变量分配到外部RAM中,程序中就是简单的读写变量
-----------------------------------------------------------------------
1、如果设置了选择使用外部扩展RAM
如何定义变量到内部 如何定义变量到外部?
是不是在内部够用的情况下
使用unsigned char arr_temp;这样的 默认使用内部
而使用指针地址偏移的,如:
#define OFFEST 0x1100
unsigned char *p=(uchar *)(OFFEST+偏移量);
指针地址超出内部RAM寻址范围的转为使用外部?
2、
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_634914DC1U3T.jpg
(原文件名:b.jpg)
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_634915WU2739.jpg
(原文件名:c.jpg)
这是datasheet里关于地址锁存要求的一段话,下半段话怎么理解? 1、如果设置了选择使用外部扩展RAM,如何定义变量到内部,如何定义变量到外部?
==》作为普通的变量,通常编译器会根据情况自动分配,分配的情况可以查看编译后产生的类似MAP类型的文件。同时编译器也提供用户指定分配的语句,例如CVAVR:
Global variables can be stored at specific SRAM and EEPROM locations at design-time using the @ operator.
Example:
/* the integer variable "a" is stored
in RAM at address 80h */
int a @0x80;
/* the structure "alfa" is stored
in RAM at address 90h */
struct s1 {
int a;
char c;
} alfa @0x90;
/* the float variable "b" is stored
in EEPROM at address 10h */
eeprom float b @0x10;
/* the structure "beta" is stored
in RAM at address 20h */
eeprom struct s2 {
int i;
long j;
} beta @0x20;
The following procedure must be used if a global variable, placed at a specific address using the @ operator, must be initialized during declaration:
/* the variable will be stored in RAM at address 0x182 */
float pi @0x182;
/* and it will be initialized with the value 3.14 */
float pi=3.14;
/* the variable will be stored in EEPROM at address 0x10 */
eeprom int abc @0x10;
/* and it will be initialized with the value 123 */
eeprom int abc=123;
是不是在内部够用的情况下,使用unsigned char arr_temp;这样的默认使用内部
而使用指针地址偏移的,如:
#define OFFEST 0x1100
unsigned char *p=(uchar *)(OFFEST+偏移量);
指针地址超出内部RAM寻址范围的转为使用外部?
==》通常是这样的。
2。后面是给出建立稳定的地址输出和锁存的最小时间要求。 回复【33楼】machao
-----------------------------------------------------------------------
恩 知道了 谢谢马老师的解答
片外扩展RAM理论上是好理解的 实际上操作要求考虑到很多方面 而且现在要做的还要带掉电保护的 学习了! 记录一下 一、正常方式外部扩展RAM
所有带有外部并行扩展口的AVR芯片,其数据存储器空间容量为64k(地址线16根),也就是说整个系统的可直接操作的数据空间为64K。但与51有区别的是,这64K的空间不是全部应用于外部扩展,因为AVR的32个寄存器、I/O寄存器和内部RAM已经占掉了一部分。所以实际上外部扩展RAM仅占60K左右(M128为例)。在我的《M128》一书的第5章中有对正常方式外部扩展RAM的设计和应用的详细介绍,请大家参考。
请问下 《M128》这个的完整书名是什么啊? superray2008 你好可以认识一下你吗?
我的qq:150216708 mark,,,, 请问下 《M128》这个的完整书名是什么啊?
页:
[1]