You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32L072CZ与MFRC522 SPI通信故障排查求助

问题:STM32L072CZ与MFRC522 SPI通信失败,读写寄存器全返回0

我正在将MFRC522模块与STM32L072CZ MCU连接以实现RFID卡读写功能,参考GitHub项目、Arduino MFRC522库及RC522 datasheet编写了基础驱动,但读写模块寄存器全部失败。调试发现初始化函数无法写入寄存器,读取版本寄存器(手册说明应返回0x90或0x91)、DivIrqReg和TestBusReg均返回0,确定SPI通信存在问题,模块未正确初始化。已排查硬件连接、更换模块,SPI时钟预分频设为8(低于手册要求的10MHz),时钟相位极性配置为CPOL=LOW、CPHA=1EDGE,仍未解决问题,请求帮忙排查。


寄存器读写及初始化代码

寄存器写入函数

void Write_MFRC522(uint8_t addr, uint8_t val)
{
    uint8_t addr_bits = (((addr<<1) & 0x7E));

    /* CS LOW */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

    //The address is located:0XXXXXX0
    HAL_SPI_Transmit(&hspi1, &addr_bits, 1, 500);
    HAL_SPI_Transmit(&hspi1, &val, 1, 500);

    /* CS HIGH */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}

寄存器读取函数

uint8_t Read_MFRC522(uint8_t addr)
{
    uint8_t rx_bits;
    uint8_t addr_bits = (((addr<<1) & 0x7E) | 0x80);

    /* CS LOW */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

    //The address is located:1XXXXXX0
    HAL_SPI_Transmit(&hspi1, &addr_bits, 1, 500);
    HAL_SPI_Receive(&hspi1, &rx_bits, 1, 500);

    /* CS HIGH */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

    return rx_bits;
}

MFRC522初始化函数

void MFRC522_Init(void)
{

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);         // Set RST pin high for normal operation
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);           // Set NSS for SPI

    MFRC522_Reset();

    Write_MFRC522(MifareREG_T_MODE, 0x80); //0x8D);
    Write_MFRC522(MifareREG_T_PRESCALER, 0xA9);
    Write_MFRC522(MifareREG_T_RELOAD_L, 0x03);
    Write_MFRC522(MifareREG_T_RELOAD_H, 0xE8);
    Write_MFRC522(MifareREG_TX_AUTO, 0x40);
    Write_MFRC522(MifareREG_MODE, 0x3D);    

    AntennaOn();
}

SPI配置代码

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_8;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA4     ------> SPI1_NSS (Software Managed)
    PA5     ------> SPI1_SCK
    PA11     ------> SPI1_MISO
    PA12     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    // GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

    // Configure the NSS pin (PA4) as a GPIO output.
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // Configure MISO to be input
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

主函数代码

#include "main.h"
#include "gpio.h"

#include "mfrc_522.h"
#include <stdio.h>
#include <string.h>

char str1[17]={'\0'};
char str2[17]={'\0'};

int main(void)
{
    unsigned char status;

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();

  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);      // RST pin
  HAL_Delay(100);
  MFRC522_Init();
  //HAL_Delay(1000);

  status = Read_MFRC522(MifareREG_DIV_IRQ);
  status = Read_MFRC522(MifareREG_TEST_BUS);
  status = Read_MFRC522(MifareREG_VERSION);

  while (1)
  {

  }
}

排查建议

  1. 补全GPIO复用配置:在HAL_SPI_MspInit中,PA5(SCK)和PA12(MOSI)的复用功能被注释,STM32L072的SPI1引脚复用为AF0,必须启用这行代码:

    GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
    

    未设置复用功能时,引脚仅为普通GPIO,无法传输SPI信号。

  2. 优化MISO引脚配置:MISO引脚建议设置上拉电阻,避免模块未通信时引脚处于高阻态导致读取随机电平:

    GPIO_InitStruct.Pull = GPIO_PULLUP;
    
  3. 尝试修改SPI时序模式:部分MFRC522模块可能需要SPI_MODE3(CPOL=HIGH、CPHA=2EDGE),修改配置测试:

    hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
    hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
    
  4. 调整CS信号时序:在拉低/拉高CS前后添加短暂延时,保证信号建立/保持时间:

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    HAL_Delay(1); // 增加建立时间
    // SPI传输代码
    HAL_Delay(1); // 增加保持时间
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    
  5. 检查SPI传输返回值:添加HAL_SPI_Transmit/HAL_SPI_Receive的返回值判断,确认SPI硬件是否正常工作:

    if(HAL_SPI_Transmit(&hspi1, &addr_bits, 1, 500) != HAL_OK) {
        Error_Handler();
    }
    
  6. 验证复位流程:确认RST引脚配置为推挽输出,初始化后读取引脚电平,确保复位操作生效。

内容的提问来源于stack exchange,提问作者Shahab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:29:55