OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4089|回复: 12

两个STM32F427之间的SPI通信问题

[复制链接]

10

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2016-8-25
在线时间
62 小时
发表于 2019-6-28 11:46:09 | 显示全部楼层 |阅读模式
20金钱
用的标准库。
问题1、硬件设计是否有问题?连线如图1所示: 微信图片_20190628103642.jpg

问题2、NSS这根数据线的电平信号在数据传输的过程中需要设置嘛?主从都设计成SPI_NSS_Soft 软件模式。在各大论坛上看到的这个实验,主从配置没有什么区别,关键是主程序的读数据和写数据。以下是配置文件和主程序。这配置是否有问题?主程序能不能这样写?
主从都是SPI2.

主机配置:
  1. void SPI2_Init(void)
  2. {
  3. SPI_Cmd(SPI2, DISABLE);
  4. GPIO_InitTypeDef GPIO_InitStructure;
  5. SPI_InitTypeDef SPI2_InitStructure;

  6. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ê1ÄüGPIODê±Öó
  7. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//ê1ÄüGPIOBê±Öó

  8. SPI_I2S_DeInit(SPI2);
  9. //GPIOs initialize
  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_14| GPIO_Pin_15;//PB3~5¸′óÃ1|Äüêä3ö       
  11. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸′óÃ1|Äü
  12. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//íÆíìêä3ö
  13. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  14. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//éÏà-
  15. GPIO_Init(GPIOB, &GPIO_InitStructure);//3õê¼»ˉ

  16. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//Master CLK_Pin
  17. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//ÆÕí¨êä3öÄ£ê½
  18. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//íÆíìêä3ö
  19. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//éÏà-
  21. GPIO_Init(GPIOD, &GPIO_InitStructure);//3õê¼»ˉGPIO
  22. //GPIO AF
  23. GPIO_PinAFConfig(GPIOB,GPIO_PinSource9,GPIO_AF_SPI2);
  24. GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
  25. GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
  26. GPIO_PinAFConfig(GPIOD,GPIO_PinSource3,GPIO_AF_SPI2);

  27. GPIO_SetBits(GPIOB,GPIO_Pin_9|GPIO_Pin_14| GPIO_Pin_15);
  28. GPIO_SetBits(GPIOD,GPIO_Pin_3); //3õê¼»ˉà-¸ßμçÆ½

  29. RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//ê1ÄüSPI2ê±Öó

  30. SPI2_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //éèÖÃSPIμ¥Ïò»òÕßË«ÏòμÄêy¾YÄ£ê½:SPIéèÖÃÎaË«ÏßË«Ïòè«Ë«1¤
  31. SPI2_InitStructure.SPI_Mode = SPI_Mode_Master;        //éèÖÃSPI1¤×÷Ä£ê½:éèÖÃÎaÖ÷SPI
  32. SPI2_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //éèÖÃSPIμÄêy¾Y′óD¡:SPI·¢Ëí½óêÕ8λ֡½á11
  33. SPI2_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //′®DDí¬2½ê±ÖóμÄ¿ÕÏD×′ì¬μíμçÆ½
  34. SPI2_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //′®DDí¬2½ê±ÖóμÄμú¶t¸öìø±äÑØ£¨éÏéy»òϽ죩êy¾Y±»2éÑù
  35. SPI2_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSSDÅoÅóéó2¼t£¨NSS1ü½Å£©»1êÇèí¼t£¨ê1óÃSSI룩1üàí:Äú2¿NSSDÅoÅóDSSIλ¿ØÖÆ
  36. SPI2_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;        //¶¨òå2¨ìØÂêÔ¤·ÖÆμμÄÖμ:2¨ìØÂêÔ¤·ÖÆμÖμÎa256
  37. SPI2_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //Ö¸¶¨êy¾Y′«êä′óMSBλ»1êÇLSBλ¿aê¼:êy¾Y′«êä′óMSBλ¿aê¼
  38. SPI2_InitStructure.SPI_CRCPolynomial = 7;        //CRCÖμ¼ÆËãμĶàÏîê½       

  39. SPI_Init(SPI2, &SPI2_InitStructure); //¸ù¾YSPI_InitStructÖDÖ¸¶¨μÄ2Îêy3õê¼»ˉíaéèSPIx¼Ä′æÆ÷
  40. SPI_Cmd(SPI2, ENABLE); //ê1ÄüSPIíaéè       
  41. //        SPI2_ReadWriteByte(0xff);//Æô¶ˉ′«ê䣬¿éòa¿é2»òa       
  42. }
复制代码


从机配置
  1. void SPI2_Init(void)
  2. {
  3.         SPI_Cmd(SPI2, DISABLE);
  4.         GPIO_InitTypeDef  GPIO_InitStructure;
  5.   SPI_InitTypeDef  SPI2_InitStructure;
  6.        
  7.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ê1ÄüGPIODê±Öó

  8.   //GPIOs initialize
  9.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14| GPIO_Pin_15|GPIO_Pin_13;
  10.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//
  11.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//íÆíìêä3ö
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  13.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//éÏà-
  14.   GPIO_Init(GPIOB, &GPIO_InitStructure);//3õê¼»ˉ
  15.        
  16.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;// NSS
  17.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//êäèë
  18. //  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//íÆíìêä3ö
  19.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//éÏà-
  21.   GPIO_Init(GPIOB, &GPIO_InitStructure);//3õê¼»ˉGPIO
  22.         //GPIO AF
  23.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource12|GPIO_PinSource14|GPIO_PinSource15|GPIO_PinSource13,GPIO_AF_SPI2);


  24.         //ÕaàïÖ»Õë¶ÔSPI¿ú3õê¼»ˉ
  25.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//ê1ÄüSPI2ê±Öó

  26.         SPI2_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //éèÖÃSPIμ¥Ïò»òÕßË«ÏòμÄêy¾YÄ£ê½:SPIéèÖÃÎaË«ÏßË«Ïòè«Ë«1¤
  27.         SPI2_InitStructure.SPI_Mode = SPI_Mode_Slave;                //éèÖÃSPI1¤×÷Ä£ê½:éèÖÃÎaÖ÷SPI
  28.         SPI2_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //éèÖÃSPIμÄêy¾Y′óD¡:SPI·¢Ëí½óêÕ8λ֡½á11
  29.         SPI2_InitStructure.SPI_CPOL = SPI_CPOL_Low;                //′®DDí¬2½ê±ÖóμÄ¿ÕÏD×′ì¬Îa¸ßμçÆ½
  30.         SPI2_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //′®DDí¬2½ê±ÖóμÄμú¶t¸öìø±äÑØ£¨éÏéy»òϽ죩êy¾Y±»2éÑù
  31.         SPI2_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSSDÅoÅóéó2¼t£¨NSS1ü½Å£©»1êÇèí¼t£¨ê1óÃSSI룩1üàí:Äú2¿NSSDÅoÅóDSSIλ¿ØÖÆ
  32.         SPI2_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;                //¶¨òå2¨ìØÂêÔ¤·ÖÆμμÄÖμ:2¨ìØÂêÔ¤·ÖÆμÖμÎa256
  33.         SPI2_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //Ö¸¶¨êy¾Y′«êä′óMSBλ»1êÇLSBλ¿aê¼:êy¾Y′«êä′óMSBλ¿aê¼
  34.         SPI2_InitStructure.SPI_CRCPolynomial = 7;        //CRCÖμ¼ÆËãμĶàÏîê½
  35.        

  36.         SPI_Init(SPI2, &SPI2_InitStructure);  //¸ù¾YSPI_InitStructÖDÖ¸¶¨μÄ2Îêy3õê¼»ˉíaéèSPIx¼Ä′æÆ÷
  37.         SPI_Cmd(SPI2, ENABLE); //ê1ÄüSPIíaéè       
  38. }
复制代码

主机的主程序
  1. int main(void)
  2. {       
  3.         SPI2_Init();       
  4.         while(1)
  5.         {
  6.                 for( i=0;i<4;i++)
  7.                 {               
  8.                         while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET)
  9.                         {
  10.                                 retry++;
  11.                                 if (retry>200)
  12.                                 {
  13.                                         return 0;
  14.                                 }
  15.                         }
  16.                         SPI_I2S_SendData(SPI2,txbuffer[i]);
  17.                         while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET)
  18.                         {
  19.                                 retry++;
  20.                                 if (retry>200)
  21.                                 {
  22.                                         return 0;
  23.                                 }
  24.                         }
  25.                          SPI_I2S_ReceiveData(SPI2);       
  26.                 }               
  27.         }
  28. }
复制代码
从机的主程序
  1. int main(void)
  2. {       
  3.         Uart3_init(115200);       
  4.         SPI2_Init();
  5.         printf(" %x\n",rxbuffer[0]);               
  6.         while(1)
  7.         {               
  8.                 for(int i=0;i<4;i++)
  9.                 {
  10.                         while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET){}
  11.                         rxbuffer[i]=SPI_I2S_ReceiveData(SPI2);
  12.                         while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET){}
  13.                         SPI_SendData(SPI2,0x11);
  14.                 }
  15.                 for(int i=0;i<4;i++)
  16.                 {
  17.                         printf(" %x\n",rxbuffer[i]);                       
  18.                 }
  19.                  
  20.         }
  21. }
复制代码
问题3、在debug主机的过程中,只要执行SPI_I2S_SendData(SPI2,txbuffer);这么一句话,MOSI和SCK数据线,用示波器测量,可以得到正确的数据波形图和时钟信号波形图,但是测试MISO数据线上的话,永远都是高电平,得出从器件的问题。但是不知道哪里问题。
问题4、看完SPI的原理后,最主要是:主器件发起数据的传输,然后从器件同时往miso信号线上发送数据,但是不太明白在程序里面如何体现出这个循环移位过程。我这个是属于查询的方式,中断也尝试过,中断模仿的是原子论坛里面的一个精帖。但是仍然不通。
论坛的各位带哥帮忙看看。









正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-6-28 13:13:24 | 显示全部楼层
当spi配置为SPI_Direction_2Lines_FullDuplex时
主机要读数据, 需要同时发送数据。没有只读不发的
回复

使用道具 举报

10

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2016-8-25
在线时间
62 小时
 楼主| 发表于 2019-6-28 17:11:32 | 显示全部楼层
edmund1234 发表于 2019-6-28 13:13
当spi配置为SPI_Direction_2Lines_FullDuplex时
主机要读数据, 需要同时发送数据。没有只读不发的

你好,那主机那一块的主程序应该怎么写呢?还有我这个硬件设计没问题吧  NSS这根数据线不需要操作吧?比如set或者reset?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2019-6-29 02:42:25 | 显示全部楼层
LeBron 发表于 2019-6-28 17:11
你好,那主机那一块的主程序应该怎么写呢?还有我这个硬件设计没问题吧  NSS这根数据线不需要操作吧?比 ...

MISO接MOSI。
接错了你
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-6-29 08:38:34 | 显示全部楼层
本帖最后由 edmund1234 于 2019-6-29 08:50 编辑
LeBron 发表于 2019-6-28 17:11
你好,那主机那一块的主程序应该怎么写呢?还有我这个硬件设计没问题吧  NSS这根数据线不需要操作吧?比 ...

随便写个0或者0xFF(从需要忽略它),SPI1->DR=0xFF, 然后再读 data=SPI1->DR。
一主一从可以不接NSS, 配置时把SPI1->CR1的SSM设为1就可以。


回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-6-29 08:39:10 | 显示全部楼层
正点原子 发表于 2019-6-29 02:42
MISO接MOSI。
接错了你

MISO接MISO是对的
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2019-6-30 00:43:08 | 显示全部楼层

额,我倒是没用过这个模式,正常来说是MOSI接MISO。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

10

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2016-8-25
在线时间
62 小时
 楼主| 发表于 2019-7-1 11:28:54 | 显示全部楼层
edmund1234 发表于 2019-6-29 08:38
随便写个0或者0xFF(从需要忽略它),SPI1->DR=0xFF, 然后再读 data=SPI1->DR。
一主一从可以不接NSS,  ...

你好,从需要忽略他    的意思是在从器件的程序中不执行receive那个函数嘛?还是执行这个函数但是数据扔掉。?
回复

使用道具 举报

10

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2016-8-25
在线时间
62 小时
 楼主| 发表于 2019-7-1 11:31:47 | 显示全部楼层
正点原子 发表于 2019-6-30 00:43
额,我倒是没用过这个模式,正常来说是MOSI接MISO。

原子哥,你说的这个正常来说 是什么意思?MOSI意思主发送,从接收,MISO是主接收,从发送。如果这两根线接在一起,程序怎么设置都不会出现数据的环流吧?还是我理解错了?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-7-1 22:48:41 | 显示全部楼层
LeBron 发表于 2019-7-1 11:28
你好,从需要忽略他    的意思是在从器件的程序中不执行receive那个函数嘛?还是执行这个函数但是数据扔 ...

执行这个函数但是数据扔掉
回复

使用道具 举报

34

主题

331

帖子

0

精华

高级会员

Rank: 4

积分
857
金钱
857
注册时间
2018-9-16
在线时间
240 小时
发表于 2019-7-2 13:57:51 | 显示全部楼层
楼主,实现了么,你这MISO与MISO接确定OK?
回复

使用道具 举报

10

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2016-8-25
在线时间
62 小时
 楼主| 发表于 2019-7-4 10:57:00 | 显示全部楼层
plue 发表于 2019-7-2 13:57
楼主,实现了么,你这MISO与MISO接确定OK?

这个解法是没有问题的,我后面用HAL库 写了程序,数据发送接收正常,就是还有一点点问题
回复

使用道具 举报

11

主题

95

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2017-3-19
在线时间
116 小时
发表于 2019-7-4 15:38:47 | 显示全部楼层
正点原子 发表于 2019-6-30 00:43
额,我倒是没用过这个模式,正常来说是MOSI接MISO。

MISO接MISO是对的,MISO为master input,slave output;MOSI为master output,slave input。不同于串口通讯,TX接RX
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-12 17:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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