找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13376|回复: 20
收起左侧

51单片机模拟SPI总线通信程序及proteus仿真

  [复制链接]
ID:203208 发表于 2017-11-18 17:44 | 显示全部楼层 |阅读模式
分享一个51单片机模拟SPI总线来进行通信的程序及仿真
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png 0.png
单片机源程序如下:
  1. #include<reg51.h>    //包含单片机寄存器的头文件
  2. #include<intrins.h>  //包含_nop_()函数定义的头文件
  3. //x5045引脚定义
  4. sbit SCK=P3^4;       //将SCK位定义为P3.4引脚
  5. sbit SI=P3^5;        //将SI位定义为P3.5引脚
  6. sbit SO=P3^6;        //将SO位定义为P3.6引脚
  7. sbit CS=P3^7;        //将SCK位定义为P3.7引脚
  8. //功能变量定义
  9. #define WREN 0x06    //写使能锁存器允许
  10. #define WRDI 0x04    //写使能锁存器禁止
  11. #define WRSR 0x01    //写状态寄存器
  12. #define READ 0x03    //读出
  13. #define WRITE 0x02   //写入
  14. /*****************************************************
  15. 函数功能:延时1ms
  16. (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
  17. ***************************************************/
  18. void delay1ms()
  19. {
  20.    unsigned char i,j;
  21.   for(i=0;i<10;i++)
  22.    for(j=0;j<33;j++)
  23.     ;   
  24. }
  25. /*****************************************************
  26. 函数功能:延时若干毫秒
  27. 入口参数:n
  28. ***************************************************/
  29. void delaynms(unsigned char n)
  30. {
  31.    unsigned char i;
  32. for(i=0;i<n;i++)
  33.     delay1ms();
  34. }
  35. /*****************************************************
  36. 函数功能:从X5045的当前地址读出数据
  37. 出口参数:x
  38. ***************************************************/
  39. unsigned char ReadCurrent(void)
  40. {
  41.    unsigned char i;
  42. unsigned char x=0x00;      //储存从X5045中读出的数据
  43. SCK=1;                     //将SCK置于已知的高电平状态
  44.    for(i = 0; i < 8; i++)
  45. {
  46.     SCK=1;                 //拉高SCK
  47.     SCK=0;                 //在SCK的下降沿输出数据
  48.     x<<=1;  //将x中的各二进位向左移一位,因为首先读出的是字节的最高位数据   
  49.   x|=(unsigned char)SO;  //将SO上的数据通过按位“或“运算存入 x      
  50. }
  51. return(x);   //将读取的数据返回
  52. }
  53. /*****************************************************
  54. 函数功能:写数据到X5045的当前地址
  55. 入口参数:dat
  56. ***************************************************/
  57. void WriteCurrent(unsigned char dat)
  58. {
  59.    unsigned char i;
  60. SCK=0;                 //将SCK置于已知的低电平状态
  61.   for(i = 0; i < 8; i++)  // 循环移入8个位
  62. {
  63.   SI=(bit)(dat&0x80);   //通过按位“与”运算将最高位数据送到S
  64.                       //因为传送时高位在前,低位在后
  65.   SCK=0;
  66.   SCK=1;               //在SCK上升沿写入数据
  67.     dat<<=1;   //将y中的各二进位向左移一位,因为首先写入的是字节的最高位
  68.   }
  69. }
  70. /*****************************************************
  71. 函数功能:写状态寄存器 ,可以设置看门狗的溢出时间及数据保护
  72. 入口参数:rs;  //储存寄存器状态值
  73. ***************************************************/
  74. void WriteSR(unsigned char rs)
  75. {
  76.   CS=0;                 //拉低CS,选中X5045
  77.   WriteCurrent(WREN);   //写使能锁存器允许
  78.   CS=1;                 //拉高CS
  79.   CS=0;                 //重新拉低CS,否则下面的写寄存器状态指令将被丢弃
  80.   WriteCurrent(WRSR);   //写状态寄存器
  81.   WriteCurrent(rs);     //写入新设定的寄存器状态值
  82.   CS=1;                 //拉高CS
  83. }
  84. /*****************************************************
  85. 函数功能:写数据到X5045的指定地址
  86. 入口参数:addr
  87. ***************************************************/
  88. void WriteSet(unsigned char dat,unsigned char addr)
  89. {
  90.    SCK=0;                 //将SCK置于已知状态
  91.    CS=0;                  //拉低CS,选中X5045
  92. WriteCurrent(WREN);    //写使能锁存器允许
  93. CS=1;                  //拉高CS
  94.    CS=0;                  //重新拉低CS,否则下面的写入指令将被丢弃
  95. WriteCurrent(WRITE);   //写入指令
  96. WriteCurrent(addr);    //写入指定地址
  97. WriteCurrent(dat);     //写入数据
  98. CS=1;                  //拉高CS
  99.    SCK=0;                 //将SCK置于已知状态
  100. }
  101. /*****************************************************
  102. 函数功能:从X5045的指定地址读出数据
  103. 入口参数:addr
  104. 出口参数:dat
  105. ***************************************************/
  106. unsigned char ReadSet(unsigned char addr)
  107. {
  108. unsigned char dat;
  109. SCK=0;                 //将SCK置于已知状态
  110. CS=0;                  //拉低CS,选中X5045
  111. WriteCurrent(READ);   //开始读
  112. WriteCurrent(addr);   //写入指定地址
  113. dat=ReadCurrent();    //读出数据
  114. CS=1;                 //拉高CS
  115. SCK=0;                //将SCK置于已知状态
  116. return dat;           //返回读出的数据
  117. }
  118. /*****************************************************
  119. 函数功能:看门狗复位程序
  120. ***************************************************/
  121. void WatchDog(void)
  122. {
  123. CS=1;    //拉高CS
  124. CS=0;    //CS引脚的一个下降沿复位看门狗定时器
  125. ……………………

  126. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
SPI.zip (38.13 KB, 下载次数: 440)

评分

参与人数 2黑币 +55 收起 理由
关外秀才 + 5 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:282995 发表于 2018-2-8 09:17 | 显示全部楼层
百度只看到这个有源码
回复

使用道具 举报

ID:303104 发表于 2018-4-7 13:22 | 显示全部楼层
真好 很棒
回复

使用道具 举报

ID:320352 发表于 2018-5-2 11:58 | 显示全部楼层
不错的东西,下来看看
回复

使用道具 举报

ID:335202 发表于 2018-5-21 20:26 | 显示全部楼层
好 真棒
回复

使用道具 举报

ID:279728 发表于 2018-7-19 13:14 | 显示全部楼层
强强,小白受教了
回复

使用道具 举报

ID:379819 发表于 2018-7-27 13:25 | 显示全部楼层
感谢大佬   
回复

使用道具 举报

ID:379819 发表于 2018-7-27 13:44 | 显示全部楼层
他就是可以实现普通IO口模拟SPI的功能 对吧

回复

使用道具 举报

ID:275111 发表于 2018-9-13 10:14 | 显示全部楼层
Proteus里这个芯片没有 看门狗 模块。可以搞其他部分。
回复

使用道具 举报

ID:20672 发表于 2018-9-29 14:50 | 显示全部楼层
谢谢!!!
回复

使用道具 举报

ID:465392 发表于 2019-1-9 20:31 | 显示全部楼层
感谢大佬分享
回复

使用道具 举报

ID:501077 发表于 2019-3-30 11:19 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:519963 发表于 2019-4-23 21:15 | 显示全部楼层
小白来学习,回复可以拿币吗?
回复

使用道具 举报

ID:520635 发表于 2019-4-25 10:31 | 显示全部楼层
学习一下
回复

使用道具 举报

ID:32962 发表于 2019-5-26 16:38 | 显示全部楼层
正需要这个来参考一下,谢谢楼主.
回复

使用道具 举报

ID:384820 发表于 2019-8-6 23:26 | 显示全部楼层
下来学习学习,感谢分享。
回复

使用道具 举报

ID:602723 发表于 2019-9-10 17:49 | 显示全部楼层
为什么时钟是(3j+2)*i=(3×33+2)×10=1010(微秒)
回复

使用道具 举报

ID:611955 发表于 2019-11-15 07:08 | 显示全部楼层
很好,学习了
回复

使用道具 举报

ID:171060 发表于 2020-3-14 00:24 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:774480 发表于 2020-6-12 20:41 | 显示全部楼层
这个可以运行吗
回复

使用道具 举报

ID:480951 发表于 2020-6-15 09:42 | 显示全部楼层
很棒,非常感谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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