【问题标题】:Why does SPI not work with my STM32f4DISCOVERY?为什么 SPI 不适用于我的 STM32f4DISCOVERY?
【发布时间】:2015-04-23 15:15:58
【问题描述】:

我已经被这个卡住了一段时间。我在网上关注了几个例子,但没有成功。我无法让它与我的 STM32F4Discovery 一起使用。我有一个外部芯片(更具体地说是 Semtech 的 SX1272),我尝试与之进行 SPI 通信。通过 Arduino 做的都是儿童游戏,但 ST 产品没有运气。 我用过示波器,它显示发送了 MOSI 命令,但没有 MISO 输出。 (使用 Arduino 很好)。这是我的代码:

#include "main.h"

void init_SPI1(void){   


  GPIO_InitTypeDef GPIO_InitStruct; 
  SPI_InitTypeDef SPI_InitStruct; 

  // enable clock for used IO pins 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 

  /* configure pins used by SPI1 
  * PA5 = SCK 
  * PA6 = MISO 
  * PA7 = MOSI 
  */ 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; 
  GPIO_Init(GPIOA, &GPIO_InitStruct); 

  // connect SPI1 pins to SPI alternate function 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); 

  // enable clock for used IO pins 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); 

  /* Configure the chip select pin 
  in this case we will use PE7 */ 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; 
  GPIO_Init(GPIOE, &GPIO_InitStruct); 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 high 

  // enable peripheral clock 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); 

  /* configure SPI1 in Mode 0  
  * CPOL = 0 --> clock is low when idle 
  * CPHA = 0 --> data is sampled at the first edge 
  */ 
  SPI_InitStruct.SPI_Direction =                SPI_Direction_2Lines_FullDuplex;        // set to full duplex mode, seperate MOSI and MISO lines 
  SPI_InitStruct.SPI_Mode =                     SPI_Mode_Master;                        // transmit in master mode, NSS pin has to be always high 
  SPI_InitStruct.SPI_DataSize =                 SPI_DataSize_8b;                        // one packet of data is 8 bits wide 
  SPI_InitStruct.SPI_CPOL =                     SPI_CPOL_High;                           // clock is low when idle 
  SPI_InitStruct.SPI_CPHA =                     SPI_CPHA_1Edge;                         // data sampled at first edge 
  SPI_InitStruct.SPI_NSS =                      SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high 
  SPI_InitStruct.SPI_BaudRatePrescaler =        SPI_BaudRatePrescaler_64;                // SPI frequency is APB2 frequency / 4 
  SPI_InitStruct.SPI_FirstBit =                 SPI_FirstBit_MSB;                       // data is transmitted MSB first 
  SPI_Init(SPI1, &SPI_InitStruct);  

  SPI_Cmd(SPI1, ENABLE); // enable SPI1 
} 


/* This funtion is used to transmit and receive data  
* with SPI1 
*           data --> data to be transmitted 
*           returns received value 
*/ 
uint8_t SPI1_read(uint8_t data){   
  GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low 

  SPI1->DR = data; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high
  uint8_t ret = SPI1->DR;
  return ret; // return received data from SPI data register 
} 


void SPI1_write(uint8_t address, uint8_t data){ 

  uint16_t comb = (address << 8) | data;
  GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low 

  SPI1->DR = address; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  //while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  SPI1->DR = data; // write data to be transmitted to the SPI data register 
  while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete 
  while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore 

  GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high   
} 

int main(void){ 

  init_SPI1(); 

  while(1){  
    SPI1_read(0x01); 
  } 
} 

我从 MOSI 得到的只是一个随机的 ~1.5V 峰值,它不同步。

【问题讨论】:

  • 用您尝试过的将 MISO 引脚设置为输入的代码更新此内容。
  • 暂缓我所说的关于沟通的内容。 MISO没有回应。芯片不解释来自 MOSI 的命令。 SPI 通信协议出了点问题……使用 Arduino 仍然一切正常。我看到(在示波器上)清晰的响应,一切都按预期工作。
  • 让程序反复做SPI事务,这样即使在模拟示波器上也能得到稳定的画面,拍下片选和时钟的照片,然后是另一个时钟和MOSI数据的第一个字节.
  • 玩过 - 制作了我自己的 SPI 通信协议,它开始工作了......
  • 不确定您是否有任何运气,但您是否尝试过 SPI_CPOL_Low?这和 SX1272 数据中指定的 SPI_CPHA_1Edge 也表明您的时钟不超过 10MHz

标签: c embedded spi stm32f4discovery


【解决方案1】:
/* configure pins used by SPI1 
 * PA5 = SCK 
 * PA6 = MISO 
 * PA7 = MOSI 
 */

这表明您的 MISO(主输入,从属输出)信号在 PA6 上

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5; 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; 
  GPIO_Init(GPIOA, &GPIO_InitStruct); 

但这会将 PA6 配置为 输出

将 PA6 配置为输入,然后重试。如果它仍然不起作用,请尝试通过一个 1K 左右的电阻器在其中注入一个电平,看看您是否可以同时获得改变示波器的电压和接收到的值来反映这一点。

【讨论】:

  • 那为什么备用功能不起作用呢?不应该是从寄存器配置SPI1吗?
  • 您仍然需要配置 I/O 驱动程序的方向,并且您正在将输入引脚配置为输出。当您尝试注入具有弱源的关卡时发生了什么?电压变了吗?收到数据了吗?
【解决方案2】:

您是否尝试过使用 ST 配置工具STM32Cube 来生成初始化和通信接口代码。我用它在大约一个小时内使用 DMA 传输生成时钟设置 USART、I2C 和 SPI 通信接口。它包括 F4 发现板的预定义配置。我所要做的就是在传输加载到 DMA 时清除 CS 线,并在传输完成中断回调函数中重新设置。

【讨论】:

  • 不,我没有。会尝试
猜你喜欢
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2022-01-07
  • 2020-08-31
  • 2013-08-28
  • 2019-08-09
  • 2020-11-26
相关资源
最近更新 更多