找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于C51使用SPI协议进行双机通行的问题

  [复制链接]
跳转到指定楼层
楼主
目标:两块完全相同的C51单片机使用SPI协议进行通信。电脑A通过串口助手发送字符至单片机A的SBUF,然后单片机A通过SPI协议发送至单片机B的SBUF,并显示在电脑B的串口助手上。问题:SPI协议无法实现。
代码如下:
  1. # include <reg52.h>//头文件
  2. # include <intrins.h>//头文件

  3. # define uchar unsigned char
  4. # define uint unsigned int

  5. sbit SCK = P1^0;//位定义时钟
  6. sbit CS = P1^1;//位定义片选(使能)
  7. sbit SDI = P1^2;//位定义Input
  8. sbit SDO = P1^3;//位定义Output
  9. sbit WE = P2^7;//数码管位选位定义
  10. sbit DU = P2^6;//数码管段选位定义

  11. uchar num;//数码管显示的值
  12. uchar dat, dat0, dat1, b, flag;

  13. /*-----函数声明-----*/
  14. void delay5us(void);
  15. void SpiInit();
  16. void SpiSend(uchar dat1);
  17. uchar SpiReceive();
  18. void UARTInit();
  19. void judge();
  20. void receive1();

  21. /*-----主函数-----*/
  22. void main()
  23. {
  24.         timer0Init();
  25.         UARTInit();
  26.         while (1)
  27.         {
  28.                 judge();//执行判断
  29.         }        
  30. }

  31. /*-----5微秒延时函数-----*/
  32. void delay5us(void)
  33. {
  34.         _nop_();        
  35. }

  36. /*-----SPI初始化函数-----*/
  37. void SpiInit()
  38. {
  39.         SCK = 0;
  40.         delay5us();
  41. }

  42. /*-----SPI发送函数-----*/
  43. /*-----下降沿发送-----*/
  44. void SpiSend(uchar dat1)
  45. {
  46.         uchar i;
  47.         SCK = 0;//时序置低
  48.         delay5us();
  49.         for (i=8; i>0; i--)//8bit,一位一位写
  50.         {
  51.                 if (dat1 & 0x80)//判断当前最高位为1还是0
  52.                 {
  53.                         SDO = 1;               
  54.                 }
  55.                 else
  56.                 {
  57.                         SDO = 0;
  58.                 }
  59.                 SCK = 1;
  60.                 delay5us();
  61.                 SCK = 0;//产生时序下降沿,发送数据
  62.                 delay5us();
  63.                 dat1 <<= 1;
  64.         }
  65. }

  66. /*-----SPI接收函数-----*/
  67. /*-----上升沿接收-----*/
  68. uchar SpiReceive()
  69. {
  70.         uchar i;
  71.         dat = 0x00;
  72.         SCK = 0;//时序置低
  73.         delay5us();
  74.         for (i=8; i>0; i--)//8bit,一位一位写
  75.         {
  76.                 SCK = 0;
  77.                 delay5us();
  78.                 SCK = 1;//产生时序上升沿,接收数据
  79.                 delay5us();
  80.                 dat0 <<= 1;
  81.                 dat0 |= (uchar)(SDI);
  82.                 delay5us();
  83.         }

  84.         return dat0;//收到数据(返回值)dat0
  85. }

  86. /*-----串口(中断)初始化-----*/
  87. void UARTInit()
  88. {
  89.         EA = 1;//开启总中断
  90.         ES = 1;//打开串口中断
  91.         SM0 = 0;SM1 = 1;//串口工作方式1,8位UART波特率可变
  92.         REN = 1;//串口允许接收
  93.         TR1 = 1;//启动定时器1
  94.         TMOD |= 0X20;//定时器1,工作模式2 8位自动重装
  95.         TH1 =0XFD;
  96.         TL1 =0XFD;//设置波特率9600
  97. }

  98. /*-----串口中断服务函数-----*/
  99. void UART() interrupt 4
  100. {
  101.         if (RI)//判断是否接收完成
  102.         {
  103.                 dat = SBUF;//读SUBF
  104.                 flag = 1;//表明谁是主机
  105.                 RI = 0;//软件清零
  106.         }
  107.         if (TI)//判断是否发送完成
  108.         {
  109.                 TI = 0;//软件清零

  110.         }
  111.         else
  112.         {
  113.                 flag = 2;//?
  114.         }               
  115. }

  116. void receive1()        //乙机发送数据给上位机
  117. {
  118.         
  119.         b=SBUF;
  120.         ES=0;
  121.         SBUF=b;
  122.         while(!TI);
  123.         TI=0;
  124.         ES=1;
  125. }

  126. void judge()
  127. {
  128.         SpiInit();
  129.         if(flag == 1)                //如果flag=1,那么就意味着是甲方单片机,获得的是一手数据
  130.         {                //执行的是发送数据给上位机--电脑以及发送数据给乙方单片机
  131.                 SpiSend(dat);
  132.                 flag = 0;        
  133.         }
  134.         if (flag == 2)                        //如果flag=2那么就意味着是乙方单片机,获得的是二手数据
  135.         {
  136.                 SpiReceive();
  137.                 receive1();     //执行的是接受数据,并且发送数据给上位机
  138.                 flag = 0;
  139.         }
  140. }
复制代码
使用的SPI协议为:CPOA=0;CPHA=0
如图




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

使用道具 举报

沙发
ID:158375 发表于 2019-3-6 08:20 | 只看该作者
肯定是你的程序有不合适的地方,分部分来调试吧。
有点不明白:单片机A通过SPI协议,发送至单片机B的SBUF,这个是怎么回事。
回复

使用道具 举报

板凳
ID:94031 发表于 2019-3-6 09:05 | 只看该作者
你这实验环节很多,任何一个环节出错就会实验失败,所以得一各一个环节搞,先看电脑A通过串口助手发送字符至单片机A的SBUF正常吗,再看单片机A通过SPI协议发送至单片机B的SBUF正常吗,最后才是显示在电脑B的串口助手上正常吗,不是光看程序能解决的。
回复

使用道具 举报

地板
ID:94031 发表于 2019-3-6 09:20 | 只看该作者
笨笨兔 发表于 2019-3-6 08:20
肯定是你的程序有不合适的地方,分部分来调试吧。
有点不明白:单片机A通过SPI协议,发送至单片机B的SBUF ...

他的意思,单片机A通过SPI协议,发送至单片机B的SPI接收,然后转到本单片机B串口SBUF,向电脑B的串口助手发送。估计是学习SPI的实验项目。
回复

使用道具 举报

5#
ID:476313 发表于 2019-3-6 10:47 | 只看该作者
xuyaqi 发表于 2019-3-6 09:05
你这实验环节很多,任何一个环节出错就会实验失败,所以得一各一个环节搞,先看电脑A通过串口助手发送字符 ...

电脑A通过串口助手发送字符至单片机A的SBUF正常
单片机A通过SPI协议发送至单片机B的SBUF失败
问题应该处在SPI的配置上面,但是网上也没有合适的解决方案
回复

使用道具 举报

6#
ID:476313 发表于 2019-3-6 10:49 | 只看该作者
xuyaqi 发表于 2019-3-6 09:20
他的意思,单片机A通过SPI协议,发送至单片机B的SPI接收,然后转到本单片机B串口SBUF,向电脑B的串口助手 ...

恩恩,是这样的。
确实是学习SPI的项目
回复

使用道具 举报

7#
ID:476313 发表于 2019-3-6 10:53 | 只看该作者
问题出在SPI上,问问大家根据下面的时序图,SPI配置代码有问题吗?
回复

使用道具 举报

8#
ID:94031 发表于 2019-3-6 13:25 | 只看该作者
Benjia 发表于 2019-3-6 10:49
恩恩,是这样的。
确实是学习SPI的项目

用逻辑分析仪抓一下SPI时序看一下。
回复

使用道具 举报

9#
ID:466164 发表于 2019-3-6 23:43 | 只看该作者
这个比较复杂:
1.从硬件讲传输距离是不是太远,
2.你B单片机接收程序是否正常,
3.B单片机是否能给电脑B发送,
4.你就一个程序,无法判断,应该两个系统程序,单片机A程序,单片机B程序。
回复

使用道具 举报

10#
ID:485724 发表于 2019-3-7 01:10 | 只看该作者
应该是主从机的协议没有设置好
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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