XXXVip 发表于 2025-2-25 16:38

N32G435单片机读取异常

各位大佬帮忙看看是啥问题。
原本SPI寄存器中的数据长度设置的16位,读取从机寄存器8位数据没有问题。因为要读取从机寄存器的24位数据,故将数据长度设置为8位,但读取的8位数据都变成了0或者FF,示波器抓取了MISO上的波形与应该读取到的数值一样,但从SPI数据寄存器中读的值就不对。
原本数据长度设置为16位时的发送函数:
/*********************************************
函数: void SPI_WriteByte(uint16_t data)
描述: SPI写数据.
参数: none
返回: none
版本: V1.0, 2025-1-8
**********************************************/
void SPI_WriteByte(uint16_t data)
{
   /* Wait for SPI1 Tx buffer empty */
   while (SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET)
         ;
   
   /* Check the parameters */
    assert_param(IS_SPI_PERIPH(SPI1));

    /* Write in the DAT register the data to be sent */
    SPI1->DAT = data;
   
    /* 等待发送完成 */
   while (SPI_I2S_GetStatus(SPI1, SPI_I2S_BUSY_FLAG) == SET)
         ;
}

设置为8位的发送函数:
/*********************************************
函数: void SPI_WriteByte(uint16_t data)
描述: SPI写数据.
参数: none
返回: none
版本: V1.0, 2025-1-8
**********************************************/
void SPI_WriteByte(uint16_t data)
{
    uint8_t byte1,byte2;
    byte1 = (data >> 8) & 0xFF;
    byte2 = data & 0xFF;
   /* Wait for SPI1 Tx buffer empty */
   while (SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET)
         ;
   
   /* Check the parameters */
    assert_param(IS_SPI_PERIPH(SPI1));

    /* Write in the DAT register the data to be sent */
    SPI1->DAT = byte1;
   
   while (SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET)
         ;
   /* Check the parameters */
    assert_param(IS_SPI_PERIPH(SPI1));
   
   SPI1->DAT = byte2;
   
    /* 等待发送完成 */
   while (SPI_I2S_GetStatus(SPI1, SPI_I2S_BUSY_FLAG) == SET)
         ;
}

SPI读函数用的是官方例程中的,数据8位或16位都用的这个:
/*********************************************
函数: uint8_t SPI_ReadByte(uint8_t addr)
描述: SPI读寄存器数据.
参数: none
返回: none
版本: V1.0, 2025-1-8
**********************************************/
uint8_t SPI_ReadByte(void)
{
    while (SPI_I2S_GetStatus(SPI1, SPI_I2S_RNE_FLAG) == RESET)
         ;
    /* Check the parameters */
    assert_param(IS_SPI_PERIPH(SPI1));

    /* Return the data in the DAT register */
    return SPI1->DAT;
}

从机数据读取函数:
/*********************************************
函数: uint8_tTDC7200_ReadByte(uint8_t addr)
描述: TDC7200读寄存器.
参数: none
返回: none
版本: V1.0, 2025-1-8
**********************************************/
uint8_tTDC7200_ReadByte(uint8_t addr)
{
    uint8_t Rd_Data;
    uint16_t addr_data;
    SPI_CS_L_TDC7200();
    addr_data = ((0x80 | addr) << 8) | Data_Buf;
    SPI_WriteByte(addr_data);
    Rd_Data = SPI_ReadByte();
    SPI_CS_H_TDC7200();
    return Rd_Data;
   
}

XXXVip 发表于 2025-2-25 16:44

读从机数据,需要发8位命令和8位的空数据,数据长度设置16位,和数据长度设置8位,发送接收的波形都正常,但设置8位时接收的数据就不对
%E6%81%92%E7%94%9F%E7%A7%91%E6%8A%80%E5%9B%AD

suncat0504 发表于 2025-2-25 23:08

时序上匹配没?可以通过逻辑分析仪的波形改程序,在时序上保持一致就应该没问题。另外一点注意SPI的设置,避免设置错误,导致数据丢失。比如时钟信号的极性、第几个脉冲沿之类的设置。

flycamelaaa 发表于 2025-2-26 16:30

SPI配置不一致,当你将SPI的数据长度从16位更改为8位时,SPI的配置也相应地进行更改。

powerantone 发表于 2025-2-26 17:00

发送和接收不匹配?

cooldog123pp 发表于 2025-2-26 17:14

貌似3楼说的是对的,SPI配置不一致,当你将SPI的数据长度从16位更改为8位时,SPI的配置也相应地进行更改。

stormwind123 发表于 2025-2-26 18:00

保持SPI配置为16位,但修改发送函数以只发送必要的字节

probedog 发表于 2025-2-26 19:00

在接收端,如果需要24位数据,则分三次调用SPI_ReadByte函数,并将结果组合成一个24位的值。

classroom 发表于 2025-2-26 20:00

如果更改SPI配置为8位是必需的,SPI初始化函数中的数据帧大小也要设置为8位,并相应地调整发送和接收逻辑。

地瓜patch 发表于 2025-2-27 08:55

接受端程序配置存在问题

地瓜patch 发表于 2025-2-27 08:56

probedog 发表于 2025-2-26 19:00
在接收端,如果需要24位数据,则分三次调用SPI_ReadByte函数,并将结果组合成一个24位的值。 ...

分拆为3个字节读取了

lix1yr 发表于 2025-3-4 16:32

当 SPI 数据长度从 16 位改为 8 位时,SPI 数据寄存器(DAT)的读写方式需要相应调整。

cen9ce 发表于 2025-3-4 17:41

如果寄存器配置不正确,可能导致读取的数据为 0 或 0xFF

zhizia4f 发表于 2025-3-4 18:30

确保 SPI 控制寄存器(CTL)中的数据长度配置已正确设置为 8 位。检查 SPI 初始化代码,确认数据长度配置已更新。

b5z1giu 发表于 2025-3-4 19:47

在 8 位模式下,SPI 数据寄存器(DAT)应按照 8 位方式进行读写。如果仍然按照 16 位方式读写,可能导致数据错位或读取异常

q1ngt12 发表于 2025-3-4 21:14

SPI 的时钟极性和相位配置需要与从设备一致。如果配置不匹配,可能导致数据读取错误。

y1n9an 发表于 2025-3-4 23:36

一般来说,在8位模式下,发送和接收的时序需要与从设备匹配。如果时序不正确,可能导致数据读取错误

suw12q 发表于 2025-3-5 09:10

建议查查硬件,使用示波器检查 SPI 的时钟(SCLK)、数据(MOSI 和 MISO)和片选(CS)信号,确保时序正确。调整 SPI 的时钟频率,确保从设备能够正确响应。

q1d0mnx 发表于 2025-3-5 12:51

我觉得如果在8位模式下,SPI 接收缓冲区的数据可能需要及时读取,否则可能被覆盖。

lamanius 发表于 2025-3-5 14:27

一般SPI的时候,其实需要在每次发送数据后,及时读取接收缓冲区的数据。确保在读取数据时,SPI 接收缓冲区非空标志(RNE)已置位。
页: [1]
查看完整版本: N32G435单片机读取异常