OpenEdv-开源电子网

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

STM32F103的SPI 收发问题,只能收发第一个数

[复制链接]

2

主题

9

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-12-25
在线时间
9 小时
发表于 2015-12-25 21:50:28 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 sheye 于 2015-12-25 22:05 编辑

我是刚接触STM32,用的库函数,项目需求所以需要用STM32与CC1110通过STM32通信。我先是用STM32做从机和电脑端的上位机测试通信先,SPI 的 4线+vcc+gnd都连接好了并且对了,STM32用下面的程序和上位机通信,收发数组时只能收发第一个数据,即datatemp【0】
求大神解惑这是为什么,哪里写错了?
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"#include "spi.h"
u8 TEXT_Buffer[10]={1,1,2,0,0,0,0,0,0,0};//STM32发送的测试数据
#define SIZE sizeof(TEXT_Buffer)
#define        SPI_SWJ_CS                 PBout(12)         
int main(void)
{         
        u8 datatemp[SIZE];//接收从上位机收到的数据
        delay_init();            
        uart_init(115200);
        LED_Init();                                 
        SPI2_Init();        
        SPI2_SetSpeed(SPI_BaudRatePrescaler_32);//设置为1.125M时钟


SPI_SWJ_CS=0;     //使能片选信号
         
        while(1)
        {
                SPI_Ecah_Buffer_Send(datatemp,TEXT_Buffer,SIZE);//收发数组数据
                if(datatemp[0]!=0)
                {
                        LED0=!LED0;//若从上位机收到datatemp[0]数据不为0则闪烁led0        
                }        

                if(datatemp[1]!=0)
                {
                        LED1=!LED1;//若从上位机收到datatemp[1]数据不为0则闪烁led1        
                }               
        delay_ms(500);               
        }
}
//初始化SPI2
void SPI2_Init(void)
{
         GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能
        RCC_APB1PeriphClockCmd(        RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能         

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

         GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  // PB12 推挽       CS片选
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(GPIOB, &GPIO_InitStructure);
         GPIO_SetBits(GPIOB,GPIO_Pin_12);
        
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;                //设置SPI工作模式:设置为从SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //串行同步时钟的空闲状态为高电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;                //改改改定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(SPI2, ENABLE); //使能SPI外设
                 

}   

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);

}

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{               
        u8 retry=0;                                         
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                          
        SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
        retry=0;

        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                                                              
        return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据                                            
}

//收发数组数据
void SPI_Ecah_Buffer_Send(u8* str , u8* pBuffer, u8 NumByteToRead) //发送接收读写数组数据
{
                u8 i;
for(i=0; i < NumByteToRead; i++)
{
*str = SPI2_ReadWriteByte(*pBuffer);
pBuffer++;
str++;
    //         delay_ms(10);        
}
}

QQ图片20151225214436.jpg


这是上位机收发数据的界面,左边是从STM32收到的读数,无论收多少次,收到的都是u8 TEXT_Buffer[10]={1,1,2,0,0,0,0,0,0,0};的第一个数1
右边是上位机发给STM32的数,不论上位机发什么数,STM32都只能接受到第一个数,即即LED0会闪烁,LED1不会闪烁
如果void SPI_Ecah_Buffer_Send(u8* str , u8* pBuffer, u8 NumByteToRead) 这个函数中不加标蓝的延时,则收发都只能第一个数,如果加上延时函数,上位机偶尔能收到TEXT_Buffer[10]={1,1,2,0,0,0,0,0,0,0}中不是第一个数1的其他书,但是STM32还是只能收到上位机发来的第一个数
求解答!!!!!!!!!!!!!!

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

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-12-26 20:41:07 | 显示全部楼层
回复

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-12-25
在线时间
9 小时
 楼主| 发表于 2015-12-27 18:24:59 | 显示全部楼层
自顶,求救啊!!!!!!!!!
回复

使用道具 举报

1

主题

84

帖子

0

精华

高级会员

Rank: 4

积分
529
金钱
529
注册时间
2015-7-21
在线时间
47 小时
发表于 2015-12-28 08:59:34 | 显示全部楼层
sheye 发表于 2015-12-27 18:24
自顶,求救啊!!!!!!!!!

LZ在SPI2_ReadWriteByte()函数里有两个while的循环是什么意思?在等待发送、接收缓冲区为空吗?通过retry++后retry与200的比较来跳出循环? 是不是应该改成 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) ; 来死等  或者 if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET)  return SPI_I2S_ReceiveData(SPI2); 判断标志位的确为空后再返回接受的数据。
一名合格的工程师一定要做到,代码虐我千百遍依然待她如初恋!
回复

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-12-25
在线时间
9 小时
 楼主| 发表于 2015-12-28 20:31:23 | 显示全部楼层
流水若冰 发表于 2015-12-28 08:59
LZ在SPI2_ReadWriteByte()函数里有两个while的循环是什么意思?在等待发送、接收缓冲区为空吗?通过ret ...

LZ在SPI2_ReadWriteByte()函数是先发送数据,再接收数据,是个收发一体的函数,原子的例程里是这么用的
回复

使用道具 举报

30

主题

282

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1001
金钱
1001
注册时间
2015-8-24
在线时间
241 小时
发表于 2015-12-28 23:38:45 | 显示全部楼层
流水若冰 发表于 2015-12-28 08:59
LZ在SPI2_ReadWriteByte()函数里有两个while的循环是什么意思?在等待发送、接收缓冲区为空吗?通过ret ...

这个想法应该是可以的。
回复

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-12-25
在线时间
9 小时
 楼主| 发表于 2015-12-30 23:22:00 | 显示全部楼层
自顶!!!!!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-21 21:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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