使用指针读取 SPI Eeprom 不起作用,但在不使用指针时有效
Read SPI Eeprom using a pointer does not work but works when not using a pointer
我是编程新手,我正在尝试从 SPI Eeprom 中读取一页(64 字节),并且在读取数组时它开始工作[67](3 个传输字节以通过 SPI + 启动读取过程64 字节数据)。
我正在使用 IAR Workbench 在 STM32L475 上工作。
当我尝试使用指针时它不起作用,这可能是初学者犯的一个愚蠢的错误,但我很感激一些帮助来解决这个问题。
我正在使用这样的联合(我知道我在浪费内存,但为了测试它是这样的):
//Production Data union
union Production_Data_union
{
struct
{
uint8_t Dummy_Array[3];
char Xxxx_Sn[16];
char Yyyy_Sn[16];
char Prod_Date[8];
char Firmware_Ver[8];
};
uint8_t Eeprom_Page0_Buffer[67];
};
union Production_Data_union Prod_Data;
uint8_t *Eeprom_Page0_Ptr;
uint8_t Read_Cmd[3] = {0x03, 0x00, 0x00};
uint8_t Buff[67];
uint8_t Eeprom_Page_Size = 64;
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No);
我的主要是这样的:
Eeprom_Page0_Ptr = (uint8_t*)&Prod_Data.Eeprom_Page0_Buffer;
Eeprom_Page_Read(Eeprom_Page0_Ptr, 0);
Eeprom_Page_Read函数:
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No)
{
uint16_t Address;
Address = Page_No * Eeprom_Page_Size;
Read_Cmd[2] = Address & 0xFF;
Read_Cmd[1] = (Address >> 8) & 0xFF;
//Send READ command to Eeprom
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)&Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
Error_Handler();
}
printf("Prod_Data:\n - Xxxx SN %s\n - Yyyy SN %s\n - Prod date %s - Firmware %s\n - Cmd - %d - %d - %d\n",
Prod_Data.Xxxx_Sn,
Prod_Data.Yyyy_Sn,
Prod_Data.Prod_Date,
Prod_Data.Firmware_Ver,
Read_Cmd[0],
Read_Cmd[1],
Read_Cmd[2]);
//Wait for SPI transfer to complete
while (HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)
{
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
Read_E2prom = 0;
}
我知道 Eeprom 的内容没问题,如果我在 HAL_SPI_TransmitReceive(...) 调用中将“&Data”替换为“Buff”(Array[67]),我可以读取它。
指针值是结构体的起始地址(0x20000090)。
因此寻址 a.s.o。应该没问题,但使用指针时结构为空。
我最感兴趣的是为什么这不起作用以及对此的修复,而不是像“你为什么不这样做,而不是这样,我想知道我做错了什么导致这个”这样的评论我相信这种方法应该有效。
请记住我是编程新手,所以请解释一下 "for Dummies"。
好的,解决了一天左右,我终于找到了错误,它不应该是 &Data 而应该是 Data 所以它必须是这样的:
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}
我不知道为什么会这样?
I am not sure why that is ?
函数HAL_SPI_TransmitReceive
需要一个指针来知道在哪里存储它接收到的数据。它本质上想要一个地址,用于放置字节。在你的情况下,根据 line
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No){...}
Data
已经是一个指针,因为它用 *
表示。这意味着 Data
是一个指向某处 uint8_t
number/array 的指针。那个地方就是您希望 SPI 写入的地方。
当您添加 &
时,您基本上为 SPI 提供了指针 指向要写入的 指针。所以 SPI 正在将接收到的数据 写到指针 上,而不是指针指向的地方?
如果这没有意义,请再问我一次。很难解释。
更新:
This is as I understand it, not a pointer but an array?
编译器只把它看作一个指针。在您的情况下,指针恰好指向一个数组,但它可能指向内存中的任何地方(几乎)。我恳请您更愿意根据指向数组第一个元素的指针 (*ptr==array[0]
) 来思考,而不是根据数组来思考。
Is it somehow implicit so the compiler knows what I want to do so it just accepts and compiles correctly?
我不确定编译器是否应该编译成功。但是你不应该依赖它。它经常发生在可以发送指针的指针(**ptr
)的地方,所以编译器只是假设你知道你在做什么。所以你必须非常注意你如何使用你的指针。
我是编程新手,我正在尝试从 SPI Eeprom 中读取一页(64 字节),并且在读取数组时它开始工作[67](3 个传输字节以通过 SPI + 启动读取过程64 字节数据)。
我正在使用 IAR Workbench 在 STM32L475 上工作。
当我尝试使用指针时它不起作用,这可能是初学者犯的一个愚蠢的错误,但我很感激一些帮助来解决这个问题。
我正在使用这样的联合(我知道我在浪费内存,但为了测试它是这样的):
//Production Data union
union Production_Data_union
{
struct
{
uint8_t Dummy_Array[3];
char Xxxx_Sn[16];
char Yyyy_Sn[16];
char Prod_Date[8];
char Firmware_Ver[8];
};
uint8_t Eeprom_Page0_Buffer[67];
};
union Production_Data_union Prod_Data;
uint8_t *Eeprom_Page0_Ptr;
uint8_t Read_Cmd[3] = {0x03, 0x00, 0x00};
uint8_t Buff[67];
uint8_t Eeprom_Page_Size = 64;
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No);
我的主要是这样的:
Eeprom_Page0_Ptr = (uint8_t*)&Prod_Data.Eeprom_Page0_Buffer;
Eeprom_Page_Read(Eeprom_Page0_Ptr, 0);
Eeprom_Page_Read函数:
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No)
{
uint16_t Address;
Address = Page_No * Eeprom_Page_Size;
Read_Cmd[2] = Address & 0xFF;
Read_Cmd[1] = (Address >> 8) & 0xFF;
//Send READ command to Eeprom
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)&Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
Error_Handler();
}
printf("Prod_Data:\n - Xxxx SN %s\n - Yyyy SN %s\n - Prod date %s - Firmware %s\n - Cmd - %d - %d - %d\n",
Prod_Data.Xxxx_Sn,
Prod_Data.Yyyy_Sn,
Prod_Data.Prod_Date,
Prod_Data.Firmware_Ver,
Read_Cmd[0],
Read_Cmd[1],
Read_Cmd[2]);
//Wait for SPI transfer to complete
while (HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)
{
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
Read_E2prom = 0;
}
我知道 Eeprom 的内容没问题,如果我在 HAL_SPI_TransmitReceive(...) 调用中将“&Data”替换为“Buff”(Array[67]),我可以读取它。
指针值是结构体的起始地址(0x20000090)。 因此寻址 a.s.o。应该没问题,但使用指针时结构为空。
我最感兴趣的是为什么这不起作用以及对此的修复,而不是像“你为什么不这样做,而不是这样,我想知道我做错了什么导致这个”这样的评论我相信这种方法应该有效。
请记住我是编程新手,所以请解释一下 "for Dummies"。
好的,解决了一天左右,我终于找到了错误,它不应该是 &Data 而应该是 Data 所以它必须是这样的:
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}
我不知道为什么会这样?
I am not sure why that is ?
函数HAL_SPI_TransmitReceive
需要一个指针来知道在哪里存储它接收到的数据。它本质上想要一个地址,用于放置字节。在你的情况下,根据 line
void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No){...}
Data
已经是一个指针,因为它用 *
表示。这意味着 Data
是一个指向某处 uint8_t
number/array 的指针。那个地方就是您希望 SPI 写入的地方。
当您添加 &
时,您基本上为 SPI 提供了指针 指向要写入的 指针。所以 SPI 正在将接收到的数据 写到指针 上,而不是指针指向的地方?
如果这没有意义,请再问我一次。很难解释。
更新:
This is as I understand it, not a pointer but an array?
编译器只把它看作一个指针。在您的情况下,指针恰好指向一个数组,但它可能指向内存中的任何地方(几乎)。我恳请您更愿意根据指向数组第一个元素的指针 (*ptr==array[0]
) 来思考,而不是根据数组来思考。
Is it somehow implicit so the compiler knows what I want to do so it just accepts and compiles correctly?
我不确定编译器是否应该编译成功。但是你不应该依赖它。它经常发生在可以发送指针的指针(**ptr
)的地方,所以编译器只是假设你知道你在做什么。所以你必须非常注意你如何使用你的指针。