Topic "[Programmation] en C sur des STM32"

Flux RSS des posts récents dans ce topic ( Flux Atom)


Pas de photo de profil

weetoz

Membre

#112 | Signaler ce message


Bonjour à toutes et à tous,

je suis maintenant l' heureux possesseur d' un Nucleo 32 f303k8,

j' essais de modifier un code fournit par ST dans STMCube_FW_F3V1.4.0,

c' est l' exemple PWMout.

J' ai du mal à comprendre ces lignes:

1
2
3
4
5
6
7
/* Set the pulse value for channel 2 */
  sConfig.Pulse = PULSE2_VALUE;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }

sConfig est le synonyme de struct TIM_OC_InitTypeDef de la librairie stm32f3xx_hal_tim.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** 
  * @brief  TIM Output Compare Configuration Structure definition  
  */
typedef struct
{                                 
  uint32_t OCMode;        /*!< Specifies the TIM mode.
                               This parameter can be a value of @ref TIMEx_Output_Compare_and_PWM_modes */

  uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register. 
                               This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */                          

  uint32_t OCPolarity;    /*!< Specifies the output polarity.
                               This parameter can be a value of @ref TIM_Output_Compare_Polarity */

  uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
                               This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
                               @note This parameter is valid only for TIM1 and TIM8. */
  
  uint32_t OCFastMode;   /*!< Specifies the Fast mode state.
                               This parameter can be a value of @ref TIM_Output_Fast_State
                               @note This parameter is valid only in PWM1 and PWM2 mode. */


  uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
                               This parameter can be a value of @ref TIM_Output_Compare_Idle_State
                               @note This parameter is valid only for TIM1 and TIM8. */

  uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
                               This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
                               @note This parameter is valid only for TIM1 and TIM8. */
} TIM_OC_InitTypeDef;

Je comprends à peu près cette structure. Mon souci vient plutôt du fait que je ne comprends pas comment pouvoir

utiliser chaque canal du Timer indépendamment les uns des autres. je mets le code en entier:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#include "main.h"

/** @addtogroup STM32F3xx_HAL_Examples
  * @{
  */

/** @addtogroup TIM_PWMOutput
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
#define  PERIOD_VALUE       (uint32_t)(444 - 1)  /* Period Value  */
#define  PULSE1_VALUE       (uint32_t)(PERIOD_VALUE/2)        /* Capture Compare 1 Value  */
#define  PULSE2_VALUE       (uint32_t)(PERIOD_VALUE*37.5/100) /* Capture Compare 2 Value  */
#define  PULSE3_VALUE       (uint32_t)(PERIOD_VALUE/4)        /* Capture Compare 3 Value  */
#define  PULSE4_VALUE       (uint32_t)(PERIOD_VALUE*12.5/100) /* Capture Compare 4 Value  */

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Timer handler declaration */
TIM_HandleTypeDef    TimHandle;

/* Timer Output Compare Configuration Structure declaration */
TIM_OC_InitTypeDef sConfig;

/* Counter Prescaler value */
uint32_t uhPrescalerValue = 0;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void Error_Handler(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /* STM32F3xx HAL library initialization:
       - Configure the Flash prefetch
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock to 64 MHz */
  SystemClock_Config();

  /* Configure LED3 */
  BSP_LED_Init(LED3);

  /* Compute the prescaler value to have TIM2 counter clock equal to 16000000 Hz */
  uhPrescalerValue = (uint32_t)(SystemCoreClock / 16000000) - 1;

  /*##-1- Configure the TIM peripheral #######################################*/
  /* -----------------------------------------------------------------------
  TIM2 Configuration: generate 4 PWM signals with 4 different duty cycles.

    In this example TIM2 input clock (TIM2CLK) is set to 2 * APB1 clock (PCLK1), 
    since APB1 prescaler is different from 1.   
      TIM2CLK = 2 * PCLK1  
      PCLK1 = HCLK / 2 
      => TIM2CLK = HCLK = SystemCoreClock

    To get TIM2 counter clock at 16 MHz, the prescaler is computed as follows:
       Prescaler = (TIM2CLK / TIM2 counter clock) - 1
       Prescaler = (SystemCoreClock /16 MHz) - 1
                                              
    To get TIM2 output clock at 36 KHz, the period (ARR)) is computed as follows:
       ARR = (TIM2 counter clock / TIM2 output clock) - 1
           = 443

    TIM2 Channel1 duty cycle = (TIM2_CCR1/ TIM2_ARR + 1)* 100 = 50%
    TIM2 Channel2 duty cycle = (TIM2_CCR2/ TIM2_ARR + 1)* 100 = 37.5%
    TIM2 Channel3 duty cycle = (TIM2_CCR3/ TIM2_ARR + 1)* 100 = 25%
    TIM2 Channel4 duty cycle = (TIM2_CCR4/ TIM2_ARR + 1)* 100 = 12.5%

    Note:
     SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f3xx.c file.
     Each time the core clock (HCLK) changes, user had to update SystemCoreClock
     variable value. Otherwise, any configuration based on this variable will be incorrect.
     This variable is updated in three ways:
      1) by calling CMSIS function SystemCoreClockUpdate()
      2) by calling HAL API function HAL_RCC_GetSysClockFreq()
      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
  ----------------------------------------------------------------------- */

  /* Initialize TIMx peripheral as follows:
       + Prescaler = (SystemCoreClock / 16000000) - 1
       + Period = (444 - 1)
       + ClockDivision = 0
       + Counter direction = Up
  */
  TimHandle.Instance = TIMx;

  TimHandle.Init.Prescaler         = uhPrescalerValue;
  TimHandle.Init.Period            = PERIOD_VALUE;
  TimHandle.Init.ClockDivision     = 0;
  TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
  TimHandle.Init.RepetitionCounter = 0;
  if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /*##-2- Configure the PWM channels #########################################*/
  /* Common configuration for all channels */
  sConfig.OCMode       = TIM_OCMODE_PWM1;
  sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
  sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
  sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
  sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;

  sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;

  /* Set the pulse value for channel 1 */
  sConfig.Pulse = PULSE1_VALUE;        // Comment le compilateur   //sait de quelle "Channel" il s' agit???
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
   }

  /* Set the pulse value for channel 2 */
  sConfig.Pulse = PULSE2_VALUE;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }

  /* Set the pulse value for channel 3 */
  sConfig.Pulse = PULSE3_VALUE;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }

  /* Set the pulse value for channel 4 */
  sConfig.Pulse = PULSE4_VALUE;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_4) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }

  /*##-3- Start PWM signals generation #######################################*/
  /* Start channel 1 */
 // if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
 // {
    /* PWM Generation Error */
 //   Error_Handler();
 // }
  /* Start channel 2 */
  if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_2) != HAL_OK)
  {
    /* PWM Generation Error */
    Error_Handler();
  }
  /* Start channel 3 */
  if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_3) != HAL_OK)
  {
    /* PWM generation Error */
    Error_Handler();
  }
  /* Start channel 4 */
  if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_4) != HAL_OK)
  {
    /* PWM generation Error */
    Error_Handler();
  }

  while (1)
  {
      /*On commence les tests
       * -Cablage:
       * - TIM2_CH1 : PA.5 (Arduino A4)  -->REDLED
             - TIM2_CH2 : PA.1 (Arduino A1)  -->GREENLED
             - TIM2_CH3 : PA.2 (Arduino A7)  -->BLUELED
             - TIM2_CH4 : PA.3 (Arduino A2)  -->

       * */
      /*On commnce par faire varier la led rouge
       * avec les #define  PULSEX_VALUE
       * On les remplacera par des fonctions d' incrémentaions par la suite
       * */
      sConfig.Pulse = PULSE1_VALUE;
      HAL_Delay(2000);
      sConfig.Pulse = PULSE2_VALUE;
      HAL_Delay(2000);
      sConfig.Pulse = PULSE3_VALUE;
      HAL_Delay(2000);
      sConfig.Pulse = PULSE4_VALUE;
      HAL_Delay(2000);

  }

}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn LED3 on */
  BSP_LED_On(LED3);
  while (1)
  {
  }
}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSI)
  *            SYSCLK(Hz)                     = 64000000
  *            HCLK(Hz)                       = 64000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            PLLMUL                         = RCC_PLL_MUL16 (16)
  *            Flash Latency(WS)              = 2
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
  
  /* HSI Oscillator already ON after system reset, activate PLL with HSI as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_NONE;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1); 
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 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)
  {
    /* Initialization Error */
    while(1); 
  }
}
#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 can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}

#endif

/**
  * @}
  */

/**
  * @}
  */

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

Comment puis-je faire pour m' adresser directement à chaque canal? Je suis conscient que ma tentative n' est pas complète, qu'il faut:

Créer une fonction "change PWMx" recevant le paramètres du "Channel" concerné.

Cette fonction désactivera le timer,

lui donnera le nouveau rapport cyclique,

et redémarrera le timer.

La façon de procéder n' est peut-être pas la meilleur…

Si vous avez des pistes ou des remarques, n' hésitez pas à m' en faire part.

Merci d' avance.

Derniére modification le par weetoz


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#114 | Signaler ce message


Bonjour,

Je ne comprend pas ton problème en fait …

Tu utilises :

1
HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2)

En détail :

  • HAL_TIM_PWM_ConfigChannel : la fonction qui permet de configurer le mode PWM d'un canal d'un timer,

  • TimHandle : la structure qui contient les info du timer cible,

  • sConfig : la structure qui contient les info du canal cible,

  • TIM_CHANNEL_2 : le canal cible,

Tout est là, le timer et sa config, le canal et sa config …

Qu'est ce qui pose problème avec le code de ton message ?


Pas de photo de profil

weetoz

Membre

#115 | Signaler ce message


Bonjour Skywodd,

c' est le fait que ce soit dans un if:

1
2
3
4
5
6
sConfig.Pulse = PULSE1_VALUE;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
   }

ce que je ne comprends pas, c' est que l' appel de la fonction puisse se faire dans la condition du IF. Je vais essayer ça sans le IF, encore merci pour ta disponibilité.

Je te tiens au courant.


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#116 | Signaler ce message


ce que je ne comprends pas, c' est que l' appel de la fonction puisse se faire dans la condition du IF.

C'est tout à fait faisable ;)

Tant que la fonction retourne une valeur qui peut être testé dans le if, ça passe.

Ici le but est de tester si le retour de la fonction est différent de HAL_OK qui correspond à "pas d'erreur".


Pas de photo de profil

weetoz

Membre

#117 | Signaler ce message


En fait, pour ma compréhension,si je le formule de cette manière: le simple fait d' appeler la fonction dans un If, on rentre dans la fonction, et à sa sortie, on la teste pour voir si il n' y a pas d' erreurs. Fallait le savoir un truc pareil!! En tout cas c' est super pratique et intelligent comme façon de coder.

En fait, ça rejoint un peu ce que tu dis dans ton article "Pour l'amour du C, n'utilisez pas les fonctions atoi, atol, atof et dérivées", il faut sécuriser son code avec ce genre de test.

Du coups, j' ai réussi avec le IF:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 while (1)
  {
      /*On commence à jouer au con
       * -Cablage:
       * - TIM2_CH1 : PA.5 (Arduino A4)  -->REDLED
         - TIM2_CH2 : PA.1 (Arduino A1)  -->GREENLED
         - TIM2_CH3 : PA.2 (Arduino A7)  -->BLUELED
         - TIM2_CH4 : PA.3 (Arduino A2)  -->

       * */
      /*On commnce par faire varier la led rouge
       * avec les #define  PULSEX_VALUE
       * On les remplacera par des fonctions d' incrémentaions par la suite
       * */
      sConfig.Pulse = PULSE1_VALUE;
        if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
        {
          /* Configuration Error */
          Error_Handler();
         }
      if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
        {
          /* PWM Generation Error */
          Error_Handler();
        }
      HAL_Delay(2000);

      sConfig.Pulse = PULSE2_VALUE;

        if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
        {
          /* Configuration Error */
          Error_Handler();
         }
      if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
        {
          /* PWM Generation Error */
          Error_Handler();
        }
      HAL_Delay(2000);

      sConfig.Pulse = PULSE3_VALUE;
      if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
            {
              /* Configuration Error */
              Error_Handler();
             }
      if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
            {
              /* PWM Generation Error */
              Error_Handler();
            }
      HAL_Delay(2000);

      sConfig.Pulse = PULSE4_VALUE;
      if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
            {
              /* Configuration Error */
              Error_Handler();
             }
      if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
            {
              /* PWM Generation Error */
              Error_Handler();
            }
      HAL_Delay(2000);

  }

Et ça fonctionne!!

Pour la suite, je me pencherai un peu plus sur la fonction Error_Handler(), En gros si il y a erreur, la led 3 s' allume.

J' apprécie beaucoup ta pédagogies, ta patiences, et ta disponibilités, lorsque j' ai commencé avec les µC (Arduino, mais ça on s' en doute), je n' avais aucune connaissance, et grace à tes articles et tutos sur Skyduino, j' ai pu progresser sur pal mal de point, tu fais un très bon travail, grand merci à toi.


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#118 | Signaler ce message


En fait, pour ma compréhension,si je le formule de cette manière: le simple fait d' appeler la fonction dans un If, on rentre dans la fonction, et à sa sortie, on la teste pour voir si il n' y a pas d' erreurs.

C'est exactement ça.

Ça ce passe comme avec des parenthèses dans un calcul de math. Quand tu as 2 * (1 + 2), tu fais d'abord 1 + 2, puis 2 * 3. Ici tu fais d'abord l'appel à la fonction, qui te retourne une valeur, que tu test pour obtenir un booléen, et qui conditionne ensuite l'action du if.

Fallait le savoir un truc pareil!! En tout cas c' est super pratique et intelligent comme façon de coder.

Ce genre de petite astuce est très pratique et évite bien des soucis.

En fait, ça rejoint un peu ce que tu dis dans ton article "Pour l'amour du C, n'utilisez pas les fonctions atoi, atol, atof et dérivées", il faut sécuriser son code avec ce genre de test.

Toujours sécuriser son code. Un code non testé (dans tous les sens du terme) est un code cassé par design.

En informatique, la question n'est pas de savoir si un programme va planter, car il plantera toujours un jour, mais de savoir si le plantage sera bien détecté et géré (voir corrigé).

J' apprécie beaucoup ta pédagogies, ta patiences, et ta disponibilités, lorsque j' ai commencé avec les µC (Arduino, mais ça on s' en doute), je n' avais aucune connaissance, et grace à tes articles et tutos sur Skyduino, j' ai pu progresser sur pal mal de point, tu fais un très bon travail, grand merci à toi.

Et un grand merci à toi de me lire. Sans lecteur je n'irai pas bien loin ;)


Pas de photo de profil

weetoz

Membre

#119 | Signaler ce message


Et un grand merci à toi de me lire. Sans lecteur je n'irai pas bien loin ;)

C' est un plaisir ;)

Bien maintenant que je peux jouer avec le rapport cyclique, il faut que je trouve le moyen de créer des couleurs défini et les affecter au rapport cyclique. J' utilise une banale diode RGB à cathode commune.

Je compte en faire un tutoriel, n' ayant pas encore de blog ou de site, je me demandais si ça t' ennuierais si je pouvais le poster sur ton site? J' ai aussi un astuce à partager sur l' utilisation des exemples "STM32Cube_FW_F3V1.4.0" avec SW4STM32 sous Linux, pour l' instant le fichier de configuration de SW4STM32 comportes des erreurs sur les chemins d' inclusions, je pense mettre ça dans la section Tutoriels et cours avec comme titre: [Astuce] Utilisé les exemples "STM32Cube_FW_Fxxx" avec SW4STM32 sous linux Si ça ne te dérange pas, bien sûre. La solution m' a été apporté sur le forum de openSTM32.

Derniére modification le par weetoz


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#120 | Signaler ce message


Bien maintenant que je peux jouer avec le rapport cyclique, il faut que je trouve le moyen de créer des couleurs défini et les affecter au rapport cyclique. J' utilise une banale diode RGB à cathode commune.

par weetoz

N'importe quel logiciel de dessin (même paint) permet d'exporter une couleur en RGB888 hexadécimal. Envoi simplement les valeurs R, G, B dans les registres PWM du timer et t'es bon ;)

Si tu veux faire les choses bien, tu peux même passer les valeurs R, G, B dans une table de correction gamma. La correction gamma permet de corriger la non linéarité de l’œil par rapport à la perception de la luminosité. Ça évite d'avoir des couleurs délavées / blanchâtres.

J'ai prévu un tutoriel sur le sujet (mais en version Arduino), à la limite je vais le commencer aujourd'hui pour la publication du samedi (j'avais pas encore de sujet de prévu) ;)

Je compte en faire un tutoriel, n' ayant pas encore de blog ou de site, je me demandais si ça t' ennuierais si je pouvais le poster sur ton site? (…) Si ça ne te dérange pas, bien sûre.

par weetoz

Aucun soucis, le forum dispose d'une section rien que pour ça, fait toi plaisir ;)

Si tu veux faire des titres / sommaires, envoi moi un MP avant de publier ton tutoriel, je te débloquerai les limitations d'affichage.


Pas de photo de profil

weetoz

Membre

#121 | Signaler ce message


Merci Skywodd,

je vais commencer tout de suite à faire des essais pour l' utilisation de l' archive STM32Cube_FW_F3_V1.4.0.zip.

Désolé, je vais faire "péter" les notifs dans la soirée, normalement, pour ce petit article, je ne vais pas aller bien loin dans la présentation, juste quelque "Edit" sans trop abuser.

Pour le tuto, j' ai encore du boulot, j' y reviendrais…


Pas de photo de profil

weetoz

Membre

#123 | Signaler ce message


Si tu veux faire les choses bien, tu peux même passer les valeurs R, G, B dans une table de correction gamma. La correction gamma permet de corriger la non linéarité de l’œil par rapport à la perception de la luminosité. Ça évite d'avoir des couleurs délavées / blanchâtres.

Je vais essayer la table fourni par Adafruit, ça devrai nettement améliorer les choses.

N'importe quel logiciel de dessin (même paint) permet d'exporter une couleur en RGB888 hexadécimal. Envoi simplement les valeurs R, G, B dans les registres PWM du timer et t'es bon ;)

En gros, envoyer directement les valeurs RGB dans HAL_TIM_PWM_ConfigChannel de chaque chaine?

Pour l' instant, je ne vois pas encore comment, il me parait plus aisé d' envoyer les valeurs 8bits dans chaque Canal TIM…

J'ai prévu un tutoriel sur le sujet (mais en version Arduino), à la limite je vais le commencer

aujourd'hui pour la publication du samedi (j'avais pas encore de sujet de prévu) ;)

Du coup, je vais attendre que ce soit soit sortie, comme ça je ferais juste l' adaptation sur le STM32

avec une présentation des Timers et leurs quelques possibilités d' utilisations.


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#124 | Signaler ce message


Je vais essayer la table fourni par Adafruit, ça devrai nettement améliorer les choses.

par weetoz

Si tu as besoin d'une table de correction Gamma différente, je fourni un script de génération avec l'article de Samedi ;)

En gros, envoyer directement les valeurs RGB dans HAL_TIM_PWM_ConfigChannel de chaque chaine?

Pour l' instant, je ne vois pas encore comment, il me parait plus aisé d' envoyer les valeurs 8bits dans chaque Canal TIM…

par weetoz

Tu changes simplement le "pulse" des canaux adéquats par les valeurs respectives R, G et B (en passant par la table de correction gamma si besoin).

Si c'est la valeur sur 8 bits qui pose problème : valeur_32b = valeur_8b << 24;, valeur_24b = valeur_8b << 16;, valeur_16b = valeur_8b << 8;.


Pas de photo de profil

weetoz

Membre

#125 | Signaler ce message


Si tu as besoin d'une table de correction Gamma différente, je fourni un script de génération avec l'article de Samedi ;)

J' suis impatient!!

Si t' as envie de rigoler, jusqu' à ce matin, j' envoyais mes valeurs en pourcentage… XD

bon, j' ai bu ma tisane et sa va mieux, pour exemple:

avant:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void Blue_Fade_Half_Up(void){    // de 50% à 100%
    int i;
            for (i = 50; i <= 100; i++) {
                sConfig.Pulse = gamma[i];
                    if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK)
                    {
                       //Configuration Error
                      Error_Handler();
                     }
                  if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_3) != HAL_OK)
                    {
                     //  PWM Generation Error
                      Error_Handler();
                    }
                  HAL_Delay(delaisBoucleUp/*-(rapportCyclique*2)*/);
        }Blue_Full();HAL_Delay(delaisBoucleUp);
}

après:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void Blue_Fade_Half_Up(void){
    int i;
            for (i = 127; i <= 255; i++) {
                sConfig.Pulse = gamma[i];
                    if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK)
                    {
                       //Configuration Error
                      Error_Handler();
                     }
                  if (HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_3) != HAL_OK)
                    {
                     //  PWM Generation Error
                      Error_Handler();
                    }
                  HAL_Delay(delaisBoucleUp/*-(rapportCyclique*2)*/);
        }Blue_Full();HAL_Delay(delaisBoucleUp);
}

Bon, faut que je retape toutes mes 'petites' fonctions…

Bonne journée.

[Edite]

Je ne me suis pas pris la tête, à manipuler les champs de bits, j' ai déclaré mon tableau en 32 bits,

je sais, niveau optimisation du code, je repasserais.

Derniére modification le par weetoz