|
发表于 2008-7-11 23:58:55
|
显示全部楼层
谢谢。我重新仔细参考了手册,是有这样的问题。使用一个标志变量解决这个BUG。
具体代码见如下:
#define SIZE 100
unsigned char SPI_rx_buff[SIZE];
unsigned char SPI_tx_buff[SIZE];
unsigned char rx_wr_index,rx_rd_index,rx_counter,rx_buffer_overflow;
unsigned char tx_wr_index,tx_rd_index,tx_counter;
unsigned char SPI_free;
interrupt [SPI_STC] void spi_isr(void) // SPI 完成中断服务
{
SPI_rx_buff[rx_wr_index] = SPDR; // 从SPI口读出收到的字节放入接收缓冲区
if (tx_counter) // 如果发送缓冲区中有待发的数据
{
SPDR = SPI_tx_buff[tx_rd_index]; // 发送1字节数据,
--tx_counter; // 待发送数据个数减1
if (++tx_rd_index == SIZE) tx_rd_index = 0; // 调整发送缓冲区队列指针
}
else SPI_free = 1; // 无待发送数据,置SPI空闲
if (++rx_wr_index == SIZE) rx_wr_index = 0; // 调整接收缓冲区队列指针
if (++rx_counter == SIZE)
{
rx_counter = 0;
rx_buffer_overflow = 1; // 接收数据溢出
}
}
unsigned char getSPIchar(void)
{
unsigned char data;
while (rx_counter == 0); //无接收数据,等待(死循环!)
data = SPI_rx_buff[rx_rd_index]; //从接收缓冲区取出一个SPI收到的数据
if (++rx_rd_index == SIZE) rx_rd_index = 0; //调整指针
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
void putSPIchar(unsigned char c)
{
while (tx_counter == SIZE); // 发送缓冲区满,等待
#asm("cli")
if (SPI_free)
{
SPDR = c; // SPI口空闲,直接放入SPDR由SPI口发送
SPI_free = 0; // 置SPI忙
}
else
{
SPI_tx_buffer[tx_wr_index] = c; // 将数据放入发送缓冲区排队
if (++tx_wr_index == SIZE) tx_wr_index = 0; //调整指针
++tx_counter;
}
#asm("sei")
}
void spi_init(void)
{
unsigned char temp;
DDRB |= 0xB0; // MISO为输入方式,MOSI,SCK和~SS为输出方式
PORTB |= 0x40; // MISO上拉电阻有效
SPCR = 0xD5; // SPI允许,主机模式,MSB方式,允许SPI中断,极性方式01,1/16系统时钟频率
SPSR = 0x00;
temp = SPSR;
temp = SPDR; // 清除SPI中断标志位,使SPI空闲
SPI_free = 1; // 置SPI空闲
}
void main(void)
{
unsigned char i;
#asm("cli") // 关中断
spi_init(); // 初始化SPI接口
#asm("sei") // 使能中断
while()
{
putSPIchar(i); // 通过SPI发送1字节
i++;
getSPIchar(); // 读取SPI接收的字节
………
}
} |
|