有关STC12单片机SPI通讯问题

2019-07-16 02:54发布

SPI通讯是发送和接收同时进行的吗?datasheet上说SPI可看成是一个8位的移位寄存器,主机发送一个字节数据的同时也接收到来自从机的一字节数据,可是怎么判断接收的哪个数据是自己需要的呢?求指导啊。
我这有主机和从机的两段程序,求各位大侠帮忙分析下,程序很简单,就是主机接收到串口发送的数据后,通过SPI传送给从机,然后接收从机传回的固定数据0XAA,发送到串口显示。
问题是,假如串口向主机发送0x06,从机显示接收也正确,可是发送回主机显示的数据不对呀。比如串口发送5次0x06,最后主机返回串口显示的是:0xff,0x00,0xab,0xaa,0xab....后面接收到的0xaa或0xab不确定,求教
主机程序:
#include <stc12c5a60s2.h>
#define SPIF  ( SPSTAT & 0x80 )  //查询SPIF是否置位,SPIF不能进行位操作
//通信端口设置
sbit SCLK = P1^7;
sbit MISO = P1^6;
sbit MOSI = P1^5;
sbit SS   = P1^4;
sbit LED   = P1^0;
unsigned char UART_SendData=0;
unsigned char UART_RecData=0;
unsigned char SPI_RecData=0;
void Init_System();
void Init_UART();
void Init_SPI();
unsigned char SPI_SendByte(unsigned char SPI_SendData);
void UART_SendByte(unsigned char UART_Send);

void main()
{
   Init_System();
   while(1)           
     {
/*  查询UART接收信号 ----------------------------------*/
        while(RI==1)     //查看串口是否接收到数据
          {
             RI=0;               //当接收到数据后,清除接收中断标志
             UART_RecData=SBUF;   //读入数据
             UART_SendData=SPI_SendByte(UART_RecData);//将收到的数据由SPI发送出去,又接收回来
             UART_SendByte(UART_SendData);
           }
       }
}
/*---------------------------------------------------------
*函数名:Init_System
*函数功能:系统初始化
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_System()
{
   Init_UART();
   Init_SPI();
}
/*---------------------------------------------------------
*函数名:Init_UART
*函数功能:串口初始化,无中断方式
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_UART()
{
    TMOD=0x20;//设置定时器1为工作方式2
    TH1=0xfc; //波特率为9600,晶振为22.1184MHz
    TL1=0xfc;
    TR1=1;   //启动T1
    REN=1;   //串行允许位
//  PCON=0x80;  //PCON寄存器的SMOD位置一,波特率提高一倍
    SM0=0;
    SM1=1;   //串行方式1
}
/*---------------------------------------------------------
*函数名:Init_SPI
*函数功能:SPI初始化,SPI的工作方式,不使用SPI中断方式
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_SPI()
{
   SPCTL = 0xDd;//CPU_CLK/16,时钟前沿为下降沿,后沿采样,主模式,最低位在前,SPI使能
   SPSTAT = 0xc0;//SPDAT.7和SPDAT.6写11,可以将中断标志清零。注意是写1才清零
   SPDAT = 0;
}
/*---------------------------------------------------------
*函数名:SPI_SendByte
*函数功能:SPI发射接收一体程序
*输入参数:SPI_SendData,经主机发给从机的数据
*返回参数:从机发给主机的数据
----------------------------------------------------------*/
unsigned char SPI_SendByte(unsigned char SPI_SendData)
{
    SPDAT= SPI_SendData; //将串口接收的数据装入SPI数据寄存器
    while(!SPIF);//等待发送完毕
    SPSTAT = 0xc0; //清除中断标志,和写冲突标志,注意是对应位写1才能清零
return SPDAT;
}

/*---------------------------------------------------------
*函数名:UART_SendByte
*函数功能:串口发送
*输入参数:UART_Send
*返回参数:无
----------------------------------------------------------*/
void UART_SendByte(unsigned char UART_Send)
{
    ti = 0;            //清除发送SBUF空标志
    SBUF =  UART_Send; //写入SBUF
    while (!TI);       //等待发送完毕
    TI = 0;            //清除发送SBUF空标志
}

从机程序:
#include <stc12c5a60s2.h>
#define SPIF  ( SPSTAT & 0x80 )  //查询SPIF是否置位,SPIF不能进行位操作
/*通信端口设置-------------------------------------------------------*/
sbit SCLK = P1^7;
sbit MISO = P1^6;
sbit MOSI = P1^5;
sbit SS   = P1^4;
sbit LED   = P1^1;
unsigned char SPI_Buffer=0;
void Init_SPI();

void main()
{
   Sysinit();
   Init_SPI();
   while(1);
}
/*---------------------------------------------------------
*函数名:Init_SPI
*函数功能:SPI初始化,SPI的工作方式,开中断
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_SPI()
{
   SPCTL = 0xcd;//CPU_CLK/16,时钟前沿为下降沿,后沿采样,从模式,最低位在前,SPI使能
   SPSTAT = 0xc0;//SPDAT.7和SPDAT.6写11,可以将中断标志清零。注意是写1才清零
   SPDAT = 0;
   IE2 |= 0x02; //允许SPI中断
   EA =1;        //开总中断
}
/*---------------------------------------------------------
*函数名:SPI_Rec
*函数功能:SPI接收处理中断函数,将接收到的数发送出去
*输入参数:
*返回参数:
----------------------------------------------------------*/
void SPI_Rec() interrupt 9   //当SPIF = 1时,且EADC=1,AUXR  = 0x08,EA=1时将进入此中断
{
   SPSTAT = 0xc0;      //清除中断标志,和写冲突标志,注意是对应位写1才能清零
   SPI_Buffer = SPDAT;   
   SPDAT= 0xaa;        //从机收到SPI数据后,发送固定数据0xaa
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。