1

您好,
我正在使用 STK600,并且我已经使用 SPI 为外部数据闪存编写了代码。当我从 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
       }
4

1 回答 1

0

这可能是有问题的:

无符号字符数据;//数组保存保存接收到的数据

首先,这不是一个数组,而是单个字符的存储,但是您似乎没有尝试在其中存储一个数组,所以它只是被错误描述了。

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

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

于 2015-03-01T15:14:02.707 回答