单片机IO口模拟SPI四种模式的程序

[复制链接]
2074|16
 楼主| 王大熊 发表于 2015-5-27 09:05 | 显示全部楼层 |阅读模式
 楼主| 王大熊 发表于 2015-5-27 09:06 | 显示全部楼层
 楼主| 王大熊 发表于 2015-5-27 09:06 | 显示全部楼层
本帖最后由 王大熊 于 2015-5-27 09:09 编辑
  1. #include "iom8535v.h"
  2. #define _CPOL     1
  3. #define _CPHA     0
  4. #define SCK_IO    DDRA|=0X01
  5. #define MOSI_IO   DDRA|=0X02
  6. #define MISO_IO   DDRA&=0XFB
  7. #define SSEL_IO   DDRA|=0X08
  8. #define SCK_D(X)   (X?(PORTA|=0X01):(PORTA&=0XFE))
  9. #define MOSI_D(X)  (X?(PORTA|=0X02):(PORTA&=0XFD))
  10. #define SSEL_D(X)  (X?(PORTA|=0X08):(PORTA&=0XF7))

  11. #define MISO_I()  (PINA&0X04)  
  12. void delay()
  13. {
  14. unsigned char m,n;
  15.      for(n=0;n<5;n++);
  16.     for(m=0;m<100;m++);
  17. }
  18. /************************************************
  19.         端口方向配置  与输出初始化
  20. ************************************************/
  21. void SPI_Init(void)
  22. {
  23. SCK_IO   ;
  24. MOSI_IO  ;
  25. MISO_IO  ;
  26. SSEL_IO  ;
  27. SSEL_D(1);
  28. MOSI_D(1);
  29. #if _CPOL==0
  30. SCK_D(0);
  31. #else
  32. SCK_D(1);
  33. #endif
  34. }

  35. /**********************************************
  36. 模式零           写数据
  37. ***********************************************/
  38. #if _CPOL==0&&_CPHA==0          //MODE   0  0   
  39. void SPI_Send_Dat(unsigned char dat)
  40. {
  41. unsigned char n;
  42. for(n=0;n<8;n++)
  43. {
  44.   SCK_D(0);
  45.   if(dat&0x80)MOSI_D(1);
  46.   else MOSI_D(0);
  47.   dat<<=1;
  48.   SCK_D(1);
  49. }
  50.   SCK_D(0);
  51. }
  52. /*********************************************
  53. 模式零         读数据
  54. *********************************************/
  55. unsigned char SPI_Receiver_Dat(void)
  56. {
  57. unsigned char n ,dat,bit_t;
  58. for(n=0;n<8;n++)
  59. {
  60.   SCK_D(0);
  61.   dat<<=1;
  62.   if(MISO_I())dat|=0x01;
  63.   else dat&=0xfe;
  64.   SCK_D(1);
  65. }
  66.   SCK_D(0);
  67.   return dat;
  68. }
  69. #endif
  70. /**********************************************
  71. 模式二           写数据
  72. ***********************************************/
  73. #if _CPOL==1&&_CPHA==0           //MODE   1  0
  74. void SPI_Send_Dat(unsigned char dat)
  75. {
  76. unsigned char n;
  77. for(n=0;n<8;n++)
  78. {
  79.   SCK_D(1);
  80.   if(dat&0x80)MOSI_D(1);
  81.   else MOSI_D(0);
  82.   dat<<=1;
  83.   SCK_D(0);
  84. }
  85.   SCK_D(1);
  86. }
  87. /*********************************************
  88. 模式二          读数据
  89. *********************************************/
  90. unsigned char SPI_Receiver_Dat(void)
  91. {
  92. unsigned char n ,dat,bit_t;
  93. for(n=0;n<8;n++)
  94. {
  95.   SCK_D(1);
  96.   dat<<=1;
  97.   if(MISO_I())dat|=0x01;
  98.   else dat&=0xfe;
  99.   SCK_D(0);
  100. }
  101.   SCK_D(1);
  102.   return dat;
  103. }

  104. #endif
  105. /*********************************************
  106. 模式一        写数据
  107. *********************************************/
  108. #if _CPOL==0&&_CPHA==1           //MODE  0  1
  109. void SPI_Send_Dat(unsigned char dat)
  110. {
  111. unsigned char n;
  112. SCK_D(0);
  113. for(n=0;n<8;n++)
  114. {
  115.   SCK_D(1);
  116.   if(dat&0x80)MOSI_D(1);
  117.   else MOSI_D(0);
  118.   dat<<=1;
  119.   SCK_D(0);
  120. }
  121. }
  122. /*********************************************
  123. 模式一       读数据
  124. *********************************************/
  125. unsigned char SPI_Receiver_Dat(void)
  126. {
  127. unsigned char n ,dat,bit_t;
  128. for(n=0;n<8;n++)
  129. {
  130.   SCK_D(1);
  131.    dat<<=1;
  132.   if(MISO_I())dat|=0x01;
  133.   else dat&=0xfe;
  134.   SCK_D(0);
  135. }
  136.   SCK_D(0);
  137.   return dat;
  138. }
  139. #endif
  140. ///////////////////////////////////////////////////////
  141. ///////////////////////////////////////////////////////

  142. #if _CPOL==1&&_CPHA==1            //MODE  1  1
  143. void SPI_Send_Dat(unsigned char dat)
  144. {
  145. unsigned char n;
  146. SCK_D(1);
  147. for(n=0;n<8;n++)
  148. {
  149.   SCK_D(0);
  150.   if(dat&0x80)MOSI_D(1);
  151.   else MOSI_D(0);
  152.   dat<<=1;
  153.   SCK_D(1);
  154. }
  155. }
  156. /************************************
  157. 模式三          读数据
  158. ************************************/
  159. unsigned char SPI_Receiver_Dat(void)
  160. {
  161. unsigned char n ,dat,bit_t;
  162. SCK_D(0);
  163. for(n=0;n<8;n++)
  164. { SCK_D(0);
  165.   dat<<=1;
  166.   if(MISO_I())dat|=0x01;
  167.   else dat&=0xfe;
  168.   SCK_D(1);
  169. }
  170.   SCK_D(1);
  171.   return dat;
  172. }
  173. #endif
  174. /*************************************
  175. *************************************/
  176. void main()
  177. {

  178. SPI_Init();
  179. DDRB = 0XFF;
  180. //#if _CPOL
  181. //SCK_D(0);
  182. //#endif
  183. while(1)
  184. {
  185. //SSEL_D(0);
  186. //SPI_Send_Dat(0x01);
  187. //SPI_Send_Dat(0x31);
  188. //SSEL_D(1);
  189. SSEL_D(0);
  190. SPI_Send_Dat(0x81);
  191. PORTB =SPI_Receiver_Dat();
  192. SSEL_D(1);
  193. //delay();
  194. }
  195. }

vivilzb1985 发表于 2015-6-8 19:49 | 显示全部楼层

这个主要需要注意这个时序的顺序的。
shenmu2012 发表于 2015-6-10 19:36 | 显示全部楼层
信号的起始位跟结束位的需要注意的。
firstblood 发表于 2015-6-11 19:13 | 显示全部楼层

时序是很重要的,注意起始位的。
angerbird 发表于 2015-6-15 21:09 | 显示全部楼层
这个需要注意单片机的主频频率大小的,主频太小的话肯定是不行的。
smilingangel 发表于 2015-6-16 20:35 | 显示全部楼层

这个程序中怎不需要加短延时程序的?
 楼主| 王大熊 发表于 2015-6-22 09:40 | 显示全部楼层
smilingangel 发表于 2015-6-16 20:35
这个程序中怎不需要加短延时程序的?

一般都不用加的,实际测试没什么问题。
comeon201208 发表于 2015-7-11 17:35 | 显示全部楼层
这个是需要注意信号的时序的,特别是首尾信号的电平变化的。
firstblood 发表于 2015-7-15 21:34 | 显示全部楼层

注意这个时序信号的操作很重要的。
make8419247 发表于 2015-7-16 12:07 | 显示全部楼层
4种模式全部测试通过了吗
 楼主| 王大熊 发表于 2015-7-17 09:15 | 显示全部楼层
make8419247 发表于 2015-7-16 12:07
4种模式全部测试通过了吗

都是可以的。
make8419247 发表于 2015-7-17 15:14 | 显示全部楼层
两个GD32之间的SPI是不是主机和分机的模式都必须一致
angerbird 发表于 2015-7-17 22:18 | 显示全部楼层
没看懂上边的时序图中的CPOL的信号是干啥的
zhangbo1985 发表于 2015-7-26 23:03 | 显示全部楼层
四种模式?总么讲啊。。。一般就是数据的读写的呗。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

236

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部