Subversion Repositories ScreenTimer

Rev

Rev 3 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/* USER CODE BEGIN Header */
2
/**
3
 ******************************************************************************
4
 * @file           : main.c
5
 * @brief          : Main program body
6
 ******************************************************************************
7
 * @attention
8
 *
9
 * Copyright (c) 2022 STMicroelectronics.
10
 * All rights reserved.
11
 *
12
 * This software is licensed under terms that can be found in the LICENSE file
13
 * in the root directory of this software component.
14
 * If no LICENSE file comes with this software, it is provided AS-IS.
15
 *
16
 ******************************************************************************
17
 */
18
/* USER CODE END Header */
19
/* Includes ------------------------------------------------------------------*/
20
#include "main.h"
21
 
22
/* Private includes ----------------------------------------------------------*/
23
/* USER CODE BEGIN Includes */
24
#include "stm32f0xx_hal_adc_ex.h"
25
/* USER CODE END Includes */
26
 
27
/* Private typedef -----------------------------------------------------------*/
28
/* USER CODE BEGIN PTD */
29
// turn on the watchdog timer
30
#define WATCHDOG
31
 
32
/// \brief Enumeration of heater states
33
typedef enum
34
{
35
  HEAT_OFF,        // heater is off
36
  HEAT_PENDING,    // heater request is pending
37
  HEAT_ON,         // heater is switched on
38
  HEAT_ON_LOW_VOLT // heater timer running, voltage is low
39
} heaterControl;
40
 
41
/// \brief state for heater channel
42
 
43
#pragma pack(push, 1)
44
typedef struct
45
{
46
  heaterControl control; ///< control state
47
  uint16_t LEDintensity; ///< current LED intensity
48
  uint16_t LEDtarget;    ///< current LED target intensity
49
  uint32_t heatTimer;    /// < tick time counter for heater channel
50
  uint8_t buttonCount;   /// < debounce counter
51
  uint16_t checkSum;     /// < checksum used in post-reset validation
52
} heaterStatus;
53
#pragma pack(pop)
54
 
55
/// \brief enumeration of LED intensities for each case
56
typedef enum
57
{
58
  INTENSITY_OFF = 1,          // dim glow
59
  INTENSITY_STBY_DIM = 8,     // flashing waiting for batttery voltage - dim
60
  INTENSITY_STBY_BRIGHT = 32, // flashing waiting for battery voltage -bright
61
  INTENSITY_ON_LOW = 64,      // night time intensity - dash lighting on
62
  INTENSITY_ON = 256          // daytime intensity  - dash lighting off
63
} ledIntensities;
64
 
65
/// \brief Enumeration of active ADC channels
66
typedef enum
67
{
68
  IGNITION_VOLT_CHAN = 0,
69
  DASHBOARD_VOLT_CHAN,
70
  TEMPERATURE_CHAN,
71
  VREF_CHAN
72
} adcChannels;
73
 
74
/* USER CODE END PTD */
75
 
76
/* Private define ------------------------------------------------------------*/
77
/* USER CODE BEGIN PD */
78
 
79
/// \brief LED intensities :
80
/// multiply by INTENSITY_STEP / (INTENSITY_STEP-1) to fade up  intensity
81
/// multiply by (INTENSITY_STEP-1) / INTENSITY_STEP to fade down intensity
82
#define INTENSITY_STEP 12
83
 
84
/// \brief ADC filtering parameters
85
#define ADC_TMPGRP_BUF_DEPTH 4
86
#define ADC_TEMPGRP_NUM_CHANNELS 4
87
 
88
/// \brief ADC scaling for power supply measurement
89
///  Resistor ladder is 47k top 10k bottom :ratio expressed as 1000 times value
90
#define IGN_ADC_SCALE 5556 // should be 5700 , but resistor ratio is 5.749 not
91
 
92
// Battery voltage * 1000
93
// alternator charging
94
#define HEATER_ON_VOLTAGE 13500
95
// battery OK under load
96
#define HEATER_OFF_VOLTAGE 11500
97
 
98
// if the dashboard/backlight power is over 5 volts, consider dimming LEDS
99
#define DASH_ON_VOLTAGE 5000
100
 
101
// temperature which is regarded as cold
102
#define COLD_TEMPERATURE 3
103
 
104
// Default timer run time in milli seconds
105
#define WARM_TIMER_RUN_TICKS 240000L
106
 
107
#define COLD_TIMER_RUN_TICKS 600000L
108
 
109
/*
110
 * Register addresses were taken from DM00088500 (STM32F030 datasheet)
111
 * For non-STM32F030 microcontrollers register addresses
112
 * might need to be modified according to the respective datasheet.
113
 */
114
// Temperature sensor raw value at 30 degrees C, VDDA=3.3V
115
#define TEMP30_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFFF7B8))
116
// Internal voltage reference raw value at 30 degrees C, VDDA=3.3V
117
#define VREFINT_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFFF7BA))
118
// internal temperature sensor : 1000 times ADC slope per degree C
119
#define AVG_SLOPE (5336L)
120
/* USER CODE END PD */
121
 
122
/* Private macro -------------------------------------------------------------*/
123
/* USER CODE BEGIN PM */
124
 
125
/* USER CODE END PM */
126
 
127
/* Private variables ---------------------------------------------------------*/
128
ADC_HandleTypeDef hadc;
129
DMA_HandleTypeDef hdma_adc;
130
 
131
TIM_HandleTypeDef htim3;
132
TIM_HandleTypeDef htim14;
133
 
134
WWDG_HandleTypeDef hwwdg;
135
 
136
/* USER CODE BEGIN PV */
137
 
138
// storage for heater status
139
 
140
heaterStatus const ResetHeater = {HEAT_OFF, 0, 0, 0, 0, 0};
141
 
142
heaterStatus HeaterLeft = ResetHeater;
143
heaterStatus HeaterRight = ResetHeater;
144
 
145
#define BACKUP_COPIES 2
146
 
147
heaterStatus __attribute__((section(".persistent"))) BackupLeft[BACKUP_COPIES];
148
heaterStatus __attribute__((section(".persistent"))) BackupRight[BACKUP_COPIES];
149
 
150
// storage for ADC DMA'd samples
151
 
152
uint16_t ADC_Samples[ADC_TMPGRP_BUF_DEPTH * ADC_TEMPGRP_NUM_CHANNELS];
153
 
154
// see https://techoverflow.net/2015/01/13/reading-stm32f0-internal-temperature-and-voltage-using-chibios/
155
typedef struct
156
{
157
  int32_t temperature;
158
  int32_t vdda;
159
  int32_t batteryVoltage;
160
  int32_t dashVoltage;
161
} analogReadings;
162
 
163
analogReadings vals = {0, 0, 0, 0};
164
 
165
/* USER CODE END PV */
166
 
167
/* Private function prototypes -----------------------------------------------*/
168
void SystemClock_Config(void);
169
static void MX_GPIO_Init(void);
170
static void MX_DMA_Init(void);
171
static void MX_ADC_Init(void);
172
static void MX_TIM3_Init(void);
173
static void MX_TIM14_Init(void);
174
static void MX_WWDG_Init(void);
175
/* USER CODE BEGIN PFP */
176
 
177
/* USER CODE END PFP */
178
 
179
/* Private user code ---------------------------------------------------------*/
180
/* USER CODE BEGIN 0 */
181
 
182
void setLEDLeft(uint16_t brightness)
183
{
184
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, brightness);
185
}
186
 
187
void setLEDRight(uint16_t brightness)
188
{
189
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, brightness);
190
}
191
 
192
void setLEDEval(uint16_t brightness)
193
{
194
  __HAL_TIM_SET_COMPARE(&htim14, TIM_CHANNEL_1, brightness);
195
}
196
 
197
void setRelayLeft(heaterControl control)
198
{
199
  HAL_GPIO_WritePin(RelayLeft_GPIO_Port, RelayLeft_Pin, control == HEAT_ON ? GPIO_PIN_SET : GPIO_PIN_RESET);
200
}
201
 
202
void setRelayRight(heaterControl control)
203
{
204
  HAL_GPIO_WritePin(RelayRight_GPIO_Port, RelayRight_Pin, control == HEAT_ON ? GPIO_PIN_SET : GPIO_PIN_RESET);
205
}
206
 
207
// return 1 when button pressed (using NC button)
208
uint8_t getButtonLeft()
209
{
210
  return HAL_GPIO_ReadPin(PushLeft_GPIO_Port, PushLeft_Pin) == GPIO_PIN_SET;
211
}
212
 
213
// return 1 when button pressed (using NC button)
214
uint8_t getButtonRight()
215
{
216
  return HAL_GPIO_ReadPin(PushRight_GPIO_Port, PushRight_Pin) == GPIO_PIN_SET;
217
}
218
 
219
void readTemperatureVDDA(void)
220
{
221
  // NOTE: Computation is performed in 32 bits, but result is converted to 16 bits later.s
222
  /**
223
   * Compute average of temperature sensor raw output
224
   * and vrefint raw output
225
   */
226
 
227
  int32_t tempAvg = 0;
228
  int32_t vrefintAvg = 0;
229
  int32_t batteryAvg = 0;
230
  int32_t dashAvg = 0;
231
  // Samples are alternating: ignition, temp, vrefint, ignition, temp, vrefint, ...
232
  for (int i = 0; i < (ADC_TMPGRP_BUF_DEPTH * ADC_TEMPGRP_NUM_CHANNELS); i += ADC_TEMPGRP_NUM_CHANNELS)
233
  {
234
    batteryAvg += ADC_Samples[i + IGNITION_VOLT_CHAN];
235
    tempAvg += ADC_Samples[i + TEMPERATURE_CHAN];
236
    vrefintAvg += ADC_Samples[i + VREF_CHAN];
237
    dashAvg += ADC_Samples[i + DASHBOARD_VOLT_CHAN];
238
  }
239
  tempAvg /= ADC_TMPGRP_BUF_DEPTH;
240
  vrefintAvg /= ADC_TMPGRP_BUF_DEPTH;
241
  batteryAvg /= ADC_TMPGRP_BUF_DEPTH;
242
  dashAvg /= ADC_TMPGRP_BUF_DEPTH;
243
 
244
  /**
245
   * Compute temperature in celsius
246
   *
247
   * Note that we need to normalize the value first by applying
248
   * the (actual VDDA / VDDARef) ratio.
249
   *
250
   * Note: VDDA_Actual = 3.3V * VREFINT_CAL / vrefintAvg
251
   * Therefore, the ratio mentioned above is equal to
252
   * q = VREFINT_CAL / vrefintAvg
253
   */
254
  int32_t temperature = ((int32_t)*TEMP30_CAL_ADDR - tempAvg) * 1000;
255
 
256
  temperature = temperature / AVG_SLOPE;
257
  temperature = temperature + 30L;
258
 
259
  vals.temperature = temperature;
260
  vals.vdda = (3300 * (*VREFINT_CAL_ADDR)) / vrefintAvg;
261
  vals.batteryVoltage = (IGN_ADC_SCALE * batteryAvg) / 4096 * vals.vdda / 1000; //* 3300 * (*VREFINT_CAL_ADDR)) / batteryAvg);
262
  vals.dashVoltage = (IGN_ADC_SCALE * dashAvg) / 4096 * vals.vdda / 1000;
263
}
264
uint16_t getBatteryVoltage()
265
{
266
  return vals.batteryVoltage;
267
}
268
 
269
int8_t getTemperature()
270
{
271
  return vals.temperature;
272
}
273
 
274
uint16_t getDashVoltage()
275
{
276
  return vals.dashVoltage;
277
}
278
 
279
uint16_t checkSum(heaterStatus *status)
280
{
281
  uint16_t sum = 0xFFFF;
282
  uint8_t *ptr = (uint8_t *)(status);
283
  for (uint8_t *p = ptr; p < ptr + sizeof(heaterStatus) - sizeof(uint16_t); p++)
284
  {
285
    sum *= 41;
286
    sum += *p;
287
  }
288
  return sum;
289
}
290
 
291
/// @brief  Periodic status save into RAM.
292
/// @param status status to save
293
/// @param saveStatus address of array to save status in
294
/// @param iter  iteration of saving
295
/// @return new iteratiom
296
uint8_t saveStatus(heaterStatus *status, heaterStatus *saveStatus, uint8_t iter)
297
{
298
  status->checkSum = checkSum(status);
299
  if (iter >= BACKUP_COPIES)
300
    iter = 0;
301
  saveStatus[iter] = *status;
302
 
303
  iter++;
304
  return iter;
305
}
306
 
307
/// @brief Recover status from RAM after reset/crash
308
/// @param saveStatus pointer to array of saved status
309
/// @return pointer to valid saved or reset status
310
heaterStatus const *recoverStatus(heaterStatus *saveStatus)
311
{
312
  for (int i = 0; i < BACKUP_COPIES; i++)
313
  {
314
    if (saveStatus[i].checkSum == checkSum(saveStatus + i))
315
      return saveStatus + i;
316
  };
317
  // default return a reset state
318
  return &ResetHeater;
319
}
320
 
321
void process(heaterStatus *status, uint8_t button, uint16_t intensity, int8_t temperature, uint16_t battery, uint16_t dashboard)
322
{
323
  // deal with button debounce
324
  uint8_t buttonPressed = 0;
325
  uint8_t longButtonPressed = 0;
326
 
327
  if (button && status->buttonCount < 100)
328
  {
329
    status->buttonCount++;
330
    if (status->buttonCount == 10)
331
      buttonPressed = 1;
332
    if (status->buttonCount == 100)
333
      longButtonPressed = 1;
334
  }
335
  if (!button)
336
    status->buttonCount = 0;
337
 
338
  // deal with LED brightness control
339
 
340
  if (status->LEDintensity < status->LEDtarget)
341
  {
342
    // do an exponential fade up
343
    uint16_t tmp = status->LEDintensity;
344
    tmp *= INTENSITY_STEP;
345
    tmp /= INTENSITY_STEP - 1;
346
    // if nothing happened increment
347
    status->LEDintensity = tmp == status->LEDintensity ? tmp + 1 : tmp;
348
    // handle overshoot
349
    if (status->LEDintensity > status->LEDtarget)
350
      status->LEDintensity = status->LEDtarget;
351
  }
352
  if (status->LEDintensity > status->LEDtarget)
353
  {
354
    // do an exponential fade down
355
    uint16_t tmp = status->LEDintensity;
356
    tmp *= INTENSITY_STEP - 1;
357
    tmp /= INTENSITY_STEP;
358
    // if nothing happened, decrement
359
    status->LEDintensity = tmp == status->LEDintensity ? tmp - 1 : tmp;
360
    // handle undershoot
361
    if (status->LEDintensity < status->LEDtarget)
362
      status->LEDintensity = status->LEDtarget;
363
  }
364
 
365
  // deal with state machine
366
  switch (status->control)
367
  {
368
  case HEAT_OFF: // heater is off
369
    status->LEDtarget = INTENSITY_OFF;
370
    if (buttonPressed)
371
      status->control = HEAT_PENDING;
372
    break;
373
  case HEAT_PENDING: // heater request is pending
374
    status->LEDtarget = intensity;
375
    if (buttonPressed)
376
    {
377
      status->control = HEAT_OFF;
378
      break;
379
    }
380
    if (battery > HEATER_ON_VOLTAGE)
381
    {
382
      // start the timer
383
      status->heatTimer = HAL_GetTick();
384
      status->control = HEAT_ON;
385
      break;
386
    }
387
    break;
388
  case HEAT_ON: // heater is switched on
389
  case HEAT_ON_LOW_VOLT:
390
    // specific conditions
391
    if (status->control == HEAT_ON)
392
    {
393
      if (battery < HEATER_OFF_VOLTAGE)
394
        status->control = HEAT_ON_LOW_VOLT;
395
 
396
      status->LEDtarget = (dashboard > DASH_ON_VOLTAGE) ? INTENSITY_ON : INTENSITY_ON_LOW;
397
    }
398
    if (status->control == HEAT_ON_LOW_VOLT)
399
    {
400
      if (battery > HEATER_ON_VOLTAGE)
401
        status->control = HEAT_ON;
402
 
403
      status->LEDtarget = intensity;
404
    }
405
 
406
    // common code
407
    // press and hold to turn off
408
 
409
    if (longButtonPressed)
410
    {
411
      status->control = HEAT_OFF;
412
      break;
413
    }
414
    // press button to extend time
415
    if (buttonPressed)
416
    {
417
      // restart the timer
418
      status->heatTimer = HAL_GetTick();
419
      break;
420
    }
421
    //  respond to temperature input
422
    uint32_t timeLimit = (temperature < COLD_TEMPERATURE) ? COLD_TIMER_RUN_TICKS : WARM_TIMER_RUN_TICKS;
423
 
424
    if ((HAL_GetTick() - status->heatTimer) > timeLimit)
425
    {
426
      status->control = HEAT_OFF;
427
      break;
428
    }
429
 
430
    break;
431
 
432
    // check timer value here
433
  }
434
}
435
 
436
/* USER CODE END 0 */
437
 
438
/**
439
 * @brief  The application entry point.
440
 * @retval int
441
 */
442
int main(void)
443
{
444
  /* USER CODE BEGIN 1 */
445
  uint8_t saveChannel = 0;
446
 
447
  HeaterLeft = *recoverStatus(BackupLeft);
448
  HeaterRight = *recoverStatus(BackupRight);
449
 
450
  /* USER CODE END 1 */
451
 
452
  /* MCU Configuration--------------------------------------------------------*/
453
 
454
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
455
  HAL_Init();
456
 
457
  /* USER CODE BEGIN Init */
458
 
459
  /* USER CODE END Init */
460
 
461
  /* Configure the system clock */
462
  SystemClock_Config();
463
 
464
  /* USER CODE BEGIN SysInit */
465
 
466
  /* USER CODE END SysInit */
467
 
468
  /* Initialize all configured peripherals */
469
  MX_GPIO_Init();
470
  MX_DMA_Init();
471
  MX_ADC_Init();
472
  MX_TIM3_Init();
473
  MX_TIM14_Init();
474
#if defined WATCHDOG
475
  MX_WWDG_Init();
476
#endif
477
 
478
  /* USER CODE BEGIN 2 */
479
 
480
  HAL_ADC_MspInit(&hadc);
481
 
482
  HAL_ADC_Start_DMA(&hadc, (uint32_t *)ADC_Samples, ADC_TMPGRP_BUF_DEPTH * ADC_TEMPGRP_NUM_CHANNELS);
483
 
484
  HAL_ADC_Start(&hadc);
485
 
486
  // turn on temperature sensor and VREF
487
  ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN;
488
 
489
  // initialise all the STMCubeMX stuff
490
  HAL_TIM_Base_MspInit(&htim3);
491
  HAL_TIM_Base_MspInit(&htim14);
492
  // Start the counter
493
  HAL_TIM_Base_Start(&htim3);
494
  HAL_TIM_Base_Start(&htim14);
495
 
496
  HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_2);
497
  HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_4);
498
 
499
  HAL_TIM_OC_Start(&htim14, TIM_CHANNEL_1);
500
 
501
  int cnt = 0;
502
 
503
  uint16_t intensity = 0;
504
  HeaterLeft.LEDtarget = INTENSITY_OFF;
505
  HeaterRight.LEDtarget = INTENSITY_OFF;
506
 
507
  /* USER CODE END 2 */
508
 
509
  /* Infinite loop */
510
  /* USER CODE BEGIN WHILE */
511
  while (1)
512
  {
513
    readTemperatureVDDA();
514
 
515
    int8_t temperature = getTemperature();
516
    uint16_t batteryVoltage = getBatteryVoltage();
517
    uint16_t dashVoltage = getDashVoltage();
518
 
519
    setLEDLeft(HeaterLeft.LEDintensity);
520
    setLEDRight(HeaterRight.LEDintensity);
521
    setLEDEval(HeaterLeft.LEDintensity);
522
 
523
    setRelayLeft(HeaterLeft.control);
524
    setRelayRight(HeaterRight.control);
525
 
526
    cnt = cnt + 1;
527
    // generate different intensity targets for LED pulsation effect
528
    if ((cnt % 128) == 64)
529
    {
530
      intensity = INTENSITY_STBY_DIM;
531
    }
532
    if ((cnt % 128) == 0)
533
    {
534
      intensity = INTENSITY_STBY_BRIGHT;
535
    }
536
 
537
    process(&HeaterLeft, getButtonLeft(), intensity, temperature, batteryVoltage, dashVoltage);
538
    process(&HeaterRight, getButtonRight(), intensity, temperature, batteryVoltage, dashVoltage);
539
 
540
    /* note the WWDG configuration also needs to be updated if this delay is changed */
541
    HAL_Delay(10);
542
#if defined WATCHDOG
543
    HAL_WWDG_Refresh(&hwwdg);
544
#endif
545
    saveStatus(&HeaterLeft, BackupLeft, saveChannel);
546
    saveChannel = saveStatus(&HeaterRight, BackupRight, saveChannel);
547
 
548
    /* USER CODE END WHILE */
549
 
550
    /* USER CODE BEGIN 3 */
551
  }
552
  /* USER CODE END 3 */
553
}
554
 
555
/**
556
 * @brief System Clock Configuration
557
 * @retval None
558
 */
559
void SystemClock_Config(void)
560
{
561
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
562
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
563
 
564
  /** Initializes the RCC Oscillators according to the specified parameters
565
   * in the RCC_OscInitTypeDef structure.
566
   */
567
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
568
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
569
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
570
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
571
  {
572
    Error_Handler();
573
  }
574
 
575
  /** Initializes the CPU, AHB and APB buses clocks
576
   */
577
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
578
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
579
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
580
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
581
 
582
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
583
  {
584
    Error_Handler();
585
  }
586
}
587
 
588
/**
589
 * @brief ADC Initialization Function
590
 * @param None
591
 * @retval None
592
 */
593
static void MX_ADC_Init(void)
594
{
595
 
596
  /* USER CODE BEGIN ADC_Init 0 */
597
 
598
  /* USER CODE END ADC_Init 0 */
599
 
600
  ADC_ChannelConfTypeDef sConfig = {0};
601
 
602
  /* USER CODE BEGIN ADC_Init 1 */
603
 
604
  /* USER CODE END ADC_Init 1 */
605
 
606
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
607
   */
608
  hadc.Instance = ADC1;
609
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
610
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
611
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
612
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
613
  hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
614
  hadc.Init.LowPowerAutoWait = DISABLE;
615
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
616
  hadc.Init.ContinuousConvMode = DISABLE;
617
  hadc.Init.DiscontinuousConvMode = DISABLE;
618
  hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
619
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
620
  hadc.Init.DMAContinuousRequests = ENABLE;
621
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
622
  if (HAL_ADC_Init(&hadc) != HAL_OK)
623
  {
624
    Error_Handler();
625
  }
626
 
627
  /** Configure for the selected ADC regular channel to be converted.
628
   */
629
  sConfig.Channel = ADC_CHANNEL_0;
630
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
631
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
632
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
633
  {
634
    Error_Handler();
635
  }
636
 
637
  /** Configure for the selected ADC regular channel to be converted.
638
   */
639
  sConfig.Channel = ADC_CHANNEL_1;
640
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
641
  {
642
    Error_Handler();
643
  }
644
 
645
  /** Configure for the selected ADC regular channel to be converted.
646
   */
647
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
648
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
649
  {
650
    Error_Handler();
651
  }
652
 
653
  /** Configure for the selected ADC regular channel to be converted.
654
   */
655
  sConfig.Channel = ADC_CHANNEL_VREFINT;
656
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
657
  {
658
    Error_Handler();
659
  }
660
  /* USER CODE BEGIN ADC_Init 2 */
661
 
662
  /* USER CODE END ADC_Init 2 */
663
}
664
 
665
/**
666
 * @brief TIM3 Initialization Function
667
 * @param None
668
 * @retval None
669
 */
670
static void MX_TIM3_Init(void)
671
{
672
 
673
  /* USER CODE BEGIN TIM3_Init 0 */
674
 
675
  /* USER CODE END TIM3_Init 0 */
676
 
677
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
678
  TIM_MasterConfigTypeDef sMasterConfig = {0};
679
  TIM_OC_InitTypeDef sConfigOC = {0};
680
 
681
  /* USER CODE BEGIN TIM3_Init 1 */
682
 
683
  /* USER CODE END TIM3_Init 1 */
684
  htim3.Instance = TIM3;
685
  htim3.Init.Prescaler = 79;
686
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
687
  htim3.Init.Period = 255;
688
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
689
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
690
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
691
  {
692
    Error_Handler();
693
  }
694
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
695
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
696
  {
697
    Error_Handler();
698
  }
699
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
700
  {
701
    Error_Handler();
702
  }
703
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
704
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
705
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
706
  {
707
    Error_Handler();
708
  }
709
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
710
  sConfigOC.Pulse = 1;
711
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
712
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
713
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
714
  {
715
    Error_Handler();
716
  }
717
  sConfigOC.Pulse = 64;
718
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
719
  {
720
    Error_Handler();
721
  }
722
  /* USER CODE BEGIN TIM3_Init 2 */
723
 
724
  /* USER CODE END TIM3_Init 2 */
725
  HAL_TIM_MspPostInit(&htim3);
726
}
727
 
728
/**
729
 * @brief TIM14 Initialization Function
730
 * @param None
731
 * @retval None
732
 */
733
static void MX_TIM14_Init(void)
734
{
735
 
736
  /* USER CODE BEGIN TIM14_Init 0 */
737
 
738
  /* USER CODE END TIM14_Init 0 */
739
 
740
  TIM_OC_InitTypeDef sConfigOC = {0};
741
 
742
  /* USER CODE BEGIN TIM14_Init 1 */
743
 
744
  /* USER CODE END TIM14_Init 1 */
745
  htim14.Instance = TIM14;
746
  htim14.Init.Prescaler = 79;
747
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
748
  htim14.Init.Period = 255;
749
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
750
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
751
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
752
  {
753
    Error_Handler();
754
  }
755
  if (HAL_TIM_PWM_Init(&htim14) != HAL_OK)
756
  {
757
    Error_Handler();
758
  }
759
  sConfigOC.OCMode = TIM_OCMODE_PWM2;
760
  sConfigOC.Pulse = 128;
761
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
762
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
763
  if (HAL_TIM_PWM_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
764
  {
765
    Error_Handler();
766
  }
767
  /* USER CODE BEGIN TIM14_Init 2 */
768
 
769
  /* USER CODE END TIM14_Init 2 */
770
  HAL_TIM_MspPostInit(&htim14);
771
}
772
 
773
/**
774
 * @brief WWDG Initialization Function
775
 * @param None
776
 * @retval None
777
 */
778
static void MX_WWDG_Init(void)
779
{
780
 
781
  /* USER CODE BEGIN WWDG_Init 0 */
782
 
783
  /* USER CODE END WWDG_Init 0 */
784
 
785
  /* USER CODE BEGIN WWDG_Init 1 */
786
 
787
  /* USER CODE END WWDG_Init 1 */
788
  hwwdg.Instance = WWDG;
789
  hwwdg.Init.Prescaler = WWDG_PRESCALER_1;
790
  hwwdg.Init.Window = 83;
791
  hwwdg.Init.Counter = 93;
792
  hwwdg.Init.EWIMode = WWDG_EWI_DISABLE;
793
  if (HAL_WWDG_Init(&hwwdg) != HAL_OK)
794
  {
795
    Error_Handler();
796
  }
797
  /* USER CODE BEGIN WWDG_Init 2 */
798
 
799
  /* USER CODE END WWDG_Init 2 */
800
}
801
 
802
/**
803
 * Enable DMA controller clock
804
 */
805
static void MX_DMA_Init(void)
806
{
807
 
808
  /* DMA controller clock enable */
809
  __HAL_RCC_DMA1_CLK_ENABLE();
810
 
811
  /* DMA interrupt init */
812
  /* DMA1_Channel1_IRQn interrupt configuration */
813
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
814
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
815
}
816
 
817
/**
818
 * @brief GPIO Initialization Function
819
 * @param None
820
 * @retval None
821
 */
822
static void MX_GPIO_Init(void)
823
{
824
  GPIO_InitTypeDef GPIO_InitStruct = {0};
825
 
826
  /* GPIO Ports Clock Enable */
827
  __HAL_RCC_GPIOF_CLK_ENABLE();
828
  __HAL_RCC_GPIOA_CLK_ENABLE();
829
  __HAL_RCC_GPIOB_CLK_ENABLE();
830
 
831
  /*Configure GPIO pin Output Level */
832
  HAL_GPIO_WritePin(GPIOA, RelayRight_Pin | RelayLeft_Pin, GPIO_PIN_RESET);
833
 
834
  /*Configure GPIO pins : PA2 PA3 PushLeft_Pin */
835
  GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3 | PushLeft_Pin;
836
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
837
  GPIO_InitStruct.Pull = GPIO_PULLUP;
838
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
839
 
840
  /*Configure GPIO pins : RelayRight_Pin RelayLeft_Pin */
841
  GPIO_InitStruct.Pin = RelayRight_Pin | RelayLeft_Pin;
842
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
843
  GPIO_InitStruct.Pull = GPIO_NOPULL;
844
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
845
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
846
 
847
  /*Configure GPIO pin : PushRight_Pin */
848
  GPIO_InitStruct.Pin = PushRight_Pin;
849
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
850
  GPIO_InitStruct.Pull = GPIO_NOPULL;
851
  HAL_GPIO_Init(PushRight_GPIO_Port, &GPIO_InitStruct);
852
}
853
 
854
/* USER CODE BEGIN 4 */
855
 
856
/* USER CODE END 4 */
857
 
858
/**
859
 * @brief  This function is executed in case of error occurrence.
860
 * @retval None
861
 */
862
void Error_Handler(void)
863
{
864
  /* USER CODE BEGIN Error_Handler_Debug */
865
  /* User can add his own implementation to report the HAL error return state */
866
  __disable_irq();
867
  while (1)
868
  {
869
  }
870
  /* USER CODE END Error_Handler_Debug */
871
}
872
 
873
#ifdef USE_FULL_ASSERT
874
/**
875
 * @brief  Reports the name of the source file and the source line number
876
 *         where the assert_param error has occurred.
877
 * @param  file: pointer to the source file name
878
 * @param  line: assert_param error line source number
879
 * @retval None
880
 */
881
void assert_failed(uint8_t *file, uint32_t line)
882
{
883
  /* USER CODE BEGIN 6 */
884
  /* User can add his own implementation to report the file name and line number,
885
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
886
  /* USER CODE END 6 */
887
}
888
#endif /* USE_FULL_ASSERT */