OpenEdv-开源电子网

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

两个STM32进行SPI通信的问题

[复制链接]

2

主题

2

帖子

0

精华

新手入门

积分
30
金钱
30
注册时间
2014-7-11
在线时间
0 小时
发表于 2014-7-12 17:08:38 | 显示全部楼层 |阅读模式
5金钱

主机用SPI1,从机用SPI2。目的是主机发送一组数据,从机接受,同时从机返回一组数据,通过串口打印验证。下面是程序。

主机SPI初始

#include "stm32f10x.h"

#include "SPI_init.h"

#include "sys.h"

void SPI1_Configaration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  SPI_InitTypeDef  SPI_InitStructure;


RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能 

RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1,  ENABLE );//SPI1时钟使能

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA


SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工

SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置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_4; //定义波特率预分频的值:波特率预分频值为4

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始

SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式

SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

 

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

}   

主机main函数

#include "stm32f10x.h"

#include "SPI_init.h"

#include "usart_init.h"

#include "delay.h"

#include "sys.h"

#define buffersize 32

u8 SPI1_buffer_TX[buffersize]=

{

0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,

0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,

0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,

0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20

};

u8 SPI_buffer_RX[buffersize]={0};

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

usart_configuration(115200);

SPI1_Configaration();

while(TX_Counter<buffersize)

{

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); //检查指定的SPI标志位设置与否:发送缓存空标志位  

SPI_I2S_SendData(SPI1, SPI1_buffer_TX[TX_Counter]); //通过外设SPIx发送一个数据

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位    

   SPI_buffer_RX[RX_Counter]=SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据

//SPI1_RXNE=SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);

//printf(" %0.2d \r ",SPI1_RXNE);

TX_Counter++;

RX_Counter++;

}

printf("\r\n SPI1 输出数据如下:\r\n");

while(i<buffersize)

{

printf(" %0.2d \r ",SPI1_buffer_TX);

i++;

}

printf("\r\n SPI1 收到数据如下:\r\n");

while(k<buffersize)

{

printf(" %0.2d \r ",SPI_buffer_RX[k]);

k++;

}

while(1);

}

从机SPI初始化

#include "stm32f10x.h"

#include "SPI_init.h"

#include "sys.h"

void SPI2_Configaration(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_Pin_12;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB


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_4; //定义波特率预分频的值:波特率预分频值为4

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外设

}   

从机主函数

#include "stm32f10x.h"

#include "SPI_init.h"

#include "usart_init.h"

#include "delay.h"

#include "sys.h"

#define buffersize 32

u8 SPI2_buffer_TX[buffersize]=

{

0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,

0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,

0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,

0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70

};

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

usart_configuration(115200);

SPI2_Configaration();

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); //返回通过SPIx最近接收的数据

TX_Counter++;

RX_Counter++;

}

printf("\r\n SPI2 输出数据如下:\r\n");

while(i<buffersize)

{

printf(" %0.2d \r ",SPI2_buffer_TX);

i++;

}

printf("\r\n SPI2 收到数据如下:\r\n");

while(k<buffersize)

{

printf(" %0.2d \r ",SPI_buffer_RX[k]);

k++;

}

while(1);

}

运行结果是主机收到一些无规律的数,从机收到的数全是0。
顺便问一下这个过程中自己的几个疑问

1、SPI通信时,初始化是,波特率预分频到底是什么,为什么SPI1和SPI2的速度分别为72M和36M,但采用相同的预分频系数,这样两者波特率不同为什么能通信。(事实证明是可以的。)
2、对寄存器操作怎么没有效果SPI1->SR&=~(1<<1);
3、实验中,我发现TXE位一直是1
真心希望得到大家的帮组!!!


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

使用道具 举报

0

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2014-6-10
在线时间
0 小时
发表于 2014-7-12 21:08:20 | 显示全部楼层
SPI1使用的时钟源是PCLK2 ,而SPI2使用的时钟源是PCLK1,PCLK1=36M,PCLK2=72M,这就是他们速度差别,所以即使使用相同的分频系数,他们的波特率是不相同的,存在2倍的关系!如果你正好将SPI1的波特率设置成是SPI2波特率的2倍,这样是可以通讯的!
其他的问题我不清楚!
回复

使用道具 举报

28

主题

1489

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1656
金钱
1656
注册时间
2013-7-24
在线时间
1 小时
发表于 2014-7-12 21:24:35 | 显示全部楼层
1、同步串行通信;
2、SR是只读寄存器;
3、速度杠杠地,太快了。
于20150522停用该账号:http://www.microstar.club
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-6 06:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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