2010-12-10 6 views
0

私は間違った答えを与えるEEPROM(マイクロコントローラATmega2560)からデータを書き込んで読み込もうとしています。デバッグすると、データが異なるアドレスに書き込まれているのがわかりますが、最後の文字だけが読み込まれていることがわかります。AVR EEPROM読み書き

uiAddress = 1の場合、データはA、uiAddress = 2の場合、データはB、uiAddress = 3 data = 67'C 'などとなります。したがって、uiAddress = 0から最後のアドレスまで読み込むと、ABCDEが得られます。私は一度に1文字、1文字読む。

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);」と書かれている方法で解決されません。 – sneezy

+1

このタイプの問題を解決することは、知識に関するものではなく、創造的な論理的思考に関するものです。「問題がこれならば、これを変えれば、この結果が得られるはずです。 "あなたは実験を試してみてください。私は試してみるためにいくつかの実験をしました。もっと自分のことを考えることができます。 –

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

オプティマイザセット-O0でGCCを使用すると、4クロックサイクル以上の時間がかかるため、書き込まれません。 いくつかのシンプルなマクロがこの問題を引き起こしています。

+0

+1は、コンパイラの最適化を行ったり来たりするかもしれないタイミングの問題をヒントします。 – JimmyB

関連する問題