你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103C8T6工控板双SPI互通讯实验

[复制链接]
STMCU小助手 发布时间:2022-11-18 22:55
SPI (Serial Peripheral interface)是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。

20210217225329376.png

今天分享下,基于STM32F103C8T6工控板上的两个SPI接口进行互相通讯,其中SPI1作为主机,SPI2作为从机。

硬件部分
1)某宝网上购买的STM32F103C8T6工控板,价格50¥左右;
2)某宝网上购买的232转USB数据线(如下图所示),价格15¥左右;
3)杜邦线若干,价格几乎为0¥。
20210114095104289.jpg

硬件连接
由原理图(如下所示)可知,将PA5与PB13连接,PA6与PB14连接,PA7与PB15连接即可。注意:SPI与串口的连接不同,串口的RX引脚接另一个串口TX引脚,而两个SPI连接是同名字的相连!

20210217225552953.png

20210217225648999.png


部分代码

1.spi.h头文件
  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: spi.h
  4. * @作者名称: 闲人Ne
  5. * @摘要简述: SPI头文件
  6. ******************************************************************************/
  7. #ifndef __SPI_H
  8. #define __SPI_H
  9. /* 包含的头文件 ---------------------------------------------------------------*/
  10. #include "stm32f10x.h"
  11. /* 函数申明 -------------------------------------------------------------------*/
  12. void SPI1_Init(void);     
  13. void SPI2_Init(void);
  14. u8 SPI1_ReadWriteByte(u8 TxData);
  15. u8 SPI2_ReadWriteByte(u8 TxData);
  16. #endif /* __SPI_H */
  17. /****** Copyright (C)2021 闲人Ne. All Rights Reserved ****** END OF FILE *******/
复制代码

2.spi.c源文件
  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: spi.c
  4. * @作者名称: 闲人Ne
  5. * @摘要简述: SPI头文件
  6. ******************************************************************************/
  7. /* 包含的头文件 ---------------------------------------------------------------*/
  8. #include "spi.h"
  9. /**************************************************
  10. 函数名称:SPI1_Init()
  11. 函数功能:SPI1初始化函数:配置成主机模式
  12. 入口参数:无
  13. 返回参数:无
  14. 开发作者:闲人Ne
  15. ***************************************************/
  16. void SPI1_Init(void)
  17. {
  18.   GPIO_InitTypeDef GPIO_InitStruct;  
  19.   SPI_InitTypeDef  SPI_InitStruct;   
  20.   RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA, ENABLE );     // GPIOA时钟使能,选择SPI1,对应PA4,PA5,PA6,PA7
  21.   RCC_APB2PeriphClockCmd(        RCC_APB2Periph_SPI1,  ENABLE );     // SPI1时钟使能         
  22.   // 初始化GPIOA,PA5/6/7都设置复用推挽输出AF_PP
  23.   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  24.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;                // 复用推挽输出AF_PP
  25.   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  26.   GPIO_Init(GPIOA, &GPIO_InitStruct);
  27.   GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);       // PA5/6/7置高电平
  28.   // 初始化SPI函数
  29.   SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;      // 设置SPI单向或双向的数据模式:SPI设置为双线双向全双工
  30.   SPI_InitStruct.SPI_Mode = SPI_Mode_Master;                                   // SPI1设为主机
  31.   SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;                       // 针对SPI_CR1寄存器的DFF位,设置数据帧大小为8位
  32.   SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;                                       // 针对SPI_CR1寄存器的CPOL位,串行同步时钟的空闲状态为高电平
  33.   SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;                                       // 针对SPI_CR1寄存器的CPHA位,串行同步时钟的第二个跳变沿(即上升沿)数据被采样
  34.   SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;                                           // 针对SPI_CR1寄存器的SSM位,NSS信号由软件(使用SSI位)管理
  35.   SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;           // 针对SPI_CR1寄存器的BR位,波特率预分频值为256,最低速率        
  36.   SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;                               // 针对SPI_CR1寄存器的LSBFIRST位,数据传输从MSB位开始
  37.   SPI_InitStruct.SPI_CRCPolynomial = 7;                                           // 针对SPI_CRCPR寄存器的CRCPOLY位,设为0x0007,为复位值
  38.   SPI_Init(SPI1, &SPI_InitStruct);  
  39.   SPI_Cmd(SPI1, ENABLE);                                               // 使能SPI外设                  
  40. }
  41. /**************************************************
  42. 函数名称:u8 SPI1_ReadWriteByte(u8 TxData)
  43. 函数功能:SPI1读写一个字节函数
  44. 入口参数:TxData:要写入的字节
  45. 返回参数:读取到的字节
  46. 开发作者:闲人Ne
  47. ***************************************************/
  48. u8 SPI1_ReadWriteByte(u8 TxData)
  49. {               
  50.   u8 retry=0;        
  51.   // 检查SPI_SR寄存器的TXE位(发送缓冲为空),其值0时为非空,1时为空        
  52.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  53.   {
  54.           retry++;                           // 发送缓冲为空时,retry++
  55.           if(retry>200)return 0;
  56.   }                          
  57.   SPI_I2S_SendData(SPI1, TxData);       // 通过外设SPI2发送一个数据
  58.   retry=0;
  59.   // 检查SPI_SR寄存器的RXNE位(接收缓冲为空),其值0时为空,1时为非空
  60.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
  61.   {
  62.            retry++;                         // 当接收缓冲为非空时,retry++
  63.            if(retry>200)return 0;
  64.   }                                                              
  65.   return SPI_I2S_ReceiveData(SPI1);     // 返回通过SPIx最近接收的数据                                            
  66. }
  67. /**************************************************
  68. 函数名称:SPI2_Init()
  69. 函数功能:SPI2初始化函数:配置成从机模式
  70. 入口参数:无
  71. 返回参数:无
  72. 开发作者:闲人Ne
  73. ***************************************************/
  74. void SPI2_Init(void)
  75. {
  76.   GPIO_InitTypeDef GPIO_InitStruct;  
  77.   SPI_InitTypeDef  SPI_InitStruct;   
  78.   RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );     // GPIOB时钟使能,选择SPI2,对应PB12,PB13,PB14,PB15
  79.   RCC_APB1PeriphClockCmd(        RCC_APB1Periph_SPI2,  ENABLE );     // SPI2时钟使能         
  80.   // 初始化GPIOB,PB13/14/15都设置复用推挽输出AF_PP,PB14对应MISO,最好设为带上拉输入
  81.   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  82.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;                  // 复用推挽输出AF_PP
  83.   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  84.   GPIO_Init(GPIOB, &GPIO_InitStruct);
  85.   GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);      // PB13/14/15置高电平
  86.   // 初始化SPI函数
  87.   SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;      // 设置SPI单向或双向的数据模式:SPI设置为双线双向全双工
  88.   SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;                                       // SPI2设为从机
  89.   SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;                       // 针对SPI_CR1寄存器的DFF位,设置数据帧大小为8位
  90.   SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;                                       // 针对SPI_CR1寄存器的CPOL位,串行同步时钟的空闲状态为高电平
  91.   SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;                                       // 针对SPI_CR1寄存器的CPHA位,串行同步时钟的第二个跳变沿(即上升沿)数据被采样
  92.   SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;                                           // 针对SPI_CR1寄存器的SSM位,NSS信号由软件(使用SSI位)管理
  93.   SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;    // 针对SPI_CR1寄存器的BR位,波特率预分频值为256,最低速率
  94.   SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;                               // 针对SPI_CR1寄存器的LSBFIRST位,数据传输从MSB位开始
  95.   SPI_InitStruct.SPI_CRCPolynomial = 7;                                           // 针对SPI_CRCPR寄存器的CRCPOLY位,设为0x0007,为复位值
  96.   SPI_Init(SPI2, &SPI_InitStruct);  
  97.   SPI_Cmd(SPI2, ENABLE);                                               // 使能SPI外设                  
  98. }
  99. /**************************************************
  100. 函数名称:u8 SPI1_ReadWriteByte(u8 TxData)
  101. 函数功能:SPI1读写一个字节函数
  102. 入口参数:TxData:要写入的字节
  103. 返回参数:读取到的字节
  104. 开发作者:闲人Ne
  105. ***************************************************/
  106. u8 SPI2_ReadWriteByte(u8 TxData)
  107. {               
  108.   u8 retry=0;        
  109.   // 检查SPI_SR寄存器的TXE位(发送缓冲为空),其值0时为非空,1时为空        
  110.   while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
  111.   {
  112.         retry++;                           // 发送缓冲为空时,retry++
  113.         if(retry>200)return 0;
  114.   }                          
  115.   SPI_I2S_SendData(SPI2, TxData);       // 通过外设SPI2发送一个数据
  116.   retry=0;
  117.   // 检查SPI_SR寄存器的RXNE位(接收缓冲为空),其值0时为空,1时为非空
  118.   while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
  119.   {
  120.         retry++;                           // 当接收缓冲为非空时,retry++
  121.         if(retry>200)return 0;
  122.   }                                                              
  123.   return SPI_I2S_ReceiveData(SPI2);     // 返回通过SPIx最近接收的数据                                            
  124. }
  125. /****** Copyright (C)2021 闲人Ne. All Rights Reserved ****** END OF FILE *******/
复制代码

3.main.c主函数
  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: main.c
  4. * @作者名称: 闲人Ne
  5. * @库版本号: V3.5.0
  6. * @工程版本: V1.0.0
  7. * @开发日期: 2021年02月17日
  8. * @摘要简述: 主函数
  9. ******************************************************************************/
  10. /* 包含的头文件 ---------------------------------------------------------------*/
  11. #include "led.h"
  12. #include "spi.h"
  13. #include "serial_communication.h"
  14. #include "sys.h"
  15. #include "delay.h"
  16. #include "nvic_configuration.h"
  17. /************************************************
  18. 函数名称:int main()
  19. 函数功能:主函数入口
  20. 入口参数:无
  21. 返回参数:int
  22. 开发作者:闲人Ne
  23. *************************************************/
  24. u8 spi1_sand_data=0;
  25. u8 spi2_sand_data=100;
  26. u8 spi2_receive_data;
  27. u8 spi1_receive_data;
  28. int main(void)
  29. {
  30.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  31.         delay_init();
  32.         SPI1_Init();
  33.         SPI2_Init();
  34.         My_USART1_Init();
  35.         D1=1;        
  36.         while(1)
  37.         {
  38.       spi1_receive_data=SPI1_ReadWriteByte(spi1_sand_data);
  39.           printf("\nSP1接收的数据为:%d\r\n",spi1_receive_data);        
  40.       spi2_receive_data=SPI2_ReadWriteByte(spi2_sand_data);        
  41.           printf("\nSP2接收的数据为:%d\r\n",spi2_receive_data);        
  42.           spi1_sand_data++; spi2_sand_data++;
  43.           delay_ms(500);
  44.         }
  45. }
  46. /****** Copyright (C)2021 闲人Ne. All Rights Reserved ****** END OF FILE *******/
复制代码

实验结果

20210217230914765.png
实验结果完全符合逻辑,通讯成功!

经验分享

该程序可作为双芯片之间SPI通讯的参考代码。
————————————————
版权声明:天亮继续睡


收藏 评论0 发布时间:2022-11-18 22:55

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版