Partage
  • Partager sur Facebook
  • Partager sur Twitter

SPI sur STM32 [Micro MEMS]

Sujet résolu
14 septembre 2019 à 19:37:29

Bonjour,

J'essaye de mettre en place une lecture de microphones MEMS avec le SPI d'un STM32F401RE.

J'initialise le timer 2, le SPI et je lance une lecture de la virable avec la HAL HAL_SPI_Receive().

Seulement, le registre censé se remplir avec les valeurs reçues reste à 0. (Dans le mode debug, arrivé à la ligne ou j'utilise la fonction HAL_SPI_Receive, la ligne suivant est sautée, peut être parcequ'aucune valeur n'est reçue ?

Je fouille mais ne trouve pas où j'ai pu me tromper...

Voilà mon code, generé via CubeMX.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2019 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;

TIM_HandleTypeDef htim2;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM2_Init(void);
static void MX_SPI2_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */



/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_TIM2_Init();
  MX_SPI2_Init();
  /* USER CODE BEGIN 2 */

  /*Code Ajoute*/
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
  uint32_t Result_read = 0x00000000;
  uint8_t Result_read_buff = 0x00;
  /*Fin Code Ajoute*/

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  /*Ajoute pour SPI */

	  //HAL_SPI_Receive(&hspi2,&Result_read_buff,8,10); //SPI3, DATA, 8 bit, temps 10ms avant erreur
	  //value=SPI->RXCRCR

	  //TEST CODE TROUVE
	  HAL_SPI_Receive(&hspi2,&Result_read_buff,1,10000);
	  Result_read |= (Result_read_buff<<24);

	  HAL_SPI_Receive(&hspi2,&Result_read_buff,1,10000);
	  Result_read |= (Result_read_buff<<16);

	  HAL_SPI_Receive(&hspi2,&Result_read_buff,1,10000);
	  Result_read |= (Result_read_buff<<8);

	  HAL_SPI_Receive(&hspi2,&Result_read_buff,1,10000);
	  Result_read |= (Result_read_buff);
	  //FIN CODE TROUVE

	  /*FIN SPI*/
	   for ( int i = 0; i < 100; i ++ )
	   {
	     __HAL_TIM_SET_COMPARE( &htim2, TIM_CHANNEL_3, i );
	     HAL_Delay( 10 );
	   }
	   for ( int i = 100; i > 0; i -- )
	   {
	     __HAL_TIM_SET_COMPARE( &htim2, TIM_CHANNEL_3, i );
	     HAL_Delay( 10 );
	   }
	   //value = GPIOB->IDR ; // value prend la valeur stockée à l’adresse 0x40010C08
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /**Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief SPI2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 80;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Est-ce que quelqu'un saurait où je me plante ?

Merci d'avance,

Antoine

EDIT : J'ajoute ici la fenetre CubeMX qui apportera probablement un peu plus de compréhension que le code.

Je précise aussi que mon Micro MEMS à sa clock branchée sur PB13 et sa sortie sur PB15.



-
Edité par AntoineStartup 14 septembre 2019 à 19:46:09

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
14 septembre 2019 à 19:50:19

Essaye d'abord d’incrémenter ton module!

Bonne continuation!

  • Partager sur Facebook
  • Partager sur Twitter

DOMA

15 septembre 2019 à 0:43:22

D'après ta configuration PB15 c'est MOSI, "Master Out Slave In" donc une sortie du microcontrôleur, tu devrais plutôt connecter la sortie du capteur sur PB14 / MISO, "Master In Slave Out", l'entrée du microcontrôleur.

  • Partager sur Facebook
  • Partager sur Twitter
15 septembre 2019 à 9:25:39

Merci pour vos réponses,

J'ai donc tenté de relancer le debug de mon programme en branchant ma sortie de microphone sur PB14 : j'ai le même problème qu'avant :(

Doma 12 a écrit:

Essaye d'abord d’incrémenter ton module!

Bonne continuation!


Doma 12 je ne comprends pas ce que tu veux dire par incrémenter mon module ?

Merci d'avance !!

-
Edité par AntoineStartup 15 septembre 2019 à 9:28:38

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
16 septembre 2019 à 15:59:12

En fait, la ligne suivant les HAL_SPI_Receive est ignorée, parce que tu ne fais qu'affecter des valeurs à la variable Result_read, sans jamais te servir du résultat. Le compilateur enlève, à juste titre, tout le code qui lui semble inutile, donc si tu veux que ces lignes soient compilées, il faut que tu désactives les optimisations dans les options du compilateur, ou que tu te serves de la variable, par exemple en l'écrivant sur le port série (puisque apparemment il est configuré).

Tu devrais aussi remettre Result_read à 0 au début de la boucle, parce les |= vont remplir progressivement tous les bits à 1 sans jamais les remettre à 0, mais ce n'est pas la cause du problème de lecture.

Comme le code de configuration du SPI est généré automatiquement, je doute qu'il y ai un problème de ce côté là et même si la polarité du signal SPI était mal configuré, tu devrais recevoir des données, invalides ou décalées, mais pas tout le temps 0.

Peux tu donner la référence de ton micro mems ? Celui-là par exemple: https://cdn-shop.adafruit.com/product-files/3421/i2S+Datasheet.PDF se met en veille si la fréquence d'horloge est inférieur à 900KHz, ce qui fait que si tu l'exécutes sous un debugger en mode pas à pas, la fréquence ne sera peut-être pas suffisante (en tout cas sur l'ensemble des 32 bits à lire) et il va toujours renvoyer soit 0xff soit 0x00 en fonction des pullup/pulldown sur le bus SPI.

-
Edité par alexisdm 16 septembre 2019 à 16:10:14

  • Partager sur Facebook
  • Partager sur Twitter
16 septembre 2019 à 18:46:00

Bonjour,

Merci pour ton retour, alors ju'tilise ce micro : MP34DT01-M, sur une carte de dev Nucleo CCA02M1. Celle ci vient se plugger son mon STM32F401RE.

J'ai donc ajouté la ligne Result_Read à 0 au début du while.

Je vais tenter d'envoyer la valeur reçue via l'UART2 sur mon terminal en utilisant HAL_UART_Transmit et je viendrais dire ce que ça donne :)

Merci pour toutes ces infos très utiles !!

EDIT :

Rebonjour,

Après quelques test, j'arrive à transmettre un "HelloWorld" via l'UART, mais quand il s'agit dans transmettre la valeur reçue via SPI je ne reçois rien...

J'ai peur de m'etre trompé sur quelquechose lié à la variable Result_read etant donné qu'un warning apparait : "Description    Resource    Path    Location    Type
passing argument 2 of 'HAL_UART_Transmit' makes pointer from integer without a cast [-Wint-conversion]    main.c    /TIM2_TP/Src    line 164    C/C++ Problem
"

Voilà un screen de mon code :

EDIT 2 :

Après quelques recherche, je crois avoir trouvé un moyen de scruter la valeur de Result_read. Dans le mode debug, j'ajoute cette variable via "Add Watch Expression", qui apparait de cette manière :

Comme on peut le voir ci contre : la valeur est à 0 et aucune ligne n'est sautée comme auparavant.

A priori le SPI est bien configuré, donc là j'ai l'impression d'avoir fait le tour des possibilité... Je ne vois pas vraiment quoi tester de plus...

-
Edité par AntoineStartup 16 septembre 2019 à 21:31:25

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
16 septembre 2019 à 22:12:49

D'après ce que je comprends de la datasheet (contrairement à celui que j'avais pris comme exemple), les données stéréo peuvent être entrelacées avec un bit de chaque canal sur chaque front, montant et descendant, de CLK, et l'autre front est en état de haute impédance, donc si tu n'es pas sur le bon front d'horloge et que tu n'as qu'un seul micro, il n'y a rien à lire.

Donc tu peux essayer d'inverser l'horloge, en changeant CPHA en 2EDGE plutôt que 1EDGE (dans le code ou stm32cube).

  • Partager sur Facebook
  • Partager sur Twitter
16 septembre 2019 à 22:50:35

Effectivement je n'avais pas vu ça, cependant quand je change la config j'obtiens le même résultat...

Peut-être que ma config est mauvaise ?

Sur la doc des micros il est écrit qu'un CLK entre 2 et 3.25 MHz est OK. Ma fréquence de base est 80MHz et j'utilise un prescaler de 16 soit : 80/16=5MHz...

Je vais retenter avec un prescaler à 32 pour avoir fCLK=2,5MHz....

Après tests cela ne change rien, on a toujours 0 sur le Result_read_buff et Result_read

Je vois une autre variable : CPOL, est-il utile de tenter de la changer ?

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
17 septembre 2019 à 15:59:11

Ca ne change rien à ce que tu as déjà testé, mais SPI2 est sur APB1 qui est limité à 42MHz, donc si tu n'as pas spécifiquement modifier le prescaler de APB1, si le microcontrôleur est à 80Mhz, la fréquence de base sur laquelle s'applique le prescaler du SPI2 est de 40MHz. La fréquence du micro peut être entre 1 et 3.25Mhz (Table 5 page 6), donc pour un prescaler de 16 ou 32, ça devrait fonctionner.

CPOL ne fait que changer la polarité de CLK, quand le SPI n'est pas actif, ce qui ne change que le canal de départ en mode stéréo.

Avec tous ces ponts de soudure possibles sur la carte nucleo CCA02M1, as tu vérifié qu'il y avait bien continuité entre PB14 et la broche DOUT du micro et entre PB13 et CLK, et pas de court circuit entre PB15 et PB14 (puisque tu as du retirer un pont de soudure) ?

Pour vérifier si le micro envoie des données et donc s'il s'agit d'un problème de configuration du SPI, tu peux retirer la configuration en sortie de PA5 pour éviter tout court-circuit et connecter PB14 sur PA5 et voir si la led scintille ou pas (il faut juste commenter les 2 lignes HAL_GPIO_WritePin et HAL_GPIO_Init qui concernent LD2 dans la fonction MX_GPIO_Init, ou réinitialiser l'état de PA5 dans stm32cube).

  • Partager sur Facebook
  • Partager sur Twitter
17 septembre 2019 à 20:45:51

En regardant la CLK config dans Cube MX, je suis bien à 80MHz pour HCLK.

Cependant j'ai deux lignes pour APB1, qu'on peut voir sur le screen ci dessous. Je n'ai rien touché là dedans donc j'imagine que les réglages sont OK.

Concernant les ponts de soudure :

Il n'y a pas continuité entre DOUT et PB14, DOUT est relié à PB15 physiquement (pont de soudure). Mais pour pallier à ce problème j'ai ajouté un fil que j'ai connecté entre le DOUT qui passe par J2 et PB14 (lors de mes tests precedents).

Le test de continuité au mutli sur CLKmicro et la pin PB13 montre une discontinuité que je n'avais pas vu... Après vérification, CLKmicro est connecté sur PB5... (J'ai un peu la haine de m'être trompé là dessus grrrrr !! )

Je n'ai pas retiré de pont de soudure : une resistance de 0Ohms est présente pour relier PB15 au DOUT, le pont PB14 est ouvert (c'est pourquoi j'ai mis un fil entre J2 et DOUT)

Je fais le test LED : elle ne s'allume pas...

J'ai finalement un doute sur l'etat des micros : J'ai donc trouvé et compilé un programme test de ST (utilisant I2S et non SPI). Tout fonctionne (j'enregistre bien du son avec Audacity), quand on relie J2 à PA5, la LED s'allume. Il semblerait donc que le problème vienne plutôt du SPI...

Je fais donc un autre test :

Je passe sur SPI1 afin d'activer les pins "type arduino" pour les connecter plus facilement. Voilà un screen de ma config CubeMX

Je branche ensuite avec 2 fils :

La pin CLK du micro sur PB3

La pin J2 (DOUT du micro) sur PB4

Je compile / Debug : Toujours rien (J'ai eu un faux espoir, Result Read s'est rempli de 11111 après le premier décalage de 24 bits, mais ça n'a pas suivi et même quand je recompile ça ne refait aps ça)

Je test tout de même avec CPHA en 2EDGE au lieu de 1EDGE

Je recompile tout ça tout ça et j'ai de nouveau ce petit bug que j'ai screen :

Voilà, je tente de mettre mon connecteur J2 sur la LED avec un fil mais elle ne s'allume toujours pas...

(ça me rends fou ce SPI haha)

Demain je vais tenter d'observer la CLK de mon SPI sur un oscillo, mais je trouve ça vraiment bizarre

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
17 septembre 2019 à 22:27:40

Le problème, si DOUT est connecté à PB15, c'est qu'en mode "SPI Full Duplex Master" HAL_SPI_Receive appelle en interne HAL_SPI_TransmitReceive, qui maintient donc PB15 et donc DOUT à 0 (techniquement elle envoie le buffer transmis à HAL_SPI_Receive, Result_read_buff, qui vaut 0).

Il faut passer en mode "Receive Only Master" pour ne plus utiliser PB15 (ou déplacer la broche SPI2 MOSI sur PC3 si jamais tu devais connecter une sortie audio I2S/SPI). Mais c'est quand même plus simple de couper les ponts de soudures, ils sont faits pour ça :)

  • Partager sur Facebook
  • Partager sur Twitter
18 septembre 2019 à 15:42:29

J'ai essayé en mode Receive Only Master, toujours rien.

Ducoup je reprends tout depuis la base :

Je vais cette fois ci deplugger et connecter "manuellement" chaque pin

Voilà la config Cube MX :

Quand on regarde la Doc du CCA02M1 on a CLK sur PB5 et DOUT sur J2 (PB15). J'ai donc connecté physiquement les fils de cette manière.

Le 3.3V et GND sont ceux utilisés sur les pins Arduino.

Dans le code j'ai juste ajouté dans le while 1 un _HAL_SPI_Receive.

Cette fois j'obtiens quelques chose : 256 tout le temps...

Quand je branche la sortie du micro à un oscillo j'obtiens ceci, que je trouve assez bizarre (j'ai aussi des photo de la CLK si besoin):

-
Edité par AntoineStartup 18 septembre 2019 à 15:43:45

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
18 septembre 2019 à 18:03:02

AntoineStartup a écrit:

Quand on regarde la Doc du CCA02M1 on a CLK sur PB5 et DOUT sur J2 (PB15). J'ai donc connecté physiquement les fils de cette manière.

Oui, mais ils font des trucs assez différents d'un simple SPI: PB5 est une sortie de timer, PB15 est MOSI, mais le SPI2 est en mode esclave et "receive only" (donc MOSI devient une entrée) et c'est l'I2S qui contrôle la broche SCK du SPI2 (PB13), et d'après ce qui est indiqué dans le readme.txt de l'exemple, le timer fonctionne à la moitié de la fréquence du SPI pour avoir un front montant et un front descendant qui correspondent chacun à une lecture, donc chaque lecture sur 16 bits contient les 8 bits de chacun des 2 microphones entrelacés.

Donc si tu veux n'utiliser que le SPI en mode maître, sur un seul canal, il faut seulement connecter DOUT sur PB14 et CLK sur PB13, pour le SPI2.

  • Partager sur Facebook
  • Partager sur Twitter
18 septembre 2019 à 18:49:16

Je suis desolé, j'ai mal expliqué ce que j'ai fait : Je suis passé sur le SPI1 (on voit pas sur le screen mais ce sont les trois pins en haut du microp)

Normalement c'est pareil que SPI2 mais comme j'ai repris un projet "neuf" j'ai utilisé le SPI1, dont les pins de sorties utilisent les emplacement arduino (plus facile à connecter avec les fils).

Finalement le test que j'ai fait est celui que tu dit :

connecter DOUTmems sur PB14 et CLKmems sur PB13 avec le SPI2 revient à connecter DOUTmems sur PB3 et CLKmems sur PB4 avec le SPI1.

Et c'est avec ce test que j'ai obtenu ce signal à l'oscilloscope.

Pour être plus précis, j'ai réalisé 4 mesures :

- Verification qu'il y avait bien 3.3V aux bornes du micro --> OK

- Verification de la CLK au bornes du micro --> OK

- Verification du signal DOUT sur le micro --> Présent, mais comme on peut le voir sur la photo de mon précédent message, le signal semble bizarre.

Mon explication de ce signal est que lorsqu'on regarde les ponts de resistance  on remarque qu'alimenter le micro 1 alimente le micro 2, mettre la CLK sur le micro 1 revient aussi à connecter le micro 2. Donc j'imagine que sur mon oscillo on voit enfaite les valeurs des deux micros ? Sur 16 bits donc, sauf que moi j'utilise dans mon code une var 8 bit donc j'ai un problème de lecture qui rempli les 8 premiers bits par 1 .

Malheureusement je n'ai pas de fer à déssouder chez moi, mais demain je vais déssouder le pont de soudure qui relie le DOUT du micro1 au DOUT du micro2. J'espère que cela va me sortir de ce bloquage.

PS : Merci pour le temps que tu prends à m'aider en tout cas, ça me fait vraiment avancer mine de rien parceque je suis amené à refouiller les docs / revoir les fonctionnement des protocoles etc..
  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
19 septembre 2019 à 12:36:59

En y regardant de plus près, le signal sur l'oscilloscope semble correct, les changements ont bien lieu tous les 200ns (5MHz soit 2 fois la fréquence du SPI). Il faudrait mettre le signal CLK sur une autre voie de l'oscillo pour synchroniser chaque micro sur les fronts montants et descendants du signal CLK et voir s'il y a un des micros qui reste à 1 tout le temps.

Parce que là il semble bien que le signal oscille entre 0 et 1 et qu'au centre, entre deux lignes verticales, là où devrait se trouver les fronts d'horloge, il a bien une valeur correcte.

AntoineStartup a écrit:

Mon explication de ce signal est que lorsqu'on regarde les ponts de resistance  on remarque qu'alimenter le micro 1 alimente le micro 2, mettre la CLK sur le micro 1 revient aussi à connecter le micro 2. Donc j'imagine que sur mon oscillo on voit enfaite les valeurs des deux micros ? Sur 16 bits donc, sauf que moi j'utilise dans mon code une var 8 bit donc j'ai un problème de lecture qui rempli les 8 premiers bits par 1 .

Ca ne devrait pas poser de problème, parce que la lecture de la valeur se fait peu après un front montant OU descendant, en fonction de la configuration de CPOL et CPHA, comme le 2e micro est sur un front différent, la valeur est normalement ignorée (à moins que les timings soient très serrés, mais ça n'expliquerait pas pourquoi tu ne lis que des 1).

Vu comment le câble venant de DOUT est connecté sur PB4, il est aussi possible qu'il ne fasse pas correctement contact dans le connecteur (ce serait bien que ce soit juste ça, parce que je ne vois pas d'autre raison, d'autant que le signal CLK du SPI semble passer).

  • Partager sur Facebook
  • Partager sur Twitter
19 septembre 2019 à 18:53:31

J'ai bien verifié le cablage de DOUT : pas de soucis à ce niveau...

Cependant j'ai trouvé avec le mode debug un problème :

Lorsque que j'utilise HAL_SPI_Receive, je vais enfaite utiliser le HAL_SPI_TransmitReceive comme tu me l'a fait remarquer. Or dans cette fonction , on voit bien la variable DR du SPI qui se rempli mais après : je rentre dans une boucle infinie.

Finalement je vais arreter d'utiliser cette HAL qui me semble bien longue pour s'y plonger dedans et je vais coder moi même ma fonction SPI_Read.

uint8_t SPI_Read(SPI_TypeDef *spi)
  {
      while ((spi -> SR & SPI_SR_RXNE) != SPI_SR_RXNE);
      return *(volatile uint8_t *)&spi-> DR;
 }

Cependant encore un problème (sinon ça serait trop simple haha) Je bloque dans le while...



-
Edité par AntoineStartup 19 septembre 2019 à 18:53:51

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
20 septembre 2019 à 21:27:35

AntoineStartup a écrit:

Lorsque que j'utilise HAL_SPI_Receive, je vais en fait utiliser le HAL_SPI_TransmitReceive comme tu me l'a fait remarquer.

J'ai aussi écrit que si tu passes en mode Receive Only, ce n'est plus le cas.

Or dans cette fonction , on voit bien la variable DR du SPI qui se rempli mais après : je rentre dans une boucle infinie.

Je ne sais pas si ce n'est pas juste le fait de d'entrer dans la fonction en mode debug qui pose problème. Parce que toutes les boucles utilisent un timeout, justement pour ne pas bloquer indéfiniment.
Par contre, tu n'as pas testé le retour de la fonction HAL_SPI_Receive, peut-être qu'elle indiquait une erreur.

uint8_t SPI_Read(SPI_TypeDef *spi)
  {
      while ((spi -> SR & SPI_SR_RXNE) != SPI_SR_RXNE);
      return *(volatile uint8_t *)&spi-> DR;
 }

Cependant encore un problème (sinon ça serait trop simple haha) Je bloque dans le while...

Que fais tu avant d'appeler ta fonction SPI_Read ? Tu es censé démarrer le transfert SPI soit en écrivant dans le registre DR (mode full duplex), soit en mettant le bit SPE à 1 dans le registre CR1 (mode receive only).

Peux tu montrer également la partie configuration SPI si tu le fait aussi à la main ?



  • Partager sur Facebook
  • Partager sur Twitter
22 septembre 2019 à 20:10:30

Je vais tester le retour de la fonction HAL_SPI_Receive, mais ducoup là je me suis focus sur l'écriture d'une fonction read moi même que je maitriserais mieux que la HAL. (De plus dans l'utilisation de mes microphones, je vais devoir optimiser le temps de traitement afin de faire du traitement du signal FFT etc)

En attendant, j'ai ajouté à ma fonction SPI_Read() l'ajout du bit SPE du registre CR1 à 1.

Cependant, quand je passe après le return,  le mode debug va sur le "}" de la fin de la fonction, je fait un "step over" pour repasser sur mon main mais ça bloque ici...

Voilà un screenschot de mon mode debug.

Concernant ma fonction SPI_Init, j'utilise la config CubeMX qui me semble bonne :

/* SPI1 init function */
void MX_SPI1_Init(void)
{

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
  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_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
  
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration    
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
}

Ce qui est bizarre, c'est que j'avais le même problème avec la HAL du SPI_Receive en mode Receive Only.

Alors peut-êtree que ma config CubeMX est mauvaise ?

EDIT : Je me demandais si le flag BSY pouvait poser problème donc j'ai ajouté cette ligne :


      while(( spi -> SR & SPI_SR_BSY) != SPI_SR_BSY);

Juste avant le return. Sans avoir plus de succès

-
Edité par AntoineStartup 22 septembre 2019 à 20:32:48

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/
23 septembre 2019 à 12:43:46

Comme il n'y a aucune raison que ça bloque en mode master et qu'en plus ça bloque à un endroit improbable, peut-être que ça vient du fait que la broche PB3 est aussi SWO et qu'elle est connectée sur l'interface de débogage de la carte nucléo (je n'ai qu'une nucleo-f103rb et je ne réussi pas à reproduire le problème).

La configuration semble correcte, à part le prescaler qui doit être supérieur à 32 sur SPI1 qui est sur APB2 à 80MHz, si tu veux du 2.5MHz.

Le flag BUSY est toujours à 1 en mode Master pendant un transfert d'après la doc (section 20.3.7 du manuel).

AntoineStartup a écrit:

Je vais tester le retour de la fonction HAL_SPI_Receive, mais du coup là je me suis focus sur l'écriture d'une fonction read moi même que je maitriserais mieux que la HAL. (De plus dans l'utilisation de mes microphones, je vais devoir optimiser le temps de traitement afin de faire du traitement du signal FFT etc)

Tu aurais plus intérêt à le faire avec les interruptions ou le DMA qu'avec une boucle d'attente active, et dans ce cas, HAL n'intervient que pour le démarrage de la capture.

Mais je viens de tester avec HAL_SPI_Receive en mode Receive Only Master et tu ne peux pas utiliser cette fonction dans ce mode pour une réception continue de toutes façons: la fonction active le SPI, lit un octet, désactive le SPI et attend l'octet suivant, qui, si le SPI a été désactivé correctement, n'arrive jamais, et donc la fonction bloque jusqu'au timeout (les 10000ms que tu avais mis). C'est la procédure décrite dans la doc (section 20.3.8), mais même en mettant le timeout à la valeur minimal soit 1 cycle SPI (8 bits * la période du signal SCK) tu perdrais 8 bits à chaque fois, et dans la doc il est supposé que tu arrêtes le transfert 1 octet avant, pour que l'octet lu pendant le temps d'arrêt soit le dernier octet que tu voulais lire et pas un octet perdu. En mode Full Duplex Master, il n'y a pas ce problème, puisqu'il suffit de ne pas envoyer d'octet pour que le transfert s'arrête.

Donc pour la lecture en continu sans interruption, il faut activer le SPI avant la boucle, et juste lire les données dans la boucle (avec la configuration par défaut de la carte pour les leds et les boutons):

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint8_t data;
  SPI_TypeDef *spi = hspi1.Instance;
  spi->CR1|=SPI_CR1_SPE;
  while (1)
  {
	while ((spi -> SR & SPI_SR_RXNE) != SPI_SR_RXNE);
	data = *(volatile uint8_t *)&spi->DR;
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, !data); // envoie sur la LED

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Tu peux connecter le bouton bleu (PC13) sur MISO (PB4) à la place du micro pour voir si la led s'allume bien quand tu appuies sur le bouton.

  • Partager sur Facebook
  • Partager sur Twitter
23 septembre 2019 à 18:28:54

J'ai testé ton code, ça fonctionne !!

Je reçois bien les valeurs du mon microphone :D

Je vais désormais regarder un peu du coté des interruptions / DMA pour pouvoir libérer un peu le microp.

La prochaine étape du projet est de stocker les valeurs reçues dans un tableau et de faire de la FFT... encore plein de belles aventures m'attendent haha

Merci pour tout !!

  • Partager sur Facebook
  • Partager sur Twitter
N'hésitez pas à visiter mon site en construction et à donner des avis :) Merci !! Lien : http://foxwork.esy.es/