[Programmation] STM32F303K8 - créer un Timer - Utilisation Librairies
Répondre à la discussion
Affichage des résultats 1 à 7 sur 7

STM32F303K8 - créer un Timer - Utilisation Librairies



  1. #1
    Vicolo

    STM32F303K8 - créer un Timer - Utilisation Librairies


    ------

    Bonjour,

    voici mon premier message sur ce forum, j'espère que vous pourrez m'aider ! (Je ne recherche en aucun cas une solution, juste de l'aide pour m'aider à comprendre mon sujet ! )

    Je réalise un projet sur un microcontroleur de la gamme ST : le STM32F303K8. (je test mes programmes sur la carte NUCLEO correspondant au microcontroleur)

    J'ai réalisé le Pinout de la carte sous CubeMX, logiciel de chez ST aussi, et je code avec le compiler SW4STM32 (system workbench for stm32) sous eclipse.

    Alors voilà, j'arrive actuellement par exemple à set/reset une pin, et dans le cadre de mon projet, je dois créer un timer.

    Pour l'instant je ne recherche pas à créer un timer avec un temps précis, alors partons sur un timer de 1µs.

    J'ai lu la datasheet, le manual reference du composant, je comprend le principe des registres etc... mais dans le code c'est tout autre chose.

    J'aimerais avoir de l'aide pour comprendre comment réussir à mettre en place un timer (par exemple le timer 2 du composant, étant donné que le timer 1 à l'air plus complexe), mais aussi comment calculer le temps du timer ?

    J'ai des bases sur la programmation de PIC16F, où la création d'un timer ne me posait pas de problèmes, mais actuellement, je nage complètement chez les STM32.

    Je viens donc poster ici, pour - si vous le voulez- vous puissiez partager vos connaissances STM32. (même quelque chose sur les clocks me ferait du bien).

    Concernant les librairies, je ne comprend pas comment on peut les connaitre et les utiliser.
    Selon le manual reference, il y a des registres à initialiser, par exemple pour activer la clock d'un port (ex : RCC_AHBENR). Il faut mettre le bit IOPxEN à 1 pour un port x. Mais dans le code généré par CubeMX, c'est tout autre chose.
    Je dispose d'exemple sur d'autre carte de la carte STM32 (STM32F207..), où l'utilisateur utilisait des librairies comme :

    __HAL_RCC_GPIOA_CLK_ENABLE();

    pour activer la clock du port A. (ce qui est beaucoup plus simple en soit). mais alors comment avoir tous les types de noms de librairies, je n'ai vu nul part cela dans le manual reference. Ai-je donc louper quelque chose ?

    Voilà, si vous pouvez m'éclairer sur le sujet, me donner des exemples de timer, ou de configuration de timer ou même m'expliquer les différentes configuration du timer.

    Voilà, bonne journée à vous, en esperant avoir été assez clair malgré ma demande assez confuse.


    -----

  2. #2
    Vicolo

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    Double post, pour m'expliquer un peu plus clairement

    J'ai fait des recherches, et ai pris des exemples.

    Rien que pour la configuration d'un timer (j'ai pris le TIM3) il y a différents modes :
    input caputre direct mode
    Forced output channel2
    output compare no output
    etc...


    Rien qu'avec ces paramètres je suis un peu perdu, je ne trouve rien dans la doc technique de concret car je ne connais pas ces termes.
    Je voudrais juste créer un timer qui pulse à 1µs (ou autre chose).
    Mais je m'y perd dès le début.

    J'ai choisi la config du TIM3_CH2 : force output channel2 (ce qui d'après moi, devrait juste forcer en sortie le channel 2).

    CubeMX me génère le code suivant pour la config du TIM2 :
    Code:
    void MX_TIM3_Init(void)
    {
    
      TIM_ClockConfigTypeDef sClockSourceConfig;
      TIM_MasterConfigTypeDef sMasterConfig;
      TIM_OC_InitTypeDef sConfigOC;
    
      htim3.Instance = TIM3;
      htim3.Init.Prescaler = 0;
      htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim3.Init.Period = 0;
      htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      HAL_TIM_Base_Init(&htim3);
    
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);
    
      HAL_TIM_OC_Init(&htim3);
    
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
    
      sConfigOC.OCMode = TIM_OCMODE_FORCED_ACTIVE;
      sConfigOC.Pulse = 0;
      sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
      sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
      HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
    
      HAL_TIM_MspPostInit(&htim3);
    
    }
    et j'avoue être vachement paumé dans ce code. Je comprend quelques trucs, mais pas tout les choix du logiciels.

    Comment gérer la config de mon timer pour avoir une sortie simple sur la PIN voulue qui change d'état tous les x millisecondes ?

    Merci d'avoir lu
    Dernière modification par gienas ; 18/04/2016 à 14h20. Motif: Ajouté les balises code obligatoires pour les programmes

  3. #3
    bastien31

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    Bienvenue dans le monde fabuleux du STM32.

    Comme toi j'ai eu beaucoup de mal au debut.

    J'utilise pas le même environnement que toi mais je vois quelque truc a verifier.

    Déjà il faut activer l'horloge du timer et de ton GPIO, tu en parle sur ton premier post "par exemple pour activer la clock d'un port (ex : RCC_AHBENR)"

    il faut vérifier que l'horloge du timer est activé, peut etre dans HAL_TIM_ConfigClockSource(&hti m3, &sClockSourceConfig);
    Ensuite je pense que dans ton code l'horloge du GPIO n'est pas activé.

    Il faut certainement configurer ta pin qui correspond a TIM3_CH2 en ALTERNATE FONCTION.

  4. #4
    Vicolo

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    Salut, merci de ta réponse, je me sens moins seul !

    Alors j'ai bien activer les horloges des PORT GPIO :

    Code:
    void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOF_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin : Vbatt_Pin */
      GPIO_InitStruct.Pin = Vbatt_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(Vbatt_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PA7 */
      GPIO_InitStruct.Pin = GPIO_PIN_7;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pin : IOlink_Enable_Pin */
      GPIO_InitStruct.Pin = IOlink_Enable_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(IOlink_Enable_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PA8 */
      GPIO_InitStruct.Pin = GPIO_PIN_8;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pins : CS_Girouette_Pin CS_Anemo_Pin CS_Frame_Pin */
      GPIO_InitStruct.Pin = CS_Girouette_Pin|CS_Anemo_Pin|CS_Frame_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(IOlink_Enable_GPIO_Port, IOlink_Enable_Pin, GPIO_PIN_SET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOA, CS_Girouette_Pin|CS_Anemo_Pin|CS_Frame_Pin, GPIO_PIN_RESET);
    
    }
    Depuis hier midi, je pense avoir compris un peu plus, toutefois je m'interroge sur les valeurs de htim3.Init.Prescaler = 0; et htim3.Init.Period = 0; (auto reload)

    Comment avec ces valeurs je peux me définir un compteur / temps d'éxécution ? Un peu comme un PIC où il fallait juste diviser par le PSA (prescalaire) puis compter le nombre de valeur que l'on voulait pour avoir une valeur initiale du compteur qui compte jusque x.

    J'ai aussi trouvé des programmes pour m'aider à comprendre, et ceux-ci outre la similaire configuration dans le code ci-dessous (c'est mon code généré par CubeMX) (globalement la même forme que dans les exemples que j'ai trouvé sur internet) :

    Code:
    void MX_TIM3_Init(void)
    {
    
      TIM_ClockConfigTypeDef sClockSourceConfig;
      TIM_MasterConfigTypeDef sMasterConfig;
      TIM_IC_InitTypeDef sConfigIC;
    
      htim3.Instance = TIM3;
      htim3.Init.Prescaler = 1;
      htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim3.Init.Period = 100; // valeur AUTO RELOAD REGISTER
      htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      HAL_TIM_Base_Init(&htim3);
    
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);
    
      HAL_TIM_IC_Init(&htim3);
    
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
    
      sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
      sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
      sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
      sConfigIC.ICFilter = 0;
      HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2);
    
    }
    et bien ils avaient aussi dans leur fichier stm32f3xx_it.c une sorte d'interruption (si j'ai bien compris le truc) :

    Code:
    void TIM2_IRQHandler(void)
    {
      /* USER CODE BEGIN TIM2_IRQn 0 */
    
      /* USER CODE END TIM2_IRQn 0 */
      HAL_TIM_IRQHandler(&htim2);
      /* USER CODE BEGIN TIM2_IRQn 1 */
    
      /* USER CODE END TIM2_IRQn 1 */
    }
    Est-ce véritablement utile pour créer un simple timer ? (Je ne pense pas ?)

    Ensuite :
    Pour activer la clock d'un timer comme tu me l'as recommandé, j'ai choisis le mode CLK_Internal il faut que :

    Code:
    Internal clock source (CK_INT)
    If the slave mode controller is disabled (SMS=000 in the TIMx_SMCR register), then the CEN, DIR (in the TIMx_CR1 register) and UG bits (in the TIMx_EGR register) are actual control bits and can be changed only by software (except UG which remains cleared automatically). As soon as the CEN bit is written to 1, the prescaler is clocked by the internal clock CK_INT.
    Il me reste à mettre le BIT CEN du registre TIM3_CR1 à 1.
    Pour cela, est ce que cette ligne de commande est correct ?
    (en considérant que le bit CEN est le bit 0)

    TIM3->CR1 = (TIM3->CR1) && (0x0000000000000001);


    Merci pour ta réponse, en esperant ne pas trop te surchargé en question aha

  5. A voir en vidéo sur Futura
  6. #5
    Vicolo

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    J'ai trouvé la solution tout seul finalement !
    (enfin on m'a aidé quand même). Je poste une aide ici tout de même, car ça peut en intéresser plus d'un.

    Les codes/explications suivantes fonctionnent pour le microcontroleur STM32F303K8, mais valent globalement la même chose pour les micro de la gamme ST.


    Dans le main.c :

    Code:
    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();
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      //MX_ADC1_Init();
      //MX_DAC1_Init();
      //MX_SPI1_Init();
      //MX_USART1_UART_Init();
      MX_TIM3_Init();
      //MX_RTC_Init();
      MX_TIM16_Init();
    
      HAL_TIM_Base_Start_IT(&htim16); //lance le timer géré par des interruptions : TIM16
      /* USER CODE BEGIN 2 */
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
      /* USER CODE END WHILE */
    
      /* USER CODE BEGIN 3 */
    	  HAL_GPIO_WritePin(GPIOB,IOlink_Enable_Pin,GPIO_PIN_SET ); //inutile en soit, mais c'était pour tester si le programme compilait bien au début
    
      }
      /* USER CODE END 3 */
    
    }
    Il vous faut aussi configurer la clock, dans la fonction void SystemClock_Config(void). (plus simplement, regardez la datasheet et générez ça sous CubeMX)

    Ensuite, j'ai configurer mon timer, (j'ai pris un timer simple)

    Code:
    void MX_TIM16_Init(void)
    {
    
      htim16.Instance = TIM16;
      htim16.Init.Prescaler = 7;
      htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim16.Init.Period = 500;
      htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      htim16.Init.RepetitionCounter = 0;
      HAL_TIM_Base_Init(&htim16);
    
    }
    En fait, j'ai créer ce timer, et celui-ci comptera ses valeurs prédéfinie (selon Prescaler et Period), puis :
    dans le fichier stm32f3xx_it.c : (qui gère les interruptions)
    CubeMX a généré ce code là (ci dessous), finalement très important. Il permet de dire que ce timer sera géré par des interruptions. d(où l'utilisation de la fonction HAL_TIM_Base_Start_IT(&htim16) ; dans le main plutôt que HAL_TIM_Base_Start(&htim16);.

    Code:
    void TIM1_UP_TIM16_IRQHandler(void)
    {
      /* USER CODE BEGIN TIM1_UP_TIM16_IRQn 0 */
    
      /* USER CODE END TIM1_UP_TIM16_IRQn 0 */
      HAL_TIM_IRQHandler(&htim16);
      /* USER CODE BEGIN TIM1_UP_TIM16_IRQn 1 */
    
      /* USER CODE END TIM1_UP_TIM16_IRQn 1 */
    }
    Finalement, à chaque fin de comptage de mon timer, celui-ci va générer une interruption, maintenant il suffit de dire ce qu'il va faire lorsque cette interruption est levé :

    grâce à la fonction de Callback() :

    Code:
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	 HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_12 ); //change l'état de la PIN
    }
    Cette fonction sera donc appelée dès qu'il y aura une interruption. Dans le code ci-dessous, à chaque fin de comptage de mon compteur, la fonction Callback sera appelée et inversera l'état de la PIN.

    Pour résumer :

    Nous avons bien le start du timer d'interruption, l'interruption en question, et la fonction de callback.


    Merci à toi bastien31 !
    [/b](mes explications ci dessus ne sont pas à prendre comme 100% véritable, j'ai pu (et surement) me tromper dans les explications, c'est tel que je vois le timer du microcontroleur, et si quelqu'un lit ça et voit que c'est le cas, j'espère qu'il me corrigera.)[/b]

  7. #6
    bastien31

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    Cool que tu ai pu t'en sortir.

    Tout ces surcouches me font un peu mal a la tete. J'aime bien bricoler les registres des peripheriques moi même. Et c'est beaucoup plus instructif.
    Peut être un peu plus long... parfois

    Par contre tu aurais pus faire plus efficace.

    L’interruption n'est pas nécessaire. Il est possible de mapper directement un PIN a un événement du timer(comme l'overflow) .
    Dans ton cas s'a na peut être pas d'importance, mais si tu veu t'amuser a générer une PWM sa deviens un peu plus compliqué et surtout un peu gourmand en temps d’exécution.

    Les peripheriques de ces petites bébêtes sont plutôt complet c'est parfois très utile de bien les maîtriser.

  8. #7
    Vicolo

    Re : STM32F303K8 - créer un Timer - Utilisation Librairies

    Salut,

    J'imagine bien qu'il doit y avoir des méthodes plus simples et moins consommatrice...

    Ce que tu proposes, c'est d'enlever l'interruption, pour n'avoir qu'un simple Timer qui compte jusque la valeur de reload, et Toggle la Pin à chaque evenement de ce timer ? (par exemple le reset dès qu'il est arrivé à la valeur d'auto reload ?)

    Par exemple p^rendre l'evenement : Update Event
    et à chaque front de celui-ci, toggle la pin ?

    Dans ce cas là, où mettrai t-on la fonction : (écrite grossièrement)

    if(UEV==1)[Toggle_PIN]

    dans le main ? mais cela ne permettrai pas l’exécution d'autres tâches ? là où les interruptions tournent en fond.

Discussions similaires

  1. probleme pour créer un timer avec le pic18F45K22
    Par docEmmettBrown dans le forum Électronique
    Réponses: 3
    Dernier message: 10/07/2015, 14h11
  2. Aide utilisation timer
    Par rafiduck dans le forum Électronique
    Réponses: 7
    Dernier message: 19/02/2014, 15h09
  3. Utilisation du Timer 0 sur PIC16F690
    Par invite8c7e0f8f dans le forum Électronique
    Réponses: 0
    Dernier message: 24/05/2012, 14h13
  4. MPLAB Librairies C18 utilisation de l'USART
    Par snyfir dans le forum Électronique
    Réponses: 0
    Dernier message: 14/10/2008, 17h29
  5. utilisation des librairies dans pspice(debutant)
    Par invited0d2714f dans le forum Électronique
    Réponses: 0
    Dernier message: 07/03/2007, 11h48
Découvrez nos comparatifs produits sur l'informatique et les technologies.