C语言 STM32L4 SPI指针相关问题



我有一个STM32L476RG的问题。我有两个相互关联的问题。我有一个可行的解决方案,我只是想知道它是如何工作的。

我有一个问题写数据到SPIx_DR寄存器。我的代码如下:

void SPI_SendData(SPI_RegDef_t *pSPIx, uint8_t *pTxBuffer, uint32_t Len)
{
    while(Len > 0)
    {
        //1. wait until TXE is set
        while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG)  == FLAG_RESET);
 
        //8 bit DS
        //1. load the data in to the DR
        *((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer; //typecasting to uint8_t
        Len--;
        pTxBuffer++;
    }
}

上面的代码是完美的工作。然而,我有问题,理解以下行:

*((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer;

据我所知STM32L4系列不同于STM32F4系列。我有一个STM32F4工作代码,它是不同的:

pSPIx->DR = *pTxBuffer;

当我为STM32L4这样写时,无论如何它都会发送16位而不是8位。区别在于,SPIx_DR对写入它的数据的宽度很敏感。然而,我不知道如何理解它,并从参考手册(RM0351)阅读它。它是写在参考手册RM0351页1463(数据包装)?

我的问题是:

  1. STM32L4对写入数据的宽度敏感,在哪里可以读到它(参考手册中的页面)是正确的吗?欢迎所有进一步的解释。我在参考手册里找不到。

  2. 这个问题是关于C语法的。如何理解以下转换(以SPI2为例):

*((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer;

pSPIx->DR = *(0x4000380C) (SPI2_DR地址= 0x4000380C).

所以它应该等于:

*((volatile uint8_t *)0x4000380C) = *pTxBuffer;

如何理解第一部分*((volatile uint8_t *)0x4000380C) ?

希望有人能帮我澄清这个话题。谢谢你的宝贵时间。

编辑(添加逻辑分析仪图片使我的问题更清楚):

我试着再描述一遍我的问题。

当我使用STM32L476RG发送SPI数据时:

void SPI_SendData(SPI_RegDef_t *pSPIx, uint8_t *pTxBuffer, uint32_t Len)
{
    while(Len > 0)
    {
        //1. wait until TXE is set
        while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG)  == FLAG_RESET);
        //8 bit DS
        //1. load the data in to the DR
        *((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer; //typecasting to uint8_t
        Len--;
        pTxBuffer++;
    }
}

现在我发送"Hello World"为例。我一次发送8位。如你所见,*pTxBuffer被写成uint8_t。

输出如下(正确):

8 bits_1

8 bits_2

现在当我使用这个函数发送SPI数据与STM32L476RG:

void SPI_SendData(SPI_RegDef_t *pSPIx, uint8_t *pTxBuffer, uint32_t Len)
{
    while(Len > 0)
    {
        //1. wait until TXE is set
        while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG)  == FLAG_RESET);
        //8 bit DS
        //1. load the data in to the DR
        pSPIx->DR = *pTxBuffer; //typecasting to uint8_t
        Len--;
        pTxBuffer++;
    }
}

输出如下(错误):

16 bits_1

16 bits_2

现在你可以看到区别了。问题是底层代码理论上应该可以工作。它在STM32F407上工作得很好。现在STM32F407和STM32L476在SPI方面有什么区别?我认为答案依赖于STM32L476参考手册RM0351页1463(数据打包)?

拆解

*((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer;

 uint8_t * temp1 = &pSPIx->DR;

然后

 volatile uint8_t *temp2 = temp1;

然后

 *temp2 = *pTxBuffer;
这些诡计的目的是强制执行写操作,它告诉编译器必须将该值写入指定的位置。编译器可以决定不这样做,例如,它已经在几行之前写了相同的值。'volatile'对编译器说——真的要写这个,因为它背后有特殊的硬件。

几乎和

一样
 pSPIx->DR = *pTxBuffer;

但它没有'volatile'限定符,所以编译器可以选择不这样做(或移动顺序)

最新更新