0

我正在使用 W25Q16 研究 STM32L432KC。每次我得到0xFF. 根据数据表,要获得芯片制造商代码,我需要发送0x903 个虚拟字节。芯片应该返回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 
    {
    }   
}

我该如何解决?

示意图

4

2 回答 2

0

这可能对某人有用。

我在使用连接到 SPI 引脚的数据记录器的开发板上从 W25qXX 读取数据时遇到问题。即使在慢速 SPI 时钟(SCLK < 1MHz)上,数据有时也会读取不正确。通过断开数据记录器解决了问题(我的数据记录器有大约 10 厘米长的电线)。

于 2021-12-12T09:37:38.143 回答
0

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

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

  • 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(从低开始,如果需要,稍后增加))。检查数据表,有时反复试验也可以解决问题。

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

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

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

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

于 2020-09-02T23:16:07.230 回答