我正在尝试从EEPROM (微控制器ATmega2560)读写数据,这给了我错误的答案。当我调试它时,我看到只有最后一个字符被读取,尽管我看到数据被写到不同的地址。
在uiAddress = 1时,数据为A,在uiAddress =2时,数据为B,uiAddress=3 data=67'C',依此类推。因此,当您从uiAddress =0读取到最后一个地址时,应该会得到ABCDE。我正在读一位,一次读一个字符。
EESAVE已启用。
为什么会发生这种情况?(我已经尝试包含尽可能多的代码,原始文件太大。但这是令人关注的领域)。
#include<avr/io.h>
#include<avr/eeprom.h>
#include<avr/interrupt.h>
volatile UINT intrs, i = 1, count, switch_pressed = 0, uiAdd, uiAddEnd, flag_led_intr;
volatile UINT record, play_recorded_keys, flag_serial_receiver;
volatile unsigned char get_switch=0, data, TX_complete, TX, RX;
extern void __vector_25 (void) __attribute__ ((signal)); //Interrupt vector
#define LED_DELAY 10
#define F_CPU 2000000L
#define BAUDRATE 9600
#define BAUD_PRESCALER (((F_CPU/(BAUDRATE * 16UL)))-1)
void ReadWriteSerialPort(void)
{
while(((UCSR0A) & (1<<UDRE0)) == 0)
;
UDR0 = RX;
if(RX == 0x1A) //CRTL-z
{
record = !record;
play_recorded_keys = 0;
}
else
if(RX == 0x19) //CRTL-y
{
record = 0;
uiAdd = 0;
play_recorded_keys = !play_recorded_keys;
}
if(record == 1)
{
EEPROM_write(uiAdd++, RX);
}
if(uiAdd == 4096)
{
record = 0;
uiAddEnd = 4096;
}
else
uiAddEnd = uiAdd;
}
void initialize(void)
{
cli(); //Stop all interrupts
flag_led_intr = 0;
record = 0;
play_recorded_keys = 0;
RX = 0;
TX = 0;
flag_serial_receiver = 0;
uiAdd = 0;
uiAddEnd = 0;
enable_ports();
usart_init();
sei();
}
void enable_ports() //Enables PORTB, PORTD
{
DDRB = 0xff; //PORTB as output for leds
PORTB = 0xff; //Initialize PORTB
DDRD = 0x00; //PORTD as input for switches
}
void usart_init(void) //Enables USART
{
/* Set baud rate */
UBRR0L = BAUD_PRESCALER);
UBRR0H = (BAUD_PRESCALER>>8);
/* Set frame format: 8 bit data + start bit + stop bit */
UCSR0C = 0x06;
/* Enable reciever and transmitter */
UCSR0B = 0x98;
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
while(EECR & (1<<EEPE)); /* Wait for completion of previous write */
EEARH = (uiAddress>>8); /* Set up address and Data Registers */
EEARL = uiAddress;
EEDR = ucData;
cli();
EECR |= (1<<EEMPE); /* Write logical one to EEMPE */
EECR |= (1<<EEPE); /* Start eeprom write by setting EEPE */
sei();
}
unsigned char EEPROM_read(unsigned int uiAddress)
{
while(EECR & (1<<EEPE)); /* Wait for completion of previous write */
EEARH = (uiAddress>>8); /* Set up address register */
EEARL = uiAddress;
EECR |= (1<<EERE); /* Start eeprom read by writing EERE */
return EEDR; /* Return data from Data Register */
}
void __vector_25 (void)
{
RX = UDR0;
flag_serial_receiver = 1;
sei();
}
int main(void)
{
initialize();
while(1)
{
if(flag_serial_receiver == 1)
{
ReadWriteSerialPort();
flag_serial_receiver = 0;
}
if(play_recorded_keys)
{
TX = EEPROM_read(uiAdd);
uiAdd++;
if(uiAdd == 4096 || uiAdd >= uiAddEnd)
{
play_recorded_keys = 0;
uiAdd = 0;
}
while(((UCSR0A) & (1<<UDRE0)) == 0)
;
UDR0 = TX;
}
}
return(0);
}发布于 2010-12-11 06:34:17
我敢打赌,您的写入或读取或两者都不会发生。请使用调试器或调试输出根据芯片数据表手动检查配置寄存器内容,以验证您是否按照ruslik在注释中提示的那样正确构建了标志位。
一个有用的测试是在调用read之前将EEDR设置为意外的测试值。如果读取返回了这个意外的值,那么您知道您实际上并没有读取,而只是得到了一个陈旧的EEDR值。这可能是因为没有设置正确的标志,或者可能需要等待读取完成,但没有这样做。
您还可以尝试调整顺序或写入和读取-例如,按递增的顺序写入,但按递减的顺序读出。
尝试构建这样的测试,以揭示不同类型的错误,我相信您很快就会发现它。
发布于 2014-05-20 06:25:06
代码与AVR数据手册中的代码相同,并添加了两个宏。
#define sbi(port,bit) __asm__ __volatile__ ( "sbi %0, %1" :: "I" (_SFR_IO_ADDR(port)),"I" (bit))
#define cbi(port,bit) __asm__ __volatile__ ( "cbi %0, %1" :: "I" (_SFR_IO_ADDR(port)),"I" (bit))
//Write data to EEPROM
void EEPROM_WRITE(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEPE));
/* Set up address and Data Registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMPE */
//EECR |= (1<<EEMPE);
sbi(EECR,EEMPE);
/* Start eeprom write by setting EEPE */
//EECR |= (1<<EEPE);
sbi(EECR,EEPE); //You need to set EEPE within four clock cycles to `enter code here`initiate writing.
}使用带有优化程序集-O0的GCC花费的时间太长,因此超过4个时钟周期,因此它将不会写入。几个简单的宏就可以解决这个问题。
https://stackoverflow.com/questions/4412111
复制相似问题