找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2392|回复: 9
打印 上一主题 下一主题
收起左侧

用两个C51单片机模拟SPI全双工通信,请教各位大神,指导,这错在哪里

[复制链接]
跳转到指定楼层
楼主
ID:166571 发表于 2021-7-19 21:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用两个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;
          }

  }


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:166571 发表于 2021-7-19 21:59 | 只看该作者
菜鸟求大神指教,
回复

使用道具 举报

板凳
ID:123289 发表于 2021-7-20 09:25 | 只看该作者
先说说错误的现象长什么样子?
回复

使用道具 举报

地板
ID:592807 发表于 2021-7-20 09:37 | 只看该作者
看着太麻烦了,理解也费劲。还是解释一下吧


1  所谓的双全工值得是通讯双向,接收数据的同时必须发等量数据,就像我给你一桶水你给我一桶水,如果我没收到一桶水就表示我给你的一桶水中途洒了,我要重新给你一份水,直到我收到你的水,这样我才能确保你一定收到水。但是你的发送没同步接收,不能确保从机一定受到数据。
2主机已经结束从机还没开始。
         W_data= SPI_Write_Byte(0xAA );//
         R_data= SPI_Read_Byte();

你的通讯应该是这样的

主机片选  ----  主机发送“0XAA”-----主机片选关闭 ----主机片选 -----主机开始接受---主机接受完毕---主机关闭片选
从机被片选----从机接受数据“0XAA”----从机处理数据----从机被片选-------从机发送数据
你这个主机接受数据和从机发送数据的时间没法保证统一,就像接力赛,时间一到就开始跑,不管接力棒是否已经到你手里了,也不管你接到是不是自家队友的接力棒。


回复

使用道具 举报

5#
ID:166571 发表于 2021-7-20 14:46 | 只看该作者
黄youhui 发表于 2021-7-20 09:37
看着太麻烦了,理解也费劲。还是解释一下吧

那怎样保证啊,我也是参考别家的,
回复

使用道具 举报

6#
ID:166571 发表于 2021-7-20 14:48 | 只看该作者
yzwzfyz 发表于 2021-7-20 09:25
先说说错误的现象长什么样子?

从机与主机不能通信
回复

使用道具 举报

7#
ID:592807 发表于 2021-7-20 15:25 | 只看该作者
qiuluqiang 发表于 2021-7-20 14:46
那怎样保证啊,我也是参考别家的,

你主机发送完后就while(1)等。
从机要发送数据前片选CS=0
主机加收到CS=0信号,就开始接受
回复

使用道具 举报

8#
ID:166571 发表于 2021-7-21 19:24 | 只看该作者
你要这方面的代码吗,能提供参考下吗
回复

使用道具 举报

9#
ID:166571 发表于 2021-7-21 19:39 | 只看该作者
接收与发送是时钟控制的啊,
回复

使用道具 举报

10#
ID:166571 发表于 2021-7-21 19:40 | 只看该作者
你有这方面的代码吗,就是用两个单片机模拟SPI的互相通信的,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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