在 STM32 中格式化数据以通过 HAL SPI 发送的正确方法是什么?
What is the correct way to format data to send by HAL SPI in STM32?
我正在尝试 read/write 来自 ST EEPROM M95640-W 的数据
根据数据表,读取操作数据命令的格式必须如下:
首先是8位指令"Read from Memory Array":0x03 (B00000011)
第二个是16位地址。
但是当我发送命令和数据时,我得到了这个:
地址 0x0001 (B00000001):
并且只是用镜像位检查数据位置
地址 0x0081 (B10000001):
所以我在我的代码中找不到错误,为什么它以不正确的方式发送数据。它发送 0x20 命令,除了 0x03。它发送 0x48 地址,除了 0x01 和 0x80 除了 0x81.看起来我在类型 uint16_t -> uint8_t*.
之间的数据转换不正确
代码如下:
#define EEPROM_SPI hspi1
#define EEPROM_READ 0x03 // Read from Memory Array
/**
* @brief Reads a block of data from the EEPROM.
* @param pBuffer: pointer to the buffer that receives the data read from the EEPROM.
* @param ReadAddr: EEPROM's internal address to read from.
* @param NumByteToRead: number of bytes to read from the EEPROM.
* @retval None
*/
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
EEPROM_SendInstruction((uint8_t*)EEPROM_READ, 1);
/*!< Send WriteAddr address byte to read from */
EEPROM_SendInstruction((uint8_t*)ReadAddr, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}
void EEPROM_SendInstruction(uint8_t *instruction, uint8_t size) {
while (EEPROM_SPI.State == HAL_SPI_STATE_RESET) {
osDelay(1);
}
if (HAL_SPI_Transmit_DMA(&EEPROM_SPI, (uint8_t*)instruction, (uint16_t)size) != HAL_OK) {
Error_Handler();
}
}
SPI初始化:
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_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}
UPD1: 我像@Guillaume Michel 说的那样做了数据包并且它有效:
UPD2 我在 Github 发布了库,写入和读取数据功能齐全。欢迎帮助查看代码并添加一些新功能。
您的代码似乎不是为使用 DMA 而编写的,所以不要使用它。尝试使用 HAL_SPI_Receive
和 HAL_SPI_Transmit
而不是 HAL_SPI_Receive_DMA
和 HAL_SPI_Transmit_DMA
。
极性和相位似乎没问题,但请仔细检查。
我不确定你叫EEPROM_SendInstruction
的方式是否正确。试试这个:
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
uint8_t tmpBuf[2];
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
tmpBuf[0] = EEPROM_READ;
EEPROM_SendInstruction(tmpBuf, 1);
/*!< Send WriteAddr address byte to read from */
tmpBuf[0] = (uint8_t)(ReadAddr<<8);
tmpBuf[1] = (uint8_t)ReadAddr;
EEPROM_SendInstruction(tmpBuf, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}
我正在尝试 read/write 来自 ST EEPROM M95640-W 的数据
根据数据表,读取操作数据命令的格式必须如下:
首先是8位指令"Read from Memory Array":0x03 (B00000011)
第二个是16位地址。
但是当我发送命令和数据时,我得到了这个:
地址 0x0001 (B00000001):
并且只是用镜像位检查数据位置
地址 0x0081 (B10000001):
所以我在我的代码中找不到错误,为什么它以不正确的方式发送数据。它发送 0x20 命令,除了 0x03。它发送 0x48 地址,除了 0x01 和 0x80 除了 0x81.看起来我在类型 uint16_t -> uint8_t*.
之间的数据转换不正确代码如下:
#define EEPROM_SPI hspi1
#define EEPROM_READ 0x03 // Read from Memory Array
/**
* @brief Reads a block of data from the EEPROM.
* @param pBuffer: pointer to the buffer that receives the data read from the EEPROM.
* @param ReadAddr: EEPROM's internal address to read from.
* @param NumByteToRead: number of bytes to read from the EEPROM.
* @retval None
*/
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
EEPROM_SendInstruction((uint8_t*)EEPROM_READ, 1);
/*!< Send WriteAddr address byte to read from */
EEPROM_SendInstruction((uint8_t*)ReadAddr, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}
void EEPROM_SendInstruction(uint8_t *instruction, uint8_t size) {
while (EEPROM_SPI.State == HAL_SPI_STATE_RESET) {
osDelay(1);
}
if (HAL_SPI_Transmit_DMA(&EEPROM_SPI, (uint8_t*)instruction, (uint16_t)size) != HAL_OK) {
Error_Handler();
}
}
SPI初始化:
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_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}
UPD1: 我像@Guillaume Michel 说的那样做了数据包并且它有效:
UPD2 我在 Github 发布了库,写入和读取数据功能齐全。欢迎帮助查看代码并添加一些新功能。
您的代码似乎不是为使用 DMA 而编写的,所以不要使用它。尝试使用 HAL_SPI_Receive
和 HAL_SPI_Transmit
而不是 HAL_SPI_Receive_DMA
和 HAL_SPI_Transmit_DMA
。
极性和相位似乎没问题,但请仔细检查。
我不确定你叫EEPROM_SendInstruction
的方式是否正确。试试这个:
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
uint8_t tmpBuf[2];
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
tmpBuf[0] = EEPROM_READ;
EEPROM_SendInstruction(tmpBuf, 1);
/*!< Send WriteAddr address byte to read from */
tmpBuf[0] = (uint8_t)(ReadAddr<<8);
tmpBuf[1] = (uint8_t)ReadAddr;
EEPROM_SendInstruction(tmpBuf, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}