2010-12-10 3 views
0

Я пытаюсь написать и прочитать данные с EEPROM (микроконтроллер ATmega2560), что дает мне неправильный ответ. Когда я его отлаживаю, я вижу, что читается только последний символ, хотя я вижу, что данные записываются по разным адресам.AVR EEPROM чтение-запись

В uiAddress = 1 данные: A, at 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); 
} 
+1

'' ABC '' слишком велик, чтобы вписаться в 'char' - можете ли вы лучше объяснить, что вы пытаетесь сделать? –

+1

Я думаю, что вы не понимаете разницы между C-строками и символами. – Earlz

+0

. Вы должны включить код для вызова каждого из 'EEPROM_read' и' EEPROM_write' с ожидаемыми результатами для них. – nategoose

ответ

0

Я бы поспорил, что ни ваша запись, ни чтение, ни то и другое не происходит. Убедитесь, что вы правильно строите бит флага, так как ruslik намекает на комментарии, используя отладчик или отладочный вывод, чтобы вручную проверить содержимое регистра конфигурации на листе данных чипа.

Полезным испытанием было бы установить EEDR до неожиданного значения теста перед вызовом чтения. Если чтение возвращает это неожиданное значение, вы знаете, что на самом деле вы его не читали, а просто получили устаревшее значение EEDR. Это может быть связано либо с не установкой правильных флагов, либо, возможно, с необходимостью ждать завершения чтения, но не для этого.

Вы также можете попробовать сыграть с заказом или написать и прочитать - например, писать в порядке возрастания, но при чтении в уменьшении.

Экспериментируйте с построением таких тестов, которые выявили бы различные виды ошибок, и я уверен, что вы быстро это выясните.

+0

while (EECR & (1 < Вот как это указано в техническом описании, написав «while (EECR & EEPE)», «не решает». Я буквально пытался изменить все, прежде чем публиковать его на форуме, но ни один из них и я не это Pro, используя EEPROM в первый раз. – sneezy

+1

Решение этого типа проблемы не связано с знаниями, речь идет о творческом логическом мышлении - «если проблема была в этом, и я изменил ее, тогда она должна произвести этот результат «И вы попробуете эксперимент. Я дал вам несколько экспериментов, чтобы попробовать, вы можете думать о себе больше. –

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 часов цикла и поэтому он не будет писать. Несколько простых макросов, которые превышают эту проблему.

+0

+1 для намека на проблемы синхронизации, которые могут возникать и выполняться с оптимизацией компилятора. – JimmyB

Смежные вопросы