在写程序的时候,需要做一个FIFO的队列结构来缓存数据,数据长度不一致。
这样的话,感觉用链表结构比较适合。
从来没用过Keil51的动态内存分配,求教各位高见。
用的是STC15F2K系列的片子……
各位大虾给讲解下,或者有其他的方式也可以!
十分感谢。
附:
我搜到一个篇**,似乎有点道理。求讨论!
*********************************************************************
Keil51动态内存分配
动态内存一般分配在堆中,而静态的内存一般分配在栈中;Keil51中提供了一个建立堆的函数,就是init_mempool(首地址,大小),首地址被定义为xdata的地址空间,这个函数可以在xdata中定义一个可以动态分配的堆;因为在51中,data区域的空间太小,要动态分配空间,考虑到程序的运行,是不合理的,所以必须在xdata中建立可以动态分配的堆。
STC12C5A60S2内部集成了256字节的RAM,存储类型为data,地址是00H~FFH。
其中低128字节是工作寄存器组,包括R0~R7,地址为00H~1FH,20H~2FH地址区为位寻址区,30H~7FH为普通RAM区;高128字节为普通的RAM区。
内部RAM中,30H~FFH都是普通用户RAM和堆栈区,可以用来进行内存分配,总共208字节;实际在程序运行中,要在这208字节分配一个堆栈进行动态的内存分配,对于其他的程序运行会有很多不便。
STC12C5A60S2可用的内部扩展RAM的地址空间是:0x000~0x3ff这一地址空间,存储类型为xdata,这部分空间总共占1K字节,可以用来作为堆栈区,进行内存动态分配。
STC12C5A60S2可以扩展64K外部xdata,在没有进行扩展外部存储器的情况下,最好使用上述内部扩展的1K字节,地址为0x000~0x3ff的存储器。
对于其他的51单片机,用户可以参考芯片手册查看系统内部的以及扩展的RAM空间大小和地址,确定data和xdata范围,根据需要自行定义。
目前,我使用STC12C5A60S2总结了两种动态定义的方式。
实例
方式一:给定地址区域
init_mempool(0x0000,0x03ff);//内部扩展1K字节的空间,
//都可以作为堆栈空间进行内存分配;
数据结构:
typedef structSTU{
uint8id;
structSTU*next;
}*PSTU,STU_t;
注意:一定在使用init_mempool函数之后使用malloc,calloc,realloc,free等函数,因为只有先确定了堆,才能在堆中执行相应的操作;
定义并分配堆空间:
PSTU stu;
init_mempool(0x0100,500);//内部只能用0x300~0x3ff这一地址空间;
stu=(PSTU)malloc(sizeof(STU_t));
stu->id=8;
stu->next=NULL;
函数:void insertlist(PSTUphead,uint8pos,PSTUstu);
方式二:让系统随机分配
static uint8 memblk[N];
//系统随机分配一个数组,将数组的首地址和数
init_mempool(memblk,sizeof(memblk));
//组的长度N作为堆区的空间参数数据结构:
typedefstructSTU{uint8id;
structSTUxdata*next;}*PSTU,STU_t;定义并分配堆空间:
STU_txdata*stu;
static uint8 memblk[200];//实际在用这个方法时,一般不会定义到1K字节,init_mempool(memblk,sizeof(memblk));//因为太大,系统可能无**常分配初始化:
stu=malloc(sizeof(STU_t));stu->id=8;
stu->next=NULL;
函数:voidinsertlist(STU_txdata*phead,uint8pos,STU_txdata*stu);
问题
自己发现的一个问题:在内存分配时,方式一可以用PSTU类型直接定义,一般情况下默认是在data区定义的指针类型;而方式二用STU_txdata*类型,这个定义的是在xdata区的指针类型。但是,在程序运行的过程中,我发现,用方式一,好像内存也会分配到xdata,和方式二的定义效果是一样的,于是我得出了一个不确定的结论,因为函数init_mempool()自身就是在xdata定义一个空间,那么在方式一中,如果使用了这个函数,后面的变量和分配的空间,会默认分配在xdata,以至于方式一和方式二的效果是一样的。因为这个结论没有得到最后的理论验证,仅仅是按照实验结果进行的推论,所以想和大家一起讨论,希望高人给出一个很好的结论。但是需要提醒的就是,在还没有确定的情况下,最好还是用方式二的方法,这样的定义方**规,不会出错。
|