0

我正在尝试从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);
}
4

2 回答 2

2

在 AVR DATA BOOK 中找到的代码添加了两个宏。

#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.
}

将 GCC 与优化器设置 -O0 一起使用需要太长时间,因此超过 4 个时钟周期,因此它不会写入。几个简单的宏解决了这个问题。

于 2014-05-19T22:25:06.123 回答
0

我敢打赌,您的写入或读取或两者都没有发生。请通过使用调试器或调试输出手动检查配置寄存器内容与芯片数据表,验证您是否按照注释中提示的 ruslik 正确构建标志位。

一个有用的测试是在调用读取之前将 EEDR 设置为意外的测试值。如果读取返回此意外值,您就知道您实际上并未读取,而只是获得了一个陈旧的 EEDR 值。这可能是由于没有设置正确的标志,或者可能需要等待读取完成但没有这样做。

您也可以尝试使用顺序或写入和读取 - 例如,以递增顺序写入但以递减顺序读取。

尝试构建这样的测试来揭示不同类型的错误,我相信你会很快弄清楚。

于 2010-12-10T22:34:16.793 回答