我正在使用AtmelStudio7为Atmel Mega645A控制器编写固件。我有一堆消息,我在16x2字符显示器上显示。为了保留SRAM空间,我试图将这些消息存储在ROM程序存储器中。我的问题是,我似乎正在覆盖已经用于其他代码的程序存储器部分。以下是详细信息:
我在主程序开头附近有以下声明:
#include "adht.h"
#include "languages.h"
在adht.h中我有以下内容:
#include <avr/pgmspace.h>
我相信我的问题的核心在我创建的头文件languages.h中。在languages.h中,我有数百行代码,如下所示:
const char M1_1_1[] PROGMEM = {32,32,32,32,69,110,116,101,114,105,110,103};
const char M1_2_1[] PROGMEM = {32,32,83,116,97,110,100,98,121,32,77,111,100,101};
const char M2_1_1[] PROGMEM = {32,32,70,87,32,82,101,118,105,115,105,111,110};
const char M2_2_1[] PROGMEM = {32,32,32,32,40,110,117,109,98,101,114,41};
const char M3_1_1[] PROGMEM = {32,78,79,46,32,79,70,32,84,72,69,82,65,80,89};
const char M3_2_1[] PROGMEM = {32,32,32,32,83,69,83,83,73,79,78,83,58};
.
.
. etc. etc.
当我使用这样的~660行编译时,AtmelStudio会报告以下内容: 程序内存使用:34892字节53.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整
如果我注释掉大部分“const char ....”行并重建,我得到了这个:
程序内存使用:34896字节53.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整
......看起来差不多。但是,这两个版本都将允许我的程序的其余部分运行没有问题。
这是我遇到麻烦的地方。在languages.h中,我有以下代码:
PGM_P const string_table[] PROGMEM =
{
M1_1_1 , M1_1_2 , M1_1_3 , M1_1_4 , M1_1_5 , M1_1_6}; /* ,
M1_2_1 , M1_2_2 , M1_2_3 , M1_2_4 , M1_2_5 , M1_2_6 ,
M2_1_1 , M2_1_2 , M2_1_3 , M2_1_4 , M2_1_5 , M2_1_6 ,
M2_2_1 , M2_2_2 , M2_2_3 , M2_2_4 , M2_2_5 , M2_2_6 ,
M3_1_1 , M3_1_2 , M3_1_3 , M3_1_4 , M3_1_5 , M3_1_6 ,
.
.
. etc. etc.
现在你会注意到在M1_1_1的第一行之后...我已经注释掉了 “/ ”其余的“指针赋值”。请放心,我在作业结束时有一个“ /”。如果我只有6个指针分配,我的代码工作正常。如果我将“/ *”向下移动几行以便编译更多行代码,我程序的其余部分就会开始变得惊慌失措,好像我已经没有程序存储器了。我的程序以不同的方式失败,具体取决于编译了多少“指针赋值”。 (注意我在这个论坛中键入“asterisk反斜杠”时遇到问题)。当我使用未注释掉的八行代码进行编译时,编译器将报告以下内容:
程序内存使用:35530字节54.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整
当我取消注释所有这些行时,编译器会报告以下内容:
程序内存使用:44690字节68.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整
很明显,我正在填写程序存储器,但没有接近极限。
为了完成,我在主程序中将消息从程序存储器复制到SRAM中,如下所示:
char line1[16];
char line2[16];
PGM_P p;
memcpy_P(&p, &string_table[0], sizeof(PGM_P));
strcpy_P(line1, p);
memcpy_P(&p, &string_table[1], sizeof(PGM_P));
strcpy_P(line2, p);
稍后我将line1和line2发送到显示器。
所以在我看来问题出在我的
PGM_P const string_table[] PROGMEM =
线(S)。有人可以告诉我我是如何做到这一点的,这样我就不会覆盖我的其他程序吗?
更新:在主程序中,如果我在编译之前注释掉以下代码行,程序内存使用率会下降(达到54%),程序的其余部分工作正常:
char line1[16];
char line2[16];
PGM_P p;
memcpy_P(&p, &string_table[0], sizeof(PGM_P));
strcpy_P(line1, p);
memcpy_P(&p, &string_table[1], sizeof(PGM_P));
strcpy_P(line2, p);
当我取消注释此代码并重新编译时,程序内存使用率会回升至68%,然后当我运行它时,程序的其余部分就会变坏。那么覆盖程序存储器的这些代码行是什么呢?
更新#2:在上面的代码行中,如果我注释掉这两行:
strcpy_P(line1, p);
strcpy_P(line2, p);
我的计划有效。当然,我仍然无法访问存储在程序存储器中的数据。请有人告诉我发生了什么事。如何将数据(字符数组或uint_8数组)放入RAM中,以便显示到16x2屏幕?
答案 0 :(得分:0)
在标准C中,如果您在头文件中有此内容:
const char M1_1_1[] = {32,32,32,32,69,110,116,101,114,105,110,103};
并且两个或多个翻译单元包括该头文件,由于具有相同对象的多个定义,因此是未定义的行为。由于编译器/链接器为每个定义或其他任何内容使用内存,这可能表现为高内存使用率。
如果您可以重新排列代码,以便定义只出现在.c
文件中,那么可能会解决问题。其他单位可以extern const char M1_1_1[];
访问数据。