从STK600上的外部dataflash获取垃圾数据

时间:2015-03-01 11:54:48

标签: embedded spi eeprom

您好,
         我正在使用STK600,我使用SPI编写了外部dataflash的代码。当我从dataflash读取数据时,我正确地接收了第一个数据字节,但之后我将所有数据字节作为垃圾值接收。我在SPI中读取数据,在PWM中断中将相同的数据放在UART上。 SPI和PWM中断都正常工作。          我还尝试将数据字节值放在SPI中断的LED端口上,以确认在PWM中断进入UART之前是否有任何数据损坏。但我发现两个数据值(一个在LED端口上,另一个在超级终端上)都是相同的,所以没有数据损坏。          我直接从SPI中断本身接收垃圾值。请帮帮我,这是我的代码文件。

      #include <asf.h>


      //Slave select low

      #define cs_low() \
      delay_us(10);\
      PORTB=(0<<PB0);\
      delay_us(10);

      //Slave select high

      #define cs_high() \
      delay_us(10);\
      PORTB=(1<<PB0);\
      delay_us(10);


      char opcode_cnt=0;               //Counts number bytes required before start reading actual data
      unsigned char data;         //Array to save save received data
      unsigned int dummy_byte_cnt=0;            //total dummy bytes sent to receive data
      volatile char rd_cmplete_flg=0;   //Flag is set after read operation completed
      int pg_addr;                     //Indicates address of page
      int buff_addr;                   //Indicates starting address of buffer
      unsigned int i=0;
      int array[3];
      char sample_count=4,pwm_init=0;


      void init_pwm(void);
      void spimstr_init(void);
      void spi_tx(unsigned char byte);
      void spi_tx_ISR(unsigned char byte);
      unsigned char spi_rx_ISR(void);
      unsigned char spi_rx(void);
      unsigned char get_status(void);
      void init_uart(void);
      void pg_erase(unsigned int pg_addr);
      void continuous_pg_read(unsigned int page_address,unsigned int buffer_address);




      int main (void)
    {
      // Insert system clock initialization code here (sysclk_init()).

      board_init();

      init_uart();

      spimstr_init();

      continuous_pg_read(0x00,0x00);

      while(1)
    {
       if(rd_cmplete_flg)

          init_pwm();            
    }

     // Insert application code here, after the board has been initialized.
   }



    void spimstr_init()
   {
    //Master Mode Selected
    //MSB out first
    //Clock Polarity and Clock Phase selected as 1
    //Clock Frequency 8MHz/2 selected

    SPCR|=(1<<SPE)|(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(0<<SPR1)|  (0<<SPR0);

    SPSR=(1<<SPI2X);             //Doubles the clock frequency
   }



    void spi_tx(unsigned char byte)
   {
    SPDR=byte;

    while(!(SPSR&(1<<SPIF)));        //wait until transmission is completed
   }



    void spi_tx_ISR(unsigned char byte)
   {
    SPDR=byte;
   }


    unsigned char spi_rx()
   {
    spi_tx(0x00);                    //sending dummy byte

    while(!(SPSR&(1<<SPIF)));        //wait until reception is completed

    return SPDR;
   }


    unsigned char spi_rx_ISR()
   {
    return SPDR;
   }




     unsigned char get_status()
   {
     unsigned char status;

     //high to low transition made on SS

     cs_low();

     spi_tx(0xd7);            //opcode to read status register of EEPROM

     status=spi_rx();         //Received the value of status register of EEPROM

     status=status & 0x80;

     //low to high transition made on SS

     cs_high();

     return status;
    }


     void pg_erase(unsigned int pg_addr)
    {
     while(get_status()==0x00);

     cs_low();

     spi_tx(0x81);

     spi_tx((0x00)|(pg_addr>>7));

     spi_tx((pg_addr<<1)|0x00);

     spi_tx(0x00);

     cs_high();
    }


     void init_uart()
    {
     UBRR1H=0x00;

     UBRR1L=0x01;          //Baud rate 256000 selected      

     UCSR1B|=(1<<RXEN1)|(1<<TXEN1);

     UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);
    }



     void continuous_pg_read(unsigned int page_address,unsigned int buffer_address)
    {
     pg_addr=page_address;

     buff_addr=buffer_address;

     while(get_status()==0x00);

     cs_low();

     spi_tx(0xe8);                           //opcode to read page

     SREG=0x80;

     SPCR|=(1<<SPIE);
   }



     void init_pwm()
   {
      if(!pwm_init)
     {
      pwm_init=1;

      DDRB = (1<<PB5);                          // set OC1A as output

      TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM10);// set OC1A on compare match,clear OC1A at bottom
      // 8 bit fast PWM

      TCCR1B = (1<<WGM12)|(1<<CS10);               // 8bit fast PWM and clock=8Mhz   
     }

      TIMSK1|=(1<<TOIE1);                     // enable timer 1 overflow interrupt
    }





      ISR(TIMER1_OVF_vect)
    {
      //PORTA=0x55;

      //delay_ms(15000);

      sample_count--;

      if(sample_count==0)
     {
        sample_count=4;

        if(rd_cmplete_flg)
       {
          TIMSK1=(0<<TOIE1);

          rd_cmplete_flg=0;

          UDR1=data;

          while(!(UCSR1A & (1<<UDRE1)));

           i++;

           if(i>=23923)
          {
           SREG=0x00;
          }

           cs_low();

           spi_tx_ISR(0xe8);
         }
       } 
        //PORTA=~PORTA;

        //delay_ms(15000);
      }





      //ISR for Continuous Array Read mode

        ISR(SPI_STC_vect)
   {
         //PORTA=0xff;

         //delay_ms(15000);

         opcode_cnt++;

         switch(opcode_cnt)
       {
         case 1:

              //PORTA=0X11;

              //delay_ms(15000);

              spi_tx_ISR((0x00)|(pg_addr>>7));

              break;

         case 2:

             //PORTA=0X22;

             //delay_ms(15000);

             spi_tx_ISR((pg_addr<<1)|(buff_addr>>8));

             break;

         case 3:

            //PORTA=0X33;

            //delay_ms(15000);

            spi_tx_ISR(buff_addr & 0x00ff);

            break;

         case 4:

            //PORTA=0X44;

            //delay_ms(15000);

             spi_tx_ISR(0x00);

             break;

         case 5:

            //PORTA=0X55;

            //delay_ms(15000);

            spi_tx_ISR(0x00);

            break;

        case 6:

            //PORTA=0X66;

            //delay_ms(15000);

            spi_tx_ISR(0x00);

            break;

        case 7:

            //PORTA=0X77;

            //delay_ms(15000);

            spi_tx_ISR(0x00);

            break;

        case 8:

            spi_tx_ISR(0x00);

            break;  
       }


           if(opcode_cnt>=9)
        {
            opcode_cnt=0;                //Reset to zero to repeat switch case

            if(rd_cmplete_flg==0)
           {
             data=spi_rx_ISR();

             //PORTA=data;

             //delay_ms(15000);     

             rd_cmplete_flg=1;
            }
             //Important Note

             //The buffer address and page address has to be incremented before cs_high() only then only this mode works

             if(buff_addr<263)
            {
             buff_addr++;
            }

             else
            {
             buff_addr=0;

             pg_addr++;
            }

           cs_high();

           //PORTA=0x30;

           dummy_byte_cnt++;

           //PORTA=0x40;

           //cs_low();

           //spi_tx_ISR(0xe8);            //Resend page read opcode to    read next  byte of data

            if(dummy_byte_cnt>=23923)
           {
            SREG=0x00;

            buff_addr=0;

            pg_addr=0;

            dummy_byte_cnt=0;
           }
         }
        //PORTA=~PORTA;

        //delay_ms(15000);
       }



        void board_init(void)
       {
        DDRA|=0xff;                          //optput port for LED

        DDRB|=(1<<DDB2)|(1<<DDB1)|(1<<DDB0);     //Direction of SS,MISO,SCK,MOSI  pin selected
       }

1 个答案:

答案 0 :(得分:0)

这可能存在问题:

  
    

unsigned char数据; //保存的数组保存接收的数据

  

首先,这不是一个数组,而是存储单个字符,但是你似乎没有尝试在那里存储一个数组,所以它只是被误解了。

但是,你似乎是从ISR和主线程访问它,如果你打算这样做,你需要将它声明为volatile。否则,编译器可以自由地将值缓存在寄存器中,这可能使其对给定线程是私有的,或者甚至更糟糕的是,决定没有人使用该值,因此拒绝存储它。

您已经以这种方式保护了您的国旗,但您也需要保护数据。