您好,
我正在使用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
}
答案 0 :(得分:0)
这可能存在问题:
unsigned char数据; //保存的数组保存接收的数据
首先,这不是一个数组,而是存储单个字符,但是你似乎没有尝试在那里存储一个数组,所以它只是被误解了。
但是,你做似乎是从ISR和主线程访问它,如果你打算这样做,你需要将它声明为volatile。否则,编译器可以自由地将值缓存在寄存器中,这可能使其对给定线程是私有的,或者甚至更糟糕的是,决定没有人使用该值,因此拒绝存储它。
您已经以这种方式保护了您的国旗,但您也需要保护数据。