在 STM32 MCU 上使用低电平 (LL) api 通过 SPI 读取可变长度消息
Read variable length messages over SPI using Low Level (LL) api on STM32 MCU
我的系统由一块STM32NUCLEO板和一个通过SPI连接的从设备组成。从设备发送可变长度的命令:可能的长度为 4、8、10、14 位。
我正在尝试使用 LL API 和中断检测我的 nucleo 板上的这些消息。
我目前正在研究的解决方案是基于将 SPI 设置为 4 位数据宽度 (SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_4BIT)然后计算我收到的字数(1 个字 = 4 位)。这样,如果我收到 1 个字,则意味着我收到了一个 4 位命令,2 个字 --> 8 位命令。如果我收到了3个字,那应该意味着我收到了一个10bit的命令(应该丢弃2bit),以此类推。
不幸的是,我注意到 LL API 提供的函数一次只能读取 8 位或 16 位,目前我在接收 4 位命令时遇到问题,因为函数 LL_SPI_ReceiveData8 期望接收 8 位。
这是我对 IRQ 处理程序和回调的实现:
IRQ 处理程序:
void SPI1_IRQHandler(void)
{
/* Check RXNE flag value in ISR register */
if(LL_SPI_IsActiveFlag_RXNE(SPI1))
{
/* Call function Slave Reception Callback */
SPI1_Rx_Callback();
}
/* Check STOP flag value in ISR register */
else if(LL_SPI_IsActiveFlag_OVR(SPI1))
{
/* Call Error function */
SPI1_TransferError_Callback();
}
}
回调
void SPI1_Rx_Callback(void)
{
/* Read character in Data register.
RXNE flag is cleared by reading data in DR register */
aRxBuffer[ubReceiveIndex++] = LL_SPI_ReceiveData8(SPI1);
}
正如我之前所说,问题似乎是我正在使用 LL_SPI_ReceiveData8 函数来读取,因为我找不到 LL_SPI_ReceiveData4.
你有什么建议吗?
此外,是否可以将 SPI 设置为使用 2 位数据宽度而不是 4 位?像 SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_2BIT 这样的东西:这样应该更容易检测命令,因为 4、8、10 和 14 是 2 的倍数。
谢谢。
最小可寻址数据块为字节。因此,即使您收到 4 位,读取的值也是 8 位。
顺便说一句,这个具有不同字长的秘密从属设备是什么?
关于所用控制器的新信息:
支持4到16位的SPI数据传输长度。所以你的拳头尝试似乎还不错。
你的"problem"是没有4位读取功能。这是由始终包含 16 位但只有 4 位有效数据的接收数据寄存器引起的。其他位为“0”。
你的回调函数
aRxBuffer[ubReceiveIndex++] = LL_SPI_ReceiveData8(SPI1);
会将值从 0..15 写入 aRxBuffer 而你不需要
ReceiveData4() 得到你的答案:-)
STM32L4 系列的参考手册 Reference Manual 第 1193ff 页也是如此。
我的系统由一块STM32NUCLEO板和一个通过SPI连接的从设备组成。从设备发送可变长度的命令:可能的长度为 4、8、10、14 位。
我正在尝试使用 LL API 和中断检测我的 nucleo 板上的这些消息。
我目前正在研究的解决方案是基于将 SPI 设置为 4 位数据宽度 (SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_4BIT)然后计算我收到的字数(1 个字 = 4 位)。这样,如果我收到 1 个字,则意味着我收到了一个 4 位命令,2 个字 --> 8 位命令。如果我收到了3个字,那应该意味着我收到了一个10bit的命令(应该丢弃2bit),以此类推。
不幸的是,我注意到 LL API 提供的函数一次只能读取 8 位或 16 位,目前我在接收 4 位命令时遇到问题,因为函数 LL_SPI_ReceiveData8 期望接收 8 位。
这是我对 IRQ 处理程序和回调的实现:
IRQ 处理程序:
void SPI1_IRQHandler(void)
{
/* Check RXNE flag value in ISR register */
if(LL_SPI_IsActiveFlag_RXNE(SPI1))
{
/* Call function Slave Reception Callback */
SPI1_Rx_Callback();
}
/* Check STOP flag value in ISR register */
else if(LL_SPI_IsActiveFlag_OVR(SPI1))
{
/* Call Error function */
SPI1_TransferError_Callback();
}
}
回调
void SPI1_Rx_Callback(void)
{
/* Read character in Data register.
RXNE flag is cleared by reading data in DR register */
aRxBuffer[ubReceiveIndex++] = LL_SPI_ReceiveData8(SPI1);
}
正如我之前所说,问题似乎是我正在使用 LL_SPI_ReceiveData8 函数来读取,因为我找不到 LL_SPI_ReceiveData4.
你有什么建议吗?
此外,是否可以将 SPI 设置为使用 2 位数据宽度而不是 4 位?像 SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_2BIT 这样的东西:这样应该更容易检测命令,因为 4、8、10 和 14 是 2 的倍数。
谢谢。
最小可寻址数据块为字节。因此,即使您收到 4 位,读取的值也是 8 位。
顺便说一句,这个具有不同字长的秘密从属设备是什么?
关于所用控制器的新信息:
支持4到16位的SPI数据传输长度。所以你的拳头尝试似乎还不错。
你的"problem"是没有4位读取功能。这是由始终包含 16 位但只有 4 位有效数据的接收数据寄存器引起的。其他位为“0”。
你的回调函数
aRxBuffer[ubReceiveIndex++] = LL_SPI_ReceiveData8(SPI1);
会将值从 0..15 写入 aRxBuffer 而你不需要 ReceiveData4() 得到你的答案:-)
STM32L4 系列的参考手册 Reference Manual 第 1193ff 页也是如此。