OpenEdv-开源电子网

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

关于STM32F1的SPI双机通讯 主机接收不到数据

[复制链接]

1

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2018-4-21
在线时间
0 小时
发表于 2018-4-21 23:45:21 | 显示全部楼层 |阅读模式
11金钱
学习spi好几天了但是 spi双机通讯一直没有调试好。 希望大神解救一下。
  主机跟从机接收数据都出现了问题,主机一直接受的数据为0,而从机接收的不是从主机发出的数据。
代码有点多 STM32新手 真心求大家解答。谢谢大家了

原来的主机主函数里面的发送数据的这个函数while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) ==RESET) 会一直循环在这个地方
在网上论坛有人说改成while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET)这个 就可以解决  我感觉是这里出现了问题,但又不知道怎么解决。
时钟什么的都配置好了

[mw_shl_code=c,true]主机SPI配置
#include "spi.h"
#include "stm32f10x.h"

void Spi_Init()
{
//SPI_I2S_DeInit(SPI2);
        GPIO_InitTypeDef GPIO_InitStruce;
        SPI_InitTypeDef SPI_InitStruce;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
        GPIO_InitStruce.GPIO_Mode=GPIO_Mode_AF_PP;
  GPIO_InitStruce.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;  //SCLK MOSI推挽复用输出
  GPIO_InitStruce.GPIO_Speed=GPIO_Speed_50MHz;       

        GPIO_Init(GPIOB,&GPIO_InitStruce);

// GPIO_InitStruce.GPIO_Mode= GPIO_Mode_Out_PP;
        //GPIO_InitStruce.GPIO_Pin=GPIO_Pin_12;  //CS片选信号

        GPIO_Init(GPIOB,&GPIO_InitStruce);
       
        GPIO_InitStruce.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStruce.GPIO_Pin=GPIO_Pin_14;   //MISO浮动输入
        GPIO_Init(GPIOB,&GPIO_InitStruce);
  
       
        SPI_InitStruce.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_128;//波特率进行分频为2
        SPI_InitStruce.SPI_CPHA=SPI_CPHA_2Edge;//在第二个跳边沿接收数据
        SPI_InitStruce.SPI_CPOL=SPI_CPOL_High;//空闲时间时钟为高电平
        SPI_InitStruce.SPI_CRCPolynomial=7; //?
        SPI_InitStruce.SPI_DataSize=SPI_DataSize_8b;//选择为八位字节
        SPI_InitStruce.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//设置spi为双线全双工模式
        SPI_InitStruce.SPI_FirstBit=SPI_FirstBit_MSB;//数据传输从MSB开始
        SPI_InitStruce.SPI_Mode=SPI_Mode_Master;//设置为主机模式
        SPI_InitStruce.SPI_NSS=SPI_NSS_Soft;//软件控制NSS(片选)信号
  SPI_Init(SPI2,&SPI_InitStruce);
       
        SPI_Cmd(SPI2,ENABLE);

}

void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
        SPI2->CR1&=0XFFC7;
        SPI2->CR1|=SPI_BaudRatePrescaler;        //设置SPI2速度
        SPI_Cmd(SPI2,ENABLE);

}


uint8_t SPI_WriteByte(uint8_t TxData)
{
  while((SPI1->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);
  SPI1->DR = TxData;

  while((SPI1->SR & SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);
  return SPI1->DR;
}

uint8_t SPI_ReadByte(void)
{
  while((SPI1->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);
  SPI1->DR = 0xFF;

  while((SPI1->SR & SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);
       
  return SPI1->DR;
       
}





主机main
#include "stm32f10x.h"
#include "SPI.h"
#include "usart.h"
#include "delay.h"
#include "sys.h"
#define buffersize 1  
u8 SPI2_buffer_TX[buffersize]=
{
0X10
};
u8 SPI2_buffer_RX[buffersize];
u8 TX_Counter=0;
u8 RX_Counter=0;
u8 k=0;
u8 i=0;


int main(void)
{
u8 SPI1_RXNE=0;
u8 SPI1_TXE=0;
delay_init();
uart_init(9600);
Spi_Init();
while(TX_Counter<buffersize)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) ==RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位          
SPI_I2S_SendData(SPI2, SPI2_buffer_TX[TX_Counter]); //通过外设SPIx发送一个数据
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);//检查指定的SPI标志位设置与否:接受缓存非空标志位            
//返回通过SPIx最近接收的数据
TX_Counter++;
RX_Counter++;
  SPI2_buffer_RX[RX_Counter]=SPI_I2S_ReceiveData(SPI2);
}
printf("\r\n 主机输出数据如下:\r\n");
while(i<buffersize)
{
printf(" %2d \r\n ",SPI2_buffer_TX);
i++;
}
printf("\r\n SPI1 主机收到数据如下:\r\n");
while(k<buffersize)
{
printf(" %2d \r\n ",SPI2_buffer_RX[k]);
k++;
}
while(1);
}

[/mw_shl_code]

[mw_shl_code=c,true]从机SPI配置
#include "spi.h"
#include "stm32f10x.h"

void Spi_Init()
{
        GPIO_InitTypeDef GPIO_InitStruce;
        SPI_InitTypeDef SPI_InitStruce;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
        GPIO_InitStruce.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStruce.GPIO_Pin=GPIO_Pin_13;  //SCLK MISO推挽复用输出
GPIO_InitStruce.GPIO_Speed=GPIO_Speed_50MHz;       

        GPIO_Init(GPIOB,&GPIO_InitStruce);



        GPIO_InitStruce.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStruce.GPIO_Pin=GPIO_Pin_14;   //MISO复用推挽
GPIO_Init(GPIOB,&GPIO_InitStruce);
        GPIO_InitStruce.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStruce.GPIO_Pin=GPIO_Pin_15;   //MOSI浮动输入
GPIO_Init(GPIOB,&GPIO_InitStruce);


        SPI_InitStruce.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_128;//波特率进行分频为2
        SPI_InitStruce.SPI_CPHA=SPI_CPHA_2Edge;//在第二个跳边沿接收数据
SPI_InitStruce.SPI_CPOL=SPI_CPOL_Low;//空闲时间时钟为高电平
SPI_InitStruce.SPI_CRCPolynomial=7; //?
        SPI_InitStruce.SPI_DataSize=SPI_DataSize_8b;//选择为八位字节
SPI_InitStruce.SPI_Direction=SPI_Direction_1Line_Rx;//设置spi为双线全双工模式
SPI_InitStruce.SPI_FirstBit=SPI_FirstBit_MSB;//数据传输从MSB开始
SPI_InitStruce.SPI_Mode=SPI_Mode_Slave;//设置为从机模式
SPI_InitStruce.SPI_NSS=SPI_NSS_Soft;//软件控制NSS(片选)信号
SPI_Init(SPI2,&SPI_InitStruce);

        SPI_Cmd(SPI2,ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
}

/*void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
        SPI2->CR1&=0XFFC7;
        SPI2->CR1|=SPI_BaudRatePrescaler;        //设置SPI2速度
SPI_Cmd(SPI2,ENABLE);

} */


uint8_t SPI_WriteReadByte(uint8_t TxData)
{
  while((SPI1->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);
  SPI1->DR = TxData;

  while((SPI1->SR & SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);
  return SPI1->DR;
}





从机main
#include "stm32f10x.h"
#include "SPI.h"
#include "usart.h"
#include "delay.h"
#include "sys.h"
#define buffersize 1
u8 SPI2_buffer_TX[buffersize]=
{
0X11
};
u8 SPI_buffer_RX[buffersize]={0};
u8 TX_Counter=0;
u8 RX_Counter=0;
u8 k=0;
u8 i=0;
int main(void)
{
u8 SPI2_RXNE=0;
delay_init();
uart_init(9600);
Spi_Init();
while(TX_Counter<buffersize)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //检查指定的SPI标志位设置与否:发送缓存空标志位          
SPI_I2S_SendData(SPI2, SPI2_buffer_TX[TX_Counter]); //通过外设SPIx发送一个数据
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE )== RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位
SPI_buffer_RX[RX_Counter]=SPI_I2S_ReceiveData(SPI2);
TX_Counter++;
RX_Counter++;
}
printf("\r\n SPI2 输出数据如下:\r\n");
while(i<buffersize)
{
printf(" %2d \r\n ",SPI2_buffer_TX);
i++;
}
printf("\r\n SPI2 收到数据如下:\r\n");
while(k<buffersize)
{
printf(" %2d \r\n ",SPI_buffer_RX[k]);
k++;
}
while(1);
}

[/mw_shl_code]

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

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2018-4-21
在线时间
0 小时
 楼主| 发表于 2018-4-21 23:47:28 | 显示全部楼层
这么多代码  大神们分析一下原因也可以哇,我是真的有点崩溃了 哈哈
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2018-4-22 01:53:14 | 显示全部楼层
论坛有人发过,自己搜索对比。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-7 22:29

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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