AnsweredAssumed Answered

STM32 SPI Spoiled Bits

Question asked by rwin on Oct 6, 2014
Latest reply on Sep 2, 2015 by waclawek.jan
Hello,
I have a problem trying to communicate with SPI using the STM32 Nucleo. I am using the STM_HAL_Drivers to read data from an Invensense MPU9250.
When I read values, I sometimes get spoilage of the last bit, and this seems to coincide with the value of the MISO line when the register address is being sent (i.e if the MISO line is high when transmiting the register address, the  recieved data will spoil high, and vice versa).
I have checked all lines using an Oscilloscope and the data seems to be fine.
001./* Includes ------------------------------------------------------------------*/
002.#include "stm32f4xx_hal.h"
003. 
004./* Private variables ---------------------------------------------------------*/
005.SPI_HandleTypeDef hspi1;
006. 
007.UART_HandleTypeDef huart2;
008. 
009./* USER CODE BEGIN 0 */
010.#include "MPU_SPI.h"
011.#define HAL_SPI_MODULE_ENABLED
012.#define MPU_Add         0x68<<1
013.#define MPU_WHO_AM_I    0x75
014. 
015./* USER CODE END 0 */
016. 
017./* Private function prototypes -----------------------------------------------*/
018.void SystemClock_Config(void);
019.static void MX_GPIO_Init(void);
020.static void MX_SPI1_Init(void);
021.static void MX_USART2_UART_Init(void);
022. 
023.int main(void)
024.{
025. 
026.  /* USER CODE BEGIN 1 */
027. 
028.  /* USER CODE END 1 */
029. 
030.  /* MCU Configuration----------------------------------------------------------*/
031. 
032.  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
033.  HAL_Init();
034. 
035.  /* Configure the system clock */
036.  SystemClock_Config();
037. 
038.  /* System interrupt init*/
039.  /* Sets the priority grouping field */
040.  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
041.  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
042. 
043.  /* Initialize all configured peripherals */
044.  MX_GPIO_Init();
045.  MX_SPI1_Init();
046.  MX_USART2_UART_Init();
047. 
048.  /* USER CODE BEGIN 2 */
049.  uint8_t *Buffer = "Hello World -> 1\n";
050. 
051.  uint8_t *Space = "\n";
052.  uint8_t *address[4]; //245 or f5
053. 
054.  char data[100];
055.  int *pdata =data;
056. 
057.      HAL_Delay(500);
058.      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
059.      HAL_Delay(100);
060.      func_SPI_Write_Byte(0x6B, 0x80, data); //__works
061.      HAL_Delay(100);
062. 
063.      func_SPI_Write_Byte(User_Control, 0x10, data); //__works
064.      HAL_Delay(100);
065. 
066.      func_SPI_Write_Byte(0x6B, 0x00, data); //__works
067.      HAL_Delay(100);
068. 
069.      func_SPI_Write_Byte(I2C_MST_Ctrl, 0x00, data);
070.      func_SPI_Write_Byte(I2C_MST_Ctrl, 0x4D, data);
071.      func_SPI_Write_Byte(User_Control, 0x60, data);
072. 
073.      HAL_UART_Transmit(&huart2, Buffer, strlen(Buffer), 5000);
074.      HAL_Delay(2000);
075. 
076.  /* USER CODE END 2 */
077. 
078.  /* USER CODE BEGIN 3 */
079.  /* Infinite loop */
080. 
081.  while(1){
082.      //this will read the contents of the MPU_Who_AM_I register
083.      //passing results to the "data"
084.      func_SPI_Write_Byte((MPU_WHO_AM_I|0x80),0x00, data); //__works
085. 
086.      //this will read the contents of the MPU_Who_AM_I register
087.      //This transmits 2 characters of "data" to be viewed on cutecom
088.      HAL_UART_Transmit(&huart2,  data, 2, 0x1000);
089. 
090.      //this will pass the contents of the MAG_Who_AM_I register into ext_sensor_4 register
091.      //it will then read this register passing results to the "data"
092.      //since it is an external sensor it requires more configuration
093.      func_SPI_Read_Ext_Sens_Byte(MAG_who_am_i,data);
094. 
095.      HAL_UART_Transmit(&huart2,  data, 2, 0x1000);
096. 
097.      func_SPI_Read_Ext_Sens_Byte(MAG_who_am_i,data);
098. 
099.      HAL_UART_Transmit(&huart2,  data, 2, 0x1000);
100. 
101.      func_SPI_Write_Byte((MPU_WHO_AM_I|0x80),0x00, data);
102.      HAL_UART_Transmit(&huart2,  data, 2, 0x1000);
103. 
104.      func_SPI_Write_Byte((MPU_WHO_AM_I|0x80),0x00, data);
105.      HAL_UART_Transmit(&huart2,  data, 2, 0x1000);
106. 
107.      HAL_Delay(2000);
108. }
109.  /* USER CODE END 3 */
110. 
111.}
112. 
113./** System Clock Configuration
114.*/
115.void SystemClock_Config(void)
116.{
117. 
118.  RCC_ClkInitTypeDef RCC_ClkInitStruct;
119.  RCC_OscInitTypeDef RCC_OscInitStruct;
120. 
121.  __PWR_CLK_ENABLE();
122. 
123.  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
124. 
125.  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
126.  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
127.  RCC_OscInitStruct.HSICalibrationValue = 6;
128.  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
129.  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
130.  RCC_OscInitStruct.PLL.PLLM = 16;
131.  RCC_OscInitStruct.PLL.PLLN = 336;
132.  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
133.  RCC_OscInitStruct.PLL.PLLQ = 7;
134.  HAL_RCC_OscConfig(&RCC_OscInitStruct);
135. 
136.  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
137.  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
138.  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
139.  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
140.  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
141.  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
142. 
143.}
144. 
145./* SPI1 init function */
146.void MX_SPI1_Init(void)
147.{
148. 
149.  hspi1.Instance = SPI1;
150.  hspi1.Init.Mode = SPI_MODE_MASTER;
151.  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
152.  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
153.  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
154.  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
155.  hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
156.  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
157.  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
158.  hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
159.  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
160.  HAL_SPI_Init(&hspi1);
161. 
162.}
163. 
164./* USART2 init function */5
165.void MX_USART2_UART_Init(void)
166.{
167. 
168.  huart2.Instance = USART2;
169.  huart2.Init.BaudRate = 115200;
170.  huart2.Init.WordLength = UART_WORDLENGTH_8B;
171.  huart2.Init.StopBits = UART_STOPBITS_1;
172.  huart2.Init.Parity = UART_PARITY_NONE;
173.  huart2.Init.Mode = UART_MODE_TX_RX;
174.  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
175.  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
176.  HAL_UART_Init(&huart2);
177. 
178.}
179. 
180./** Configure pins as
181.        * Analog
182.        * Input
183.        * Output
184.        * EVENT_OUT
185.        * EXTI
186.*/
187.void MX_GPIO_Init(void)
188.{
189. 
190.  GPIO_InitTypeDef GPIO_InitStruct;
191. 
192.  /* GPIO Ports Clock Enable */
193.  __GPIOC_CLK_ENABLE();
194.  __GPIOH_CLK_ENABLE();
195.  __GPIOA_CLK_ENABLE();
196.  __GPIOB_CLK_ENABLE();
197. 
198.  /*Configure GPIO pin : PC13 */
199.  GPIO_InitStruct.Pin = GPIO_PIN_13;
200.  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
201.  GPIO_InitStruct.Pull = GPIO_NOPULL;
202.  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
203. 
204.  /*Configure GPIO pin : PB6 */
205.  GPIO_InitStruct.Pin = GPIO_PIN_6;
206.  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
207.  GPIO_InitStruct.Pull = GPIO_NOPULL;
208.  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
209.  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
210. 
211.}
212. 
213./* USER CODE BEGIN 4 */
214./* int temp[6];
215.      int i;
216.      float value[2];
217.      for (i=0;i<2;i++){
218.          func_SPI_Write_Byte((MPU_Acc_X_H |0x80 + i),0x00, j);
219.          HAL_UART_Transmit(&huart2,  &data, strlen(&data), 0x1000);
220.          HAL_UART_Transmit(&huart2, Space, strlen(Space), 0x1000);
221.      temp[i]= data[2];
222. 
223.      }
224.      //for (i =0; i<3;i++){
225.         int temp2[2];
226.          temp2[0] = (int)(temp[i*2]<<8);
227.          temp2[1] = (int)temp[i*2+1];
228. 
229.          int16_t temp3 = (int16_t)(temp2[0] | temp2[1]);
230.          value[i] = (float)((temp3)/16384);
231.      //}
232. 
233.      HAL_UART_Transmit(&huart2,  &value, strlen(&value), 0x1000); //__works
234. 
235.*/
236./* USER CODE END 4 */
237. 
238.#ifdef USE_FULL_ASSERT
239. 
240./**
241.   * @brief Reports the name of the source file and the source line number
242.   * where the assert_param error has occurred.
243.   * @param file: pointer to the source file name
244.   * @param line: assert_param error line source number
245.   * @retval None
246.   */
247.void assert_failed(uint8_t* file, uint32_t line)
248.{
249.  /* USER CODE BEGIN 6 */
250./* User can add his own implementation to report the file name and line number,
251.ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
252.  /* USER CODE END 6 */
253. 
254.}
255. 
256.#endif
257. 
258./**
259.  * @}
260.  */
261. 
262./**
263.  * @}
264.*/
265. 
266./************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

The MPU_SPI header file includes the following functions and the MPU register addresses.
01.void func_SPI_Write_Byte(uint8_t address, uint8_t data, char *j){
02.    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
03.    uint8_t Write_data[2];
04.    Write_data[0] =  address;
05.    Write_data[1] = data;
06.    HAL_SPI_TransmitReceive(&hspi1, &Write_data, j, 2, 0x1000);
07.    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
08.    return;
09. 
10.}
11. 
12. 
13.void func_SPI_Read_Ext_Sens_Byte(uint8_t address, char *j){
14.    func_SPI_Write_Byte(I2C_SLV4_ADD,(MAG_Add|0x80),j);
15.    func_SPI_Write_Byte(I2C_SLV4_REG, address,j);
16.    func_SPI_Write_Byte(I2C_SLV4_CTRL, 0x80,j);
17.    func_SPI_Write_Byte((I2C_SLV4_DI|0x80), 0x00,j);
18.}

The MPU_Who_AM_I and the MAG_Who_Am_I are both set registers with values of 71 and 48 respectively.
All this should produce

ff 71 ff 48 00 48 00 71   ff 71

however it produces

ff 71 ff 49 00 48 00 70   ff 71

Any help would be greatly recieved and apologies for the wall of code, I have little experience of both using this forum and of microprocessors...

Outcomes