mojinpan 发表于 2007-8-20 07:27:02

参照着马老师的spi例子写的,但是有些问题,请老师看看

参照着马老师的spi例子写的,但是有些问题,请老师看看。主从机能收能发,但是收发的数据好像不对,开始用液晶调试的,发现从机液晶显示错误,但是返回给主机的数据是对的。后来怀疑是液晶速度跟不上,改用串口来显示数据,发现从机接收到的都是0,我是初学者,自己实在找不出问题所在。请马老师有空的时候帮忙看一下,谢谢。

主机部分:

#include <iom64v.h>

#include <macros.h>

#include "1602.h"

#include "delay.h"

#define SIZE 100

unsigned char SPI_rx_buff;         //收信箱

unsigned char SPI_tx_buff;               //发信箱

unsigned char rx_wr_index;                               //收信箱写指针

unsigned char rx_rd_index;                               //收信箱读指针

unsigned char rx_counter;                               //收信箱存量

unsigned char rx_buffer_overflow;               //收信箱满标志

unsigned char tx_wr_index;                               //发信箱写指针

unsigned char tx_rd_index;                               //发信箱读指针

unsigned char tx_counter;                               //发信箱存量

unsigned char SPI_ok=1;



#pragma interrupt_handler spi_stc_isr:18

void spi_stc_isr(void)

{

SPI_ok = 1; // SPI 空闲   

SPI_rx_buff = SPDR;                             //从ISP口读出收到的字节

if (++rx_wr_index == SIZE) rx_wr_index = 0;    //如果收信箱满则指针归零

if (++rx_counter == SIZE)

{

    rx_counter = 0;                                                            //收信箱清空

    rx_buffer_overflow = 1;                                       //置满标志位

}

if (tx_counter)                                                     //如果发送缓冲区中有待发的数据

{

   --tx_counter;                                                                //发送一个字节数据,存量减1

   SPDR = SPI_tx_buff;   

   if (++tx_rd_index == SIZE) tx_rd_index = 0; //发信箱发完后读指针归零

       SPI_ok = 0; //SPI忙

}

}



unsigned char getSPIchar(void)

{

unsigned char data;

while (rx_counter == 0);                                               //收信箱空则等待

data = SPI_rx_buff;                             //从接收缓冲区取出一个SPI收到的数据

if (++rx_rd_index == SIZE) rx_rd_index = 0;   //调整指针

CLI();

--rx_counter;

SEI();

return data;

}



void putSPIchar(char c)

{

while (tx_counter == SIZE);                                             //发信箱满,等待

CLI();

if (tx_counter || SPI_ok==0)                  //发送缓冲区已中有待发数据

{               

    SPI_tx_buff = c;                             //将数据放入发信箱排队

    if (++tx_wr_index == SIZE) tx_wr_index = 0;   //调整指针

    ++tx_counter;

}

else

   {

    SPDR = c;                   //发送缓冲区中空且SPI口空闲,直接放入SPDR由SIP口发送

        SPI_ok = 0;

       

        }   

SEI();



}



void putSPIstring(unsigned char *ptr)

{

while(*ptr)putSPIchar(*ptr++);

}



void spi_init(void)

{

unsigned char temp;

DDRB |= 0x07;                 //MISO=input and MOSI,SCK,SS = output

PORTB |= 0x08;              //MISO上拉电阻有效,ss拉低输出   

SPCR = 0xD5;                      //SPI允许,主机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率

SPSR = 0x00;

temp = SPSR;

temp = SPDR;                      //清空SPI,和中断标志,使SPI空闲

}



void main(void)

{

unsigned char i=0,j;

LCD_init();

CLI();                          //关中断

spi_init();                      //初始化SPI接口

SEI();                        //开中断

   putSPIstring("0123456789");

while(1)

{

            //发送一个字节

    //i++;

        //LCD_write_char(0,0,i);

   // getSPIchar();         //接收一个字节(第一个字节为空字节?

   i=j;

   j=getSPIchar();

   if(i!=j)

   LCD_write_data(j);

}

}





从机部分:

#include <iom64v.h>

#include <macros.h>

#include "1602.h"

#include "delay.h"

#define SIZE 100

unsigned char SPI_rx_buff;         //收信箱

unsigned char SPI_tx_buff;               //发信箱

unsigned char rx_wr_index;                               //收信箱写指针

unsigned char rx_rd_index;                               //收信箱读指针

unsigned char rx_counter;                               //收信箱存量

unsigned char rx_buffer_overflow;               //收信箱满标志

unsigned char tx_wr_index;                               //发信箱写指针

unsigned char tx_rd_index;                               //发信箱读指针

unsigned char tx_counter;                               //发信箱存量

unsigned char SPI_ok=1;

#pragma interrupt_handler spi_stc_isr:18   

void spi_stc_isr(void)

{   

SPI_rx_buff = SPDR;                             //从ISP口读出收到的字节

SPI_ok = 1; // SPI 空闲   

if (++rx_wr_index == SIZE) rx_wr_index = 0;    //如果收信箱满则指针归零

if (++rx_counter == SIZE)

{

    rx_counter = 0;                                                            //收信箱清空

    rx_buffer_overflow = 1;                                       //置满标志位

}

if (tx_counter)                                                     //如果发送缓冲区中有待发的数据

{

   --tx_counter;                                                                //发送一个字节数据,存量减1

   SPDR = SPI_tx_buff;   

   if (++tx_rd_index == SIZE) tx_rd_index = 0; //收信箱读完后读指针归零

       SPI_ok = 0;

}

}   



unsigned char getSPIchar(void)

{

unsigned char data;



while (rx_counter == 0);                                               //收信箱空则等待



data = SPI_rx_buff;                             //从接收缓冲区取出一个SPI收到的数据

if (++rx_rd_index == SIZE) rx_rd_index = 0;   //调整指针

CLI();

--rx_counter;

SEI();

return data;

}





//从机不能主动发数据,所以所有数据放发信箱里等待主机发信息来后回复过去

void putSPIchar(char c)



{

   while (tx_counter == SIZE);                                             //发信箱满,等待

CLI();                  

    SPI_tx_buff = c;                             //将数据放入发信箱排队

    if (++tx_wr_index == SIZE) tx_wr_index = 0;   //调整指针

    ++tx_counter;   

SEI();   

}



void putSPIstring(unsigned char *ptr)

{

while(*ptr)putSPIchar(*ptr++);

}



void spi_init(void)

{

unsigned char temp;

DDRB |= 0x08;                 //MISO=output and MOSI,SCK,SS = input

PORTB|= 0x07;              //MOSI,SCK,SS上拉电阻有效   

SPCR = 0xC5;                      //SPI允许,从机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率

SPSR = 0x00;

temp = SPSR;

temp = SPDR;                      //清空SPI,和中断标志,使SPI空闲

}



void main(void)

{

unsigned char i=0;

LCD_init();

CLI();                          //关中断

spi_init();                      //初始化SPI接口

SEI();                        //开中断



while(1)

{



   i=getSPIchar();         //接收一个字节(第一个字节为空字节)

   LCD_write_data(i);

   putSPIchar(i);      //发送一个字节

   

}

}





完整程序:



点击此处下载armok01167278.rar

NE5532 发表于 2008-2-24 18:34:29

把端口用电阻上拉到“1”(输出断开),看输入是不是FF,如果不是,检查程序;如果是,查硬件
页: [1]
查看完整版本: 参照着马老师的spi例子写的,但是有些问题,请老师看看