Subversion Repositories ScreenTimer

Rev

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