[其他ST产品] 两个STM32用SPI通信遇到的问题

[复制链接]
1188|13
 楼主| 家有两宝呀 发表于 2023-11-30 23:26 | 显示全部楼层 |阅读模式
在使用两个STM32使用SPI协议通信时 主机设置时钟分频因子为2 从机设置分频因子也为2。从机可以正确收到主机发来的数据,但是主机收到从机的数据不是00就是FF。 而我把主机设置时钟分频因子为256 从机设置分频因子也为256。这样双方都可正确收发数据,我想问这是为什么呢。

主机SPI2设置

  1. void SPI2_Init(void)
  2. {
  3.     GPIO_InitTypeDef  GPIO_InitStructure;
  4.     SPI_InitTypeDef  SPI_InitStructure;
  5.     NVIC_InitTypeDef NVIC_InitStructure;
  6.    
  7.     /* SPI的IO口和SPI外设打开时钟 */
  8.     RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  10.    
  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;        //PB12推挽输出
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //
  13.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  14.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  15.    
  16.     /* SPI的IO口设置 */
  17.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  18.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出
  19.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  21.     GPIO_SetBits(GPIOB,GPIO_Pin_12);
  22.    
  23.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
  24.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPI
  25.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;        //设置SPI的数据大小:SPI发送接收8位帧结构
  26.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //串行同步时钟的空闲状态为高电平
  27.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  28.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  29.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;        //定义波特率预分频的值:
  30.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  31.     SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式
  32.     SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
  33.    
  34.     SPI_Cmd(SPI2, ENABLE); //使能SPI外设
  35.    
  36.    
  37.     SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);//开启相关中断
  38.     //Usart1 NVIC 配置
  39.     NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;//SPI2中断通道
  40.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
  41.     NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;        //子优先级2
  42.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
  43.     NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、   
  44.    
  45. }
  46. u16 t=0xDD; //中断接收数据
  47. void SPI2_IRQHandler(void)
  48. {
  49.             if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_RXNE) != RESET)
  50.     {
  51.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
  52.         t = SPI_I2S_ReceiveData(SPI2);
  53.         GPIO_SetBits(GPIOB,GPIO_Pin_12);//关闭片选
  54.         USART_senddate(USART1,t) ;
  55.     }
  56. }


 楼主| 家有两宝呀 发表于 2023-11-30 23:26 | 显示全部楼层
主机使用串口1发数据之后再用SPI发给从机
  1. void USART1_IRQHandler(void)                    //串口1中断服务程序
  2. {
  3.     u16 r;
  4.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
  5.     {
  6.         GPIO_ResetBits(GPIOB,GPIO_Pin_12);
  7.         r =USART_ReceiveData(USART1);//(USART1->DR);    //读取接收到的数据
  8.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空  
  9.         SPI_I2S_SendData(SPI2,r); //通过外设SPIx发送一个byte  数据
  10.     }
  11. }     
 楼主| 家有两宝呀 发表于 2023-11-30 23:26 | 显示全部楼层
从机SPI设置,用中断接收主机的数据再把接收的数据发回主机。
  1. void SPI2_Init(void)
  2. {
  3.     GPIO_InitTypeDef  GPIO_InitStructure;
  4.     SPI_InitTypeDef  SPI_InitStructure;
  5.     NVIC_InitTypeDef NVIC_InitStructure;
  6.    
  7.     /* SPI的IO口和SPI外设打开时钟 */
  8.     RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  10.    
  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;        //PB12推挽输出
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //下拉输入
  13.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  14.    
  15.     /* SPI的IO口设置 */
  16.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  17.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出
  18.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  19.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  20.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
  21.     SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;        //设置SPI工作模式:设置为主SPI
  22.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;        //设置SPI的数据大小:SPI发送接收8位帧结构
  23.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //串行同步时钟的空闲状态为高电平
  24.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  25.     SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  26.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;        //定义波特率预分频的值:波特率预分频值为256
  27.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  28.     SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式
  29.     SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
  30.    
  31.     SPI_Cmd(SPI2, ENABLE); //使能SPI外设
  32.    
  33.     SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);//开启相关中断
  34.     //Usart1 NVIC 配置
  35.     NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;//SPI2中断通道
  36.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级0
  37.     NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;        //子优先级2
  38.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
  39.     NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、   
  40.    
  41. }
  42. u16 i;
  43. void SPI2_IRQHandler(void)
  44. {
  45.     //接收数据
  46.     if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_RXNE) != RESET)
  47.     {
  48.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //等待接收完一个byte
  49.         i = SPI_I2S_ReceiveData(SPI2);
  50.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
  51.         SPI_I2S_SendData(SPI2,i);
  52.         USART_senddate(USART1, i);   
  53.     }
 楼主| 家有两宝呀 发表于 2023-11-30 23:27 | 显示全部楼层
左边是主机,显示收到的数据,结果收到的全是FF, 右边是从机,显示的是从主机发过去的g

916216568a9d246a51.png
夜阑风雨 发表于 2023-12-21 14:01 | 显示全部楼层
你用逻辑分析仪抓一下试试?
一秒落纱 发表于 2023-12-21 16:00 | 显示全部楼层
可能是频率太快?但一般来说,你从机都收到了数据,主机按理也不应该有问题啊
远山寻你 发表于 2023-12-21 18:00 | 显示全部楼层
是有影响么?周围有什么干扰或者影响么?
光辉梦境 发表于 2023-12-21 20:00 | 显示全部楼层
不太知道这个问题,可能是速度慢了,通信稳了?
三生万物 发表于 2023-12-21 22:00 | 显示全部楼层
那就用分频因子256吧,先能用为主呗
淡漠安然 发表于 2023-12-22 01:00 | 显示全部楼层
你可以先把主机断开,从机往主机发的数据用逻辑分析仪抓一下,看看数据是否正确
暖了夏天蓝了海 发表于 2023-12-22 03:00 | 显示全部楼层
这就得一点一点去查了,不好找问题,感觉是干扰引起的
江河千里 发表于 2023-12-22 09:00 | 显示全部楼层
为啥不是00就是FF呢?你发的是啥数据啊?
别乱了阵脚 发表于 2023-12-22 11:00 | 显示全部楼层
还是时钟没对上,不然不会这样的
冰春彩落下 发表于 2023-12-22 15:00 | 显示全部楼层
我也觉得有点意思,要是没对上应该都没对上才对啊,咋256分频系数就可以了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

585

帖子

0

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