Чтение SPI Eeprom с помощью указателя не работает, но работает, когда указатель не используется - PullRequest
0 голосов
/ 24 августа 2018

Я новичок в программировании, и я пытаюсь прочитать страницу (64 байт) из Eeprom SPI, и у меня это работает при чтении в массив [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 в порядке, и я могу прочитать его, если я заменю «& Data» на «Buff» (Array [67]) в вызове HAL_SPI_TransmitReceive (...).

Значение указателя является начальным адресом структуры (0x20000090). Так что обращаясь к А.С.О. должно быть в порядке, но структура пуста при использовании указателя.

Меня больше всего интересует, почему это не работает, и исправление, не столько в комментариях, как «почему бы вам не сделать это вместо этого, я хочу узнать, что я сделал неправильно, потому что такой подход, Я считаю, должно работать.

Пожалуйста, помните, что я НОВЫЙ в программировании, поэтому, пожалуйста, объясните "для чайников".

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

Я не уверен, почему это так?

Функция HAL_SPI_TransmitReceive хочет, чтобы указатель знал, где хранить полученные данные. По сути, он хочет адрес, куда нужно поместить байты В вашем случае, согласно линии

void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No){...}

Data уже указатель, потому что он обозначен *. Это означает, что Data - это указатель, указывающий куда-то на uint8_t число / массив. Это где-то, где вы хотите, чтобы ваш SPI писал.

Когда вы добавили &, вы в основном дали SPI указатель на указатель того места, куда вы хотите записать. Таким образом, SPI записывает полученные данные через указатель, а не в том месте, куда указывает указатель?

Если это не имеет смысла, спросите меня снова. Это сложно объяснить.

Обновление:

Это, как я понимаю, не указатель, а массив?

Компилятор видит это только как указатель. В вашем случае указатель указывает на массив, но он мог находиться где угодно (почти) в памяти. Я умоляю вас думать скорее с точки зрения указателя, указывающего на первый элемент массива (*ptr==array[0]), а не с точки зрения массива.

Это как-то неявно, так что компилятор знает, что я хочу сделать, поэтому он просто принимает и компилирует правильно?

Я не уверен, должен ли компилятор успешно скомпилироваться или нет. Но вы не должны полагаться на это. Это часто случается, когда можно отправить указатели указателей (**ptr), поэтому компилятор просто предполагает, что вы знаете, что делаете. Поэтому вы должны тщательно следить за тем, как вы работаете со своими указателями.

0 голосов
/ 24 августа 2018

Хорошо, после попытки решить это за день или около того, я наконец-то обнаружил ошибку, это не должно быть & 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();
  }

Я не уверенпочему это?

...