【问题标题】:stm32 and external flash W25q16stm32和外置闪存W25q16
【发布时间】:2020-12-21 14:13:40
【问题描述】:

我正在开发带有 W25Q16 的 STM32L432KC。每次我收到0xFF。根据数据表,要获得芯片制造商代码,我需要发送0x90 和 3 个虚拟字节。芯片应返回0xEF0x17。但是,出于某种原因,我收到了 2 个字节的 0xFF

SPI_HandleTypeDef hspi1;

static void MX_SPI1_Init(void)
{
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

#define SPI_SEL2_Pin GPIO_PIN_15
#define SPI_SEL2_GPIO_Port GPIOA
#define ChipSelect()            HAL_GPIO_WritePin(SPI_SEL2_GPIO_Port, SPI_SEL2_Pin, GPIO_PIN_RESET)
#define ChipDeselect()          HAL_GPIO_WritePin(SPI_SEL2_GPIO_Port, SPI_SEL2_Pin, GPIO_PIN_SET)

#define COMMAND_IDENTIFICATION 0x90

uint8_t buffer_tx[4];
uint8_t buffer_rx[2];

uint16_t GetIdentification()
{
    buffer_tx[0] = COMMAND_IDENTIFICATION;
    buffer_tx[1] = 0x0;
    buffer_tx[2] = 0x0;
    buffer_tx[3] = 0x0;

    ChipSelect();
    HAL_SPI_Transmit(&hspi1, buffer_tx, 4, 1000); // send 0x90, 0x0, 0x0, 0x0
    HAL_SPI_Receive(&hspi1, buffer_rx, 2, 1000); // receive 0xFF, 0xFF 
    ChipDeselect();
    return ((uint8_t)buffer_rx[0] << 8) | (uint8_t)buffer_rx[1];
}

int main(void)
{
    MX_SPI1_Init();
    HAL_Delay(1000);
    uint16_t id = GetIdentification();
    printf("Manufacturer ID: 0x%.4X\r\n", id);
    while 
    {
    }   
}

我该如何解决?

【问题讨论】:

  • 您的初始化调用是否在其他地方定义?你在哪里打电话HAL_Init()?或MX_GPIO_Init()?
  • 是的,我已经做到了。

标签: stm32 spi flash-memory stm32cubemx


【解决方案1】:

如果无法访问您的硬件设置,就很难知道出了什么问题。看起来您走在正确的轨道上,只需坚持并检查所有可能的错误来源,然后将问题缩小到简单且可测试的范围内。并先找出是否可能是硬件问题,然后尝试修复软件。

一些提示,可能会有所帮助:

  • SPI 数据线上的 0xFF(本例中为 DO/MISO)可能意味着它始终处于高电平状态。所以闪存 IC 不响应您的命令。在处理驱动程序时,它可以帮助使用逻辑分析仪、示波器或类似设备进行验证。如果可能,还要检查预期的数据位是否在 MOSI 引脚上可见。 CLK可见吗?

  • 用万用表检查所有引脚电压。测量值看起来像预期的那样吗? (/HOLD 引脚?)

  • 用于片选 (PA15) 的 GPIO 引脚是否配置为输出引脚? (也可以在STM32CubeMX配置器软件中完成。)

    /* configure /CS pin to be an output pin */
    GPIO_InitTypeDef init = {0};
    init.Pin = SPI_SEL2_Pin;
    init.Speed = GPIO_SPEED_FREQ_LOW;
    init.Mode = GPIO_MODE_OUTPUT_PP;
    init.Pull = GPIO_NOPULL;
    if (HAL_GPIO_Init(SPI_SEL2_GPIO_Port, &init) != HAL_OK) {
        Error_Handler();
    }
    ChipDeselect();
    HAL_Delay(100);
  • 是否正确配置了 SPI 外设? c检查 SPI 时钟极性和相位(即 hspi1.Init.CLKPolarity 和 hspi1.Init.CLKPhase)、位顺序(即 hspi1.Init.FirstBit(MSB/LSB 在前))和时钟速度(即 hspi1.Init. BaudRatePrescaler(从低开始,如果需要,稍后增加))。检查datasheet,有时试错也可以解决问题。

  • 闪存芯片可能处于断电状态。 - 快速浏览数据表后,似乎有一个指令号为0xAB0x90 的替代命令,称为“Release Power-down / Device ID”(参见数据表中的第 9.3.7 节) )。 - 请注意,当以“简短形式”使用时,该指令只会唤醒芯片,引用数据表:

要使器件从掉电状态中释放,通过将 /CS 引脚驱动为低电平、移位指令代码“ABh”并将 /CS 驱动为高电平来发出指令,如图 38a 所示。

  • 在网上搜索,并尝试找到类似的驱动程序作为参考。这些华邦闪存 IC 很常见。一旦您弄清楚如何从闪存中读取制造商 ID,就可以更轻松地将其他命令/功能集成到驱动程序中,按照数据表一步一步进行操作。 (另请阅读关于状态和配置寄存器的部分(第 7 章),稍后可能需要在写操作期间轮询状态位。)将事情拆分成小函数,可以单独测试......

  • HAL_SPI_TransmitReceive() 可用于一次性发送和接收数据。

【讨论】:

    【解决方案2】:

    这可能对某人有用。

    我在使用连接到 SPI 引脚的数据记录器的开发板上从 W25qXX 读取数据时遇到问题。即使在慢速 SPI 时钟(SCLK

    【讨论】:

      猜你喜欢
      • 2021-09-23
      • 2019-03-17
      • 2021-06-19
      • 2021-09-10
      • 2021-03-10
      • 1970-01-01
      • 2020-03-11
      • 2022-09-28
      • 2020-01-30
      相关资源
      最近更新 更多