搜索
bottom↓
回复: 1

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

[复制链接]

出0入0汤圆

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

主机部分:

#include <iom64v.h>

#include <macros.h>

#include "1602.h"

#include "delay.h"

#define SIZE 100  

unsigned char SPI_rx_buff[SIZE];         //收信箱

unsigned char SPI_tx_buff[SIZE];                 //发信箱

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[rx_wr_index] = 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[tx_rd_index];   

     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[rx_rd_index];                             //从接收缓冲区取出一个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[tx_wr_index] = 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[SIZE];         //收信箱

unsigned char SPI_tx_buff[SIZE];                 //发信箱

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[rx_wr_index] = 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[tx_rd_index];   

     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[rx_rd_index];                             //从接收缓冲区取出一个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[tx_wr_index] = 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

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2008-2-24 18:34:29 | 显示全部楼层
把端口用电阻上拉到“1”(输出断开),看输入是不是FF,如果不是,检查程序;如果是,查硬件
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 22:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表