求教:CVAVR中EEPROM操作问题,如何用指针在指定地址写入指定数值,高手赐教!!!
我想在eeprom的指定位置比如0x0001写入一个指定数值例如0x12,应该怎么写?我今天翻了一天的论坛也没能找到答案,求各位大哥帮帮小弟...马老师的书里关于eeprom这方面感觉写得太少了,小弟实在不知道该怎么解决...
#include <mega16.h>
#define uchar unsigned char
#define uint unsigned int
eeprom uchar *pa;
void main(void)
{
pa=0x01; //我从别的参考书上看到这样写可以指定地址,但是编译时会出现错误
*pa=0x12;
}
错误内容:a value of type 'char' can't be assigned to an entity of type "eeprom unsigned char"
请问该如何修改才能正确? 你问了一圈,最后转到这里了。
首先建议你看的是CVAVR软件中的帮助。你使用什么平台,就必须要熟悉该平台的功能和特点,每个平台都有差别。因为对与FLASH和EEPROM中的变量已经指针等,都是非标准C的东西,每个平台处理方法不一样。另外,你的C语言基础要好(不是指学校学的那点东西,以及能编一些代码),否则你看不懂,尽管CVAVR的帮助有中文翻译版的。
现在仅提供在CVAVR里如何定位EEPROM变量的简单办法。
1。CVAVR中不能直接指定EEPROM中变量的地址,它是按用户定义EEPROM变量的先后次序,顺序分配在EEPROM空间。
2。CVAVR中有类似 @0x20的变量定义方法,但只是将变量定义在指定的寄存器或RAM中,没有特殊的情况,不要使用这样的定义。
3。CVAVR中对EEPROM中的变量操作比其它的平台要方便,只要定义了在EEPROM中的变量,在程序中就如同使用了普通变量。不过注意不能无限制的赋值(写操作),因为EEPROM的写操作次数为10W次!所以通常只存放比较固定不变的变量在EEPROM中。
下面根据第1点,回答你的“指定EEPROM位置,比如0x0001,写入一个指定数值例如0x12”,并且在100的地址也存放一个0x12;
eeprom char temp; // temp 在0000
eeprom char a = 0x12; // a 在 0001
eeprom char tt; // 从0002开始的98个字节为tt数组
eeprom char b = 0x12; // b 在100的位置。
编译后在CVAVR产生的LST文件中可以查看EEPROM的变量分配情况。注意的是,编译后会产生2个文件,一个是HEX文件为FLASH中的代码,一个为EEP文件,是EEPROM变量的初值,2个文件需要一起下载写到AVR中。
下面是以上4句编译后在LST中的情况:
; 21 eeprom char temp; // temp 在0000
.ESEG
_temp:
000000 00 .DB0x0
; 22 eeprom char a = 0x12; // a 在 0001
_a:
000001 12 .DB0x12
; 23 eeprom char tt; // 从0002开始的98个字节为tt数组
_tt:
000002 00 .DB0x0
000003 00 .DB0x0
................
000062 00 .DB0x0
000063 00 .DB0x0
; 24 eeprom char b = 0x12; // b 在100的位置。
_b:
000064 12 .DB0x12 下面是CVAVR中关于指针使用的说明:
Pointers
Due to the Harvard architecture of the AVR microcontroller, with separate address spaces for data (SRAM), program(FLASH) and EEPROM memory, the compiler implements three types of pointers.
The syntax for pointer declaration is:
[<type storage modifier>] type * [<pointer storage modifier>]
[* [<pointer storage modifier>] ...] pointer_name;
or
type [<type storage modifier>] * [<pointer storage modifier>]
[* [<pointer storage modifier>] ...] pointer_name;
where type can be any data type.
Variables placed in SRAM are accessed using normal pointers.
For accessing constants placed in FLASH memory, the flash type storage modifier is used.
For accessing variables placed in EEPROM, the eeprom type storage modifier is used.
Although the pointers may point to different memory areas, they are by default stored in SRAM.
Example:
/* Pointer to a char string placed in SRAM */
char *ptr_to_ram="This string is placed in SRAM";
/* Pointer to a char string placed in FLASH */
flash char *ptr_to_flash1="This string is placed in FLASH";
char flash *ptr_to_flash2="This string is also placed in FLASH";
/* Pointer to a char string placed in EEPROM */
eeprom char *ptr_to_eeprom1="This string is placed in EEPROM";
char eeprom *ptr_to_eeprom2="This string is also placed in EEPROM";
In order to store the pointer itself in other memory areas, like FLASH or EEPROM, the flash or eeprom pointer storage modifiers must be used as in the examples below:
/* Pointer stored in FLASH to a char string placed in SRAM */
char * flash flash_ptr_to_ram="This string is placed in SRAM";
/* Pointer stored in FLASH to a char string placed in FLASH */
flash char * flash flash_ptr_to_flash="This string is placed in FLASH";
/* Pointer stored in FLASH to a char string placed in EEPROM */
eeprom char * flash eeprom_ptr_to_eeprom="This string is placed in EEPROM";
/* Pointer stored in EEPROM to a char string placed in SRAM */
char * eeprom eeprom_ptr_to_ram="This string is placed in SRAM";
/* Pointer stored in EEPROM to a char string placed in FLASH */
flash char * eeprom eeprom_ptr_to_flash="This string is placed in FLASH";
/* Pointer stored in EEPROM to a char string placed in EEPROM */
eeprom char * eeprom eeprom_ptr_to_eeprom="This string is placed in EEPROM";
In order to improve the code efficiency several memory models are implemented.
The TINY memory model uses 8 bits for storing pointers to the variables placed in SRAM. In this memory model you can only have access to the first 256 bytes of SRAM.
The SMALL memory model uses 16 bits for storing pointers the variables placed in SRAM. In this memory model you can have access to 65536 bytes of SRAM.
In both TINY and SMALL memory models pointers to the FLASH memory area use 16 bits.
Because in these memory models pointers to the FLASH memory are 16 bits wide, the total size of the constant arrays and literal char strings is limited to 64K.
However the total size of the program can be the full amount of FLASH.
In order to remove the above mentioned limitation, there are available two additional memory models: MEDIUM and LARGE.
The MEDIUM memory model is similar to the SMALL memory model, except it uses pointers to constants in FLASH that are 32 bits wide. The pointers to functions are however 16 bit wide because they hold the wordaddress of the function, so 16 bits are enough to address a function located in all 128kbytes of FLASH.
The MEDIUM memory model can be used only for chips with 128kbytes of FLASH.
The LARGE memory model is similar to the SMALL memory model, except it uses pointers to the FLASH memory area that are 32 bits wide.
The LARGE memory model can be used for chips with 256kbytes or more of FLASH.
In all memory models pointers to the EEPROM memory area are 16 bit wide.
Pointers can be grouped in arrays, which can have up to 8 dimensions.
Example:
/* Declare and initialize a global array of pointers to strings
placed in SRAM */
char *strings={"One","Two","Three"};
/* Declare and initialize a global array of pointers to strings
placed in FLASH
The pointer array itself is also stored in FLASH */
flash char * flash messages={"Message 1","Message 2","Message 3"};
/* Declare some strings in EEPROM */
eeprom char m1[]="aaaa";
eeprom char m2[]="bbbb";
void main(void) {
/* Declare a local array of pointers to the strings placed in EEPROM
You must note that although the strings are located in EEPROM,
the pointer array itself is located in SRAM */
char eeprom *pp;
/* and initialize the array */
pp=m1;
pp=m2;
}
Pointers to functions always access the FLASH memory area. There is no need to use the flash keyword for these types of pointers.
Example:
/* Declare a function */
int sum(int a, int b) {
return a+b;
}
/* Declare and initialize a global pointer to the function sum */
int (*sum_ptr) (int a, int b)=sum;
void main(void) {
int i;
/* Call the function sum using the pointer */
i=(*sum_ptr) (1,2);
} 哈哈~终于等到马老师的指导了~谢谢谢谢马老师~ 正在学习!!谢谢马老师!! 很多同行喜欢用翻译的资料做教材而懒得加些自己在实际中碰到到问题来点拨后生.一方面可能是因为时间不够吧.另一个隐性的原因就是"懒".现在很多编译器都附带了很多例子.无需再去翻译(这部分时间至少可以节省一半出来,那必须的一半是去看人家的例子.足矣.).
既然打算出来当老师,我想还应该更竞业一点.
另外对于后生,阅读专业资料的英文水平是必需的.少玩点游戏吧. 对于CVAVR中的情况,"1。CVAVR中不能直接指定EEPROM中变量的地址,它是按用户定义EEPROM变量的先后次序,顺序分配在EEPROM空间。",这显然不符合工作需要嘛.如果你事先不知道eeprom的指定位置(譬如用户通过UART输入指定位置....),我急死你.
我喜欢直接去问"office@hpinfotech.ro" .前面那位兄弟都不错,知道这个缺陷.很好啊.CVAVR自己的不足他们心知肚名也会去改善的.总之跟别的编译器而言,这是一个很大的缺点.反馈给他们这是我的一贯作法. 另外建议马老师:尽可能用C语言.就象聊天尽可能用MSN和SKYPE一样. to 123456jj:
我教这门课程已经8、9个年头了,没有一个学生问到这样的问题,因为他们学的还是基础知识和应用。可贴上本帖的问题的人估计已经不是学生,或至少是研究生了,在做具体的项目或产品。我给出原文的提示帮助已经是不错了,没有义务仔细说明吧。
作为教师,我直接是面对我教的课堂学生,我同样要求他们要看英文原版的资料,就是考试也有英文的东西。
我认为我已经是非常竞业了。你只有3个积分,可见你在这里有多少的贡献,给了多少人的帮助。恐怕没有资格说别人吧。 *((eeprom unsigned char *)0x01) = 0x12;
——难道不能写成这样吗? 亲爱的马老师,本人绝无对您不敬的意思.我只是在感叹堂堂中华这么多人员在目前的科技领域(这个方面)不那么尽如人意有点哀伤.
本人在沿海地区打工很多年(您可以把我理解成农民工吧),写软件,用的都是国外牌子的单片机.伤心啊.没本事进中科院,在此独自感叹而已.
言语过于刻薄,向您致歉!对不住. 我英文也很差劲的,但在工作中,经常碰到一些技术问题,芯片供应商的FAE总是搞不定(哈哈,他们也不是万能的小伙子),没办法只得自己发蹩脚的邮件向编译器生产商的技术人员请教(我从心底里佩服他们的博学及敬业).我用PIC最多,AVR前几年用过,忘了,先要重新拾起(都是工作需要).
附HP InfoTech今天回复的邮件(人家还在圣诞节其间!)
Hello
eeprom unsigned char abc @ 0x02;
....
abc=0x56;
Best regards,
Pavel Haiduc
Manager
**********************************
HP InfoTech S.R.L
Bd. Decebal nr.3
Bl.S12B Sc.2 Ap.29
Sector 3
Bucharest 030962
ROMANIA
EUROPEAN UNION
e-mail: office@hpinfotech.ro
http://www.hpinfotech.ro
phone: (+40)-723469754
(+40)-213261875
fax: (+40)-213261876
**********************************
----- Original Message -----
From:
To: <office@hpinfotech.ro>
Sent: Monday, December 29, 2008 5:27 AM
Subject: How to operate the special address for inner eeprom
Dear Sir,
Merry Christmas and Happy New Year!
How to operate the special address for inner eeprom in CVAVR ?
For an example: I want to write data 0x56 in address 0x02 in
EEPROM, how can I do it?
I can not find example from website and attached example of
compiler.
Thanks. 刚才依照HP InfoTech的建议,完成EEPROM读写操作的小程序附下(我们经常会先准备好一些自己写好的小程序备份一备以后工作调用,免得临时碰到问题影响项目进程.已调试过OK)给兄弟姐妹参考参考吧.我不需要积分的.谢谢!
/*****************************************************
#include <mega8.h>
// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>
//eeprom unsigned int ee_addr0 @0x0000;
eeprom unsigned char ee_addrx;
void initia(void); // move all initialization here from main()
void main(void)
{
char c;
unsigned int addr;
unsigned char data;
// Declare your local variables here
initia();
while (1)
{
// Place your code here
printf("\r\rPlease select operation mode:\r");
printf("r --- read one byte\r");
printf("w --- write one byte\r");
c = getchar();
printf("\ryou just typed \'%c\'",c);
switch (c)
{
case 0x72 : // ASCII for 'r'
printf("\rPlease input the hex address(<0x0200, such as 000A) you want to read: ");
scanf("%4x",&addr); // for data receiving "scanf" function is the best one.
if(addr < 0x200)
{
data = ee_addrx;
printf("\rData read from EEPROM is %X",data);
}
else printf("\rSorry! address you typed is out of range: ");
break;
case 0x77 : // ASCII for 'w'
printf("\rPlease input the hex address(<0x0200, such as 0002) you want to write: ");
scanf("%4x",&addr); // for data not "char" receiving "scanf" function is the best one.
if(addr < 0x200)
{
printf("\rPlease input hex data you want to write: ");
scanf("%2x",&data);
ee_addrx = data;
}
else printf("\rSorry! address you typed is out of range: ");
break;
default: break;
}// end switch
};
}
void initia(void) // move all initialization here from main()
{
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600 (Double Speed Mode)
UCSRA=0x02;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0C;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
} 雁过留言,经过这里而已!拜拜.新年快乐! #include <mega8.h>
#include <delay.h>
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer;
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif
// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;
// USART Receiver interrupt service routine
interrupt void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer=data;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
};
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer;
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif
// Standard Input/Output functions
#include <stdio.h>
// Declare your global variables here
eeprom unsigned char eepromArray;
void main(void)
{
unsigned char temp,i;
unsigned char buf,index;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
#asm("sei")
putsf("wait");
for(i=0;i<255;i++)
{
eepromArray = 255-i;
}
while (1)
{
temp = getchar();
putchar(temp);
if(temp == 'r')
{
temp = getchar();
i = eepromArray;
putchar(i);
}
if(temp == 'w')
{
temp = getchar();
putchar(temp);
i= getchar();
putchar(i);
eepromArray = i;
}
};
}
通过串口控制eeprom读写,通过数组来设置在某地址上读写eeprom。朋友们看看,有没有什么问题 我也对这个问题发表些看法,我在CVAVR1248d 版本中,可以定义,eeprom unsigned char *eePtr=0x01;
这句话编译可以通过,而且含义是eePtr 指向0x01这个地址的,若向0x01写入0x88,则 *eePtr=0x88; 即可。
但是我在cvavr2304版本,就编译通不过,出现和楼主一样的错误提示,
高手们,有谁能指教一下啊 谢谢各位的讨论,掌握了 精彩,这才叫论坛 真的很不错 认识上又有进步,感谢各位! 精彩 eeprom char temp; // temp 在0000
eeprom char a = 0x12; // a 在 0001
eeprom char tt; // 从0002开始的98个字节为tt数组
eeprom char b = 0x12; // b 在100的位置。
/************************************************/
eeprom unsigned char abc @ 0x02;
abc=0x56;
MARK 论坛 mark 据我所知,CV在版本2.03.2以前@不能用于EEPROM变量的定义,而此后就可以了。如使用2.03.2以前的(也可以是以后的),可以用:
eeprom unsigned char*P = (eeprom unsigned char *)0x00;
*P = 0x00 ; mark. mark 很精彩 很好mark 回复【24楼】Paul
-----------------------------------------------------------------------
MARK mark
页:
[1]