STM32F4 SPI1 工作,SPI5 不工作?

Posted

技术标签:

【中文标题】STM32F4 SPI1 工作,SPI5 不工作?【英文标题】:STM32F4 SPI1 working, SPI5 not working? 【发布时间】:2017-09-23 06:36:23 【问题描述】:

我有一个 STM32 Nucleo-F410RB 开发板,并且能够让我的外部 DAC 与 SPI1 一起工作,包括忙等待和 DMA。然后,我设计了自己的定制 PCB,构建了它并能够对其进行闪存。在设计阶段,我从使用 SPI1 切换到 SPI5,因为我需要 SPI1 引脚来实现其他功能。但我无法让 SPI5 在我的新设计中工作 - SCK 和 MOSI 引脚上没有信号。当我将代码更改为使用 SPI1 时,我在各自的 SPI1 SCK 和 MOSI 引脚上看到了信号。

我回到我的 Nucleo 板时遇到了同样的问题 - SPI1 工作正常,但 SPI5 根本不工作。我将 Eclipse 与 ARM GNU 编译器和最新版本的标准外设库(不是 HAL)一起使用。

SPI 初始化函数:

void init_spi(void) 

//initialize MOSI and SCK pins
//initialize SPI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_0; //SCK
gpio_init.GPIO_Speed = GPIO_Fast_Speed;
gpio_init.GPIO_Mode = GPIO_Mode_AF;
gpio_init.GPIO_OType = GPIO_OType_PP;
gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &gpio_init);

gpio_init.GPIO_Pin = GPIO_Pin_8; //MOSI
gpio_init.GPIO_Speed = GPIO_Fast_Speed;
gpio_init.GPIO_Mode = GPIO_Mode_AF;
gpio_init.GPIO_OType = GPIO_OType_PP;
gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL; 
GPIO_Init(GPIOB, &gpio_init);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_SPI5);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_SPI5);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

//initialize DAC CS PIN
gpio_init.GPIO_Pin = DAC_CS_PIN;
gpio_init.GPIO_Speed = GPIO_Fast_Speed;
gpio_init.GPIO_Mode = GPIO_Mode_OUT;
gpio_init.GPIO_OType = GPIO_OType_PP;
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &gpio_init);


SPI_I2S_DeInit(SPI5);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE); //enable SPI clock

SPI_InitTypeDef spi_init;
spi_init.SPI_Direction = SPI_Direction_1Line_Tx;
spi_init.SPI_Mode = SPI_Mode_Master;
spi_init.SPI_DataSize = SPI_DataSize_8b; //8b? Need to clock in 24 bits of data per DAC channel
spi_init.SPI_CPOL = SPI_CPOL_Low; //5134 uses low to high and high to low clock transitions. ie. idle state is LOW
spi_init.SPI_CPHA = SPI_CPHA_2Edge; //clock phase - data is clocked on falling edge of clock pulse
spi_init.SPI_NSS = SPI_NSS_Soft; //DAC chip select is handled in software
spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //APB2 clock/2, so 25 MHz SPI clock speed
spi_init.SPI_FirstBit = SPI_FirstBit_MSB; //check datasheet
spi_init.SPI_CRCPolynomial = 7; //what is this?
SPI_Init(SPI5, &spi_init);
SPI_Cmd(SPI5, ENABLE);

SPI写入函数:

void spi_write_dac(uint16_t value, uint8_t channel)  //currently just use busy/wait to transmit data to test DAC

uint8_t dac_low = value & 0xFF; //take bottom 8 bits
uint8_t dac_high = value >> 8; //take top 8 bits
GPIO_ResetBits(GPIOA, DAC_CS_PIN); //CS low
while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_TXE) == RESET);//wait for empty buffer
SPI_I2S_SendData(SPI5, channel); //send control byte
while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_BSY) == SET); //wait for byte to be sent
SPI_I2S_SendData(SPI5, dac_high); //send first data byte
while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_BSY) == SET); //wait for byte to be sent
SPI_I2S_SendData(SPI5, dac_low); //send second data byte
while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_BSY) == SET); //wait for byte to be sent
GPIO_SetBits(GPIOA, DAC_CS_PIN);


 

此代码不起作用,但是当我将所有 SPI5 引用更改为 SPI1 并将 PB3 用于 SCK 并将 PB5 用于 MOSI 时,SPI 正在工作。我检查了 SPI 控制寄存器,它们看起来已经为 SPI5 正确配置了,所以我开始搞砸了。

为什么 SPI1 在我自己的设计和 Nucleo 板上都能正常工作,但 SPI5 在任何一个板上都不能工作?

【问题讨论】:

你有想过这个吗?我在使用 Chibios 和 F7 时遇到了类似的问题 【参考方案1】:

我也犯了同样的错误。

GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_SPI5);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_SPI5);

对于 STM32F410,GPIO_AF_SPI5 必须是 GPIO_AF6_SPI5。

#define GPIO_AF6_SPI5         ((uint8_t)0x06)  /* SPI5 Alternate Function mapping (Only for STM32F410xx/STM32F411xE Devices) */

【讨论】:

【参考方案2】:

这很容易回答。 SPI5 没有映射到 PB3 和 PB5... 如果您查看第 39 页的数据表(数据表第 5 版),您会看到:

在 PB3 上,您可以使用 JTDO-SWO、I2C4_SDA、SPI1_SCK/I2S1_CK、USART1_RX、I2C2_SDA、EVENTOUT,但不能使用 SPI5

在 PB5 上,您可以使用 LPTIM1_IN1、I2C1_SMBA、SPI1_MOSI/I2S1_SD、EVENTOUT,但不能使用 SPI5

如果真的要使用SPI5,可以使用以下IO:

SPI5_MISO:PA12

SPI5_MOSI:PA10 或 PB8

SPI5_SCK: PB0

【讨论】:

感谢您的回复。是的,我知道引脚映射。 PB3 和 PB5 适用于 SPI1,在我的 SPI5 示例代码中,我正在使用 PB0 和 PB8 设置 SPI5(也尝试过 PA10,但没有运气)。【参考方案3】:

当您的所有引用都是针对 SPI5 外设时,您的 init_spi() 函数中的 SPI_I2S_DeInit(SPI1); 是否正常?

如果我没记错的话,目标 STM32 是 STM32F410RBT6。我把数据表和参考手册放在这里以供将来使用:

STM32F410RBT6 Datasheet

STM32F410RBT6 Reference Manual

【讨论】:

是的,抱歉,这是一个错字(现已更正)。基本上,当所有引用 SPI1 和 SPI1 引脚都已设置时,SPI1 按预期工作,但更改所有对 SPI5 的引用并使用 SPI5 引脚(用于 SCK 的 PB0 和用于 MOSI 的 PB8)它不起作用。 是的,确认一下,这些分别是我正在使用的数据表和参考手册。

以上是关于STM32F4 SPI1 工作,SPI5 不工作?的主要内容,如果未能解决你的问题,请参考以下文章

STM32F4 USART1 无法正常工作并返回垃圾数据

带有 DMA 7 通道常规组的 STM32F4 ADC 不工作

如何将 STM32f4 编程为 SPI 从设备

STM32F4 上的 USB 音频输入

如何在stm32f2xx or stm32f4xx中使用spi dma来完成全双攻通信

STM32F4的USB时钟必须工作在48MHZ吗?如果不是48M会有啥问题