用两个C51单片机模拟SPI全双工通信,
//SPI主机代码
void SPI_PRO_INIT()
{
SET_SFR_PAGE1;
_SPI_NSS_OUTPUT;
_SPI_NSS_PULLUPON;//上拉,关片选,
_SPI_SCK_OUTPUT;
_SPI_SCK_PULLDOWNON;//下拉 ,关时钟
_SPI_MOSI_OUTPUT;
_SPI_MOSI_PULLDOWNON;//下拉 ,关数据输出
_SPI_MISO_INPUT;
_SPI_MISO_PULLDOWNON;//下拉开启,拉低输入
R_data=0;
W_data=0;
SET_SFR_PAGE0;
}
uint8 SPI_Read_Byte()
{
uint8 i;
uint8 SPI1_dat=0;
_SPI_NSS_ON;//片选
for(i=0;i<8;i++)
{
_SPI_SCK_OFF;
Delay_3us();
SPI1_dat<<=1;//SPI1_dat=(SPI1_dat<<1),第一个上升沿读取数据
if(_SPI_MISO )//从机发来的信号,如果是高电平
{
SPI1_dat|=0x01;//0000 0001,左移后,补1;与(SPI_dat&0x80)//1000 0000相互呼应
}
// else
//{
//SPI1_dat&=0xfe;//1111 1110,左移后,补0;
//}
_SPI_SCK_ON;
Delay_3us();
}
// _SPI_SCK_OFF;
_SPI_NSS_OFF; //关片选
return SPI1_dat;
}
uint8 SPI_Write_Byte(uint8 SPI_dat)
{
uint8 i;
_SPI_NSS_ON;//片选
for(i=0;i<8;i++)
{
_SPI_SCK_OFF;
Delay_3us();
if(SPI_dat&0x80)//1000 0000,要发送的数据的第8位是1
{
_SPI_MOSI_ON;
}
else
{
_SPI_MOSI_OFF;
}
SPI_dat=(SPI_dat<<1);//左移,移动数据传送
_SPI_SCK_ON;
Delay_3us();
}
// _SPI_SCK_OFF;
_SPI_NSS_OFF; //关片选
}
void SPI_PRO()
{
W_data = SPI_Write_Byte(0x55 );//
R_data = SPI_Read_Byte();
if(R_data==0xAA)
{
_LED1_OFF;
}
}
//从机代码
void SPI_PRO_INIT()
{
SET_SFR_PAGE1;
_SPI_NSS_INPUT;
_SPI_NSS_PULLUPON;
_SPI_SCK_INPUT;
_SPI_SCK_PULLDOWNON;
_SPI_MOSI_INPUT;
_SPI_MOSI_PULLDOWNON;
_SPI_MISO_OUTPUT;
_SPI_MISO_PULLDOWNON;
SET_SFR_PAGE0;
W_data=0;
R_data=0;
}
/******************************************************************************
* Function : Slave_SPI_Read_Byte
* Description: 从SPI读出一个8位字节
* Input : SPI1_dat:要发送的数据
*******************************************************************************/
uint8 SPI_Read_Byte()
{
uint8 i;
uint8 SPI1_dat=0;
uint8 SPI1_flag=0;
if(!(_SPI_NSS ))//片选后,执行if(!(_SPI_NSS ))里面的函数
{
for(i=0;i<8;i++)
{
SPI1_flag=1;
while(!( _SPI_SCK ));//等待时钟拉低,开始读数据
SPI1_dat<<=1;//SPI1_dat=(SPI1_dat<<1)开始
if(_SPI_MOSI )
{
SPI1_dat|=0x01;//读取后,第一位补1;//与SPI_dat&0x80相呼应
}
while(_SPI_SCK );//等待读取结束
}
while(!(_SPI_NSS ));//等待关片选
}
if(SPI1_flag==1)
{
return SPI1_dat;
}
else
{
return 0;
}
}
/******************************************************************************
* Function : Slave_SPI_Write
* Description: 向SPI写入一个8位字节
* Input : SPI_dat:要发送的数据
*******************************************************************************/
uint8 SPI_Write_Byte(uint8 SPI_dat)
{
uint8 i;
if(!(_SPI_NSS ))//片选后,执行if(!(_SPI_NSS ))里面的函数
{
for(i=0;i<8;i++)
{
while(_SPI_SCK);//_SPI_SCK低时,执行后面的函数
if(SPI_dat&0x80)//1000 0000 是高电平,有数据
{
_SPI_MISO_ON;
}
else
{
_SPI_MISO_OFF;
}
while(!(_SPI_SCK));//等待读取完成
SPI_dat<<=1;//向SPI写数据
}
while(!(_SPI_NSS ));//等待关片选
}
}
void SPI_PRO()
{
W_data= SPI_Write_Byte(0xAA );//
R_data= SPI_Read_Byte();
if(R_data==0x55)
{
_LED2_OFF;
}
}
|