Subversion Repositories EngineBay2

Rev

Rev 48 | Rev 50 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
38 mjames 1
/* USER CODE BEGIN Header */
2
/**
3
 ******************************************************************************
4
 * @file           : main.c
5
 * @brief          : Main program body
6
 ******************************************************************************
7
 * @attention
8
 *
9
 * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
10
 * All rights reserved.</center></h2>
11
 *
12
 * This software component is licensed by ST under BSD 3-Clause license,
13
 * the "License"; You may not use this file except in compliance with the
14
 * License. You may obtain a copy of the License at:
15
 *                        opensource.org/licenses/BSD-3-Clause
16
 *
17
 ******************************************************************************
18
 */
19
/* USER CODE END Header */
20
/* Includes ------------------------------------------------------------------*/
21
#include "main.h"
22
 
23
/* Private includes ----------------------------------------------------------*/
24
/* USER CODE BEGIN Includes */
49 mjames 25
#include <string.h>
38 mjames 26
#include "libSerial/serial.h"
27
#include "libPLX/plx.h"
28
#include "misc.h"
29
 
48 mjames 30
#include "libIgnTiming/rpm.h"
31
 
38 mjames 32
/* USER CODE END Includes */
33
 
34
/* Private typedef -----------------------------------------------------------*/
35
/* USER CODE BEGIN PTD */
36
 
37
/* USER CODE END PTD */
38
 
39
/* Private define ------------------------------------------------------------*/
40
/* USER CODE BEGIN PD */
41
/* USER CODE END PD */
42
 
43
/* Private macro -------------------------------------------------------------*/
44
/* USER CODE BEGIN PM */
45
#define ADC_CHANNELS 7
46
 
39 mjames 47
#define ADC_MAP_CHAN 2
48
 
49
#define ADC_PRESSURE_CHAN 3
50
 
51
#define ADC_REF_CHAN 5
52
 
53
#define ADC_TEMP_CHAN 6
54
 
38 mjames 55
// wait for about 1 second to decide whether or not starter is on
56
 
57
#define STARTER_LIMIT 10
58
 
59
/* USER CODE END PM */
60
 
61
/* Private variables ---------------------------------------------------------*/
46 mjames 62
ADC_HandleTypeDef hadc1;
38 mjames 63
DMA_HandleTypeDef hdma_adc1;
64
 
65
CAN_HandleTypeDef hcan;
66
 
67
SPI_HandleTypeDef hspi1;
68
 
69
TIM_HandleTypeDef htim2;
70
TIM_HandleTypeDef htim3;
71
TIM_HandleTypeDef htim4;
72
 
73
UART_HandleTypeDef huart1;
74
 
75
/* USER CODE BEGIN PV */
76
 
77
volatile char TimerFlag = 0;
78
 
79
volatile char NoSerialInCTR = 0; // Missing characters coming in on USART1
80
volatile char NoSerialIn = 0;
81
 
49 mjames 82
// an array containing values being one more than incoming index for all observations or zero
83
// if no incoming index
84
char obsIndex[PLX_MAX_OBS];
39 mjames 85
 
38 mjames 86
// storage for ADC
45 mjames 87
uint16_t ADC_Samples[ADC_CHANNELS] = {[0 ... ADC_CHANNELS - 1] = 0};
38 mjames 88
 
45 mjames 89
uint32_t FILT_Samples[ADC_CHANNELS] = {[0 ... ADC_CHANNELS - 1] = 0}; // filtered ADC samples * Scale
38 mjames 90
 
39 mjames 91
#define NOM_VREF 3.3
92
// initial ADC vref
45 mjames 93
float adc_vref = NOM_VREF;
39 mjames 94
 
95
// internal bandgap voltage reference
45 mjames 96
const float STM32REF = 1.2; // 1.2V typical
39 mjames 97
 
98
// scale factor initially assuming
45 mjames 99
float ADC_Scale = 1 / (Scale * 4096) * NOM_VREF;
39 mjames 100
 
38 mjames 101
unsigned int Coded_RPM = 0;
102
unsigned int Coded_CHT = 0;
103
 
42 mjames 104
uint32_t PowerTempTimer;
38 mjames 105
 
106
uint16_t Starter_Debounce = 0;
107
 
108
/* USER CODE END PV */
109
 
110
/* Private function prototypes -----------------------------------------------*/
111
void SystemClock_Config(void);
112
static void MX_GPIO_Init(void);
113
static void MX_DMA_Init(void);
114
static void MX_ADC1_Init(void);
115
static void MX_CAN_Init(void);
116
static void MX_SPI1_Init(void);
117
static void MX_TIM2_Init(void);
118
static void MX_TIM3_Init(void);
119
static void MX_TIM4_Init(void);
120
static void MX_USART1_UART_Init(void);
121
/* USER CODE BEGIN PFP */
122
 
123
/* USER CODE END PFP */
124
 
125
/* Private user code ---------------------------------------------------------*/
126
/* USER CODE BEGIN 0 */
127
 
45 mjames 128
void plx_sendword(int x)
38 mjames 129
{
45 mjames 130
  PutCharSerial(&uc1, ((x) >> 6) & 0x3F);
131
  PutCharSerial(&uc1, (x)&0x3F);
38 mjames 132
}
133
 
45 mjames 134
void filter_ADC_samples()
38 mjames 135
{
136
  int i;
137
  for (i = 0; i < ADC_CHANNELS; i++)
45 mjames 138
  {
139
    FILT_Samples[i] += (ADC_Samples[i] * Scale - FILT_Samples[i]) / 2;
140
  }
38 mjames 141
}
142
 
39 mjames 143
/****!
144
 * @brief this reads the reference voltage within the STM32L151
145
 * Powers up reference voltage and temperature sensor, waits 3mS  and takes reading
146
 * Requires that the ADC be powered up
147
 */
148
 
45 mjames 149
void CalibrateADC(void)
39 mjames 150
{
45 mjames 151
  float adc_val = FILT_Samples[ADC_REF_CHAN]; // as set up in device config
39 mjames 152
 
45 mjames 153
  float adc_vref = STM32REF * (4096.0 * Scale) / adc_val; // the estimate for checking
39 mjames 154
 
45 mjames 155
  ADC_Scale = 1 / (Scale * 4096) * adc_vref;
39 mjames 156
}
157
 
49 mjames 158
void ProcessRPM(void)
38 mjames 159
{
48 mjames 160
  static unsigned int Coded_RPM = 0;
161
  int32_t rpm = CalculateRPM();
162
  if (rpm >= 0)
163
    Coded_RPM = rpm / 19.55;
46 mjames 164
 
45 mjames 165
  // send the current RPM *calculation
166
  plx_sendword(PLX_RPM);
49 mjames 167
  PutCharSerial(&uc1, obsIndex[PLX_RPM]++);
45 mjames 168
  plx_sendword(Coded_RPM / Scale);
38 mjames 169
}
170
 
171
// this uses a MAX6675 which is a simple 16 bit read
172
// SPI is configured for 8 bits so I can use an OLED display if I need it
173
// must wait > 0.22 seconds between conversion attempts as this is the measurement time
174
//
175
 
176
FunctionalState CHT_Enable = ENABLE;
177
 
178
#define CORR 3
179
 
45 mjames 180
uint16_t Temp_Observations[NUM_SPI_TEMP_SENS] = {[0 ... NUM_SPI_TEMP_SENS - 1] = 0};
38 mjames 181
 
42 mjames 182
/// \param item The array index to send
183
/// \param type the code to use for this observation
49 mjames 184
void ProcessTemp(char item, enum PLX_Observations type)
38 mjames 185
{
42 mjames 186
  if (item > NUM_SPI_TEMP_SENS)
187
    return;
45 mjames 188
  plx_sendword(type);
49 mjames 189
  PutCharSerial(&uc1, obsIndex[type]++);
45 mjames 190
  plx_sendword(Temp_Observations[(int)item]);
38 mjames 191
}
192
 
42 mjames 193
/// \brief Reset the temperature chip select system
194
void resetTempCS(void)
195
{
45 mjames 196
  HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_SET);
197
  HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
198
                    GPIO_PIN_SET);
42 mjames 199
 
45 mjames 200
  for (int i = 0; i < 8; i++)
201
  {
202
    HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
203
                      GPIO_PIN_RESET);
204
    HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
205
                      GPIO_PIN_SET);
206
  }
42 mjames 207
 
45 mjames 208
  // prepare for selecting next pin
209
  HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_RESET);
42 mjames 210
}
211
 
212
void nextTempCS(void)
213
{
45 mjames 214
  HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
215
                    GPIO_PIN_RESET);
216
  HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
217
                    GPIO_PIN_SET);
218
  HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_SET);
42 mjames 219
}
220
 
45 mjames 221
void EnableTempSensors(FunctionalState state)
38 mjames 222
 
223
{
224
  GPIO_InitTypeDef GPIO_InitStruct;
225
 
226
  CHT_Enable = state;
227
 
228
  /* enable SPI in live mode : assume it and its GPIOs are already initialised in SPI mode */
229
  if (state == ENABLE)
45 mjames 230
  {
231
    HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_SET);
38 mjames 232
 
45 mjames 233
    resetTempCS();
42 mjames 234
 
45 mjames 235
    /* put the SPI pins back into SPI AF mode */
236
    GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
237
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
238
    GPIO_InitStruct.Pull = GPIO_NOPULL;
239
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
240
    HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
241
  }
38 mjames 242
  else
45 mjames 243
  {
244
    /*  Power down the SPI interface taking signals all low */
245
    HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_RESET);
38 mjames 246
 
45 mjames 247
    HAL_GPIO_WritePin(SPI1_SCK_GPIO_Port,
248
                      SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin,
249
                      GPIO_PIN_RESET);
38 mjames 250
 
45 mjames 251
    /* put the SPI pins back into GPIO mode */
252
    GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
253
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
254
    GPIO_InitStruct.Pull = GPIO_NOPULL;
255
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
256
    HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
257
  }
38 mjames 258
}
259
 
260
// 1023 is 20.00 volts.
49 mjames 261
/// \param item - used to lookup the index of the local reading
262
void ProcessBatteryVoltage(int item)
38 mjames 263
{
49 mjames 264
  float reading = FILT_Samples[item] * ADC_Scale;
38 mjames 265
  reading = reading * 7.8125; // real voltage
45 mjames 266
  reading = reading * 51.15;  // PLC scaling =  1023/20
38 mjames 267
 
45 mjames 268
  plx_sendword(PLX_Volts);
49 mjames 269
  PutCharSerial(&uc1, obsIndex[PLX_Volts]++);
45 mjames 270
  plx_sendword((uint16_t)reading);
38 mjames 271
}
272
 
49 mjames 273
void ProcessCPUTemperature(void)
38 mjames 274
{
45 mjames 275
  // this is defined in the STM32F103 reference manual . #
39 mjames 276
  // V25 = 1.43 volts
277
  // Avg_slope = 4.3mV /degree C
278
  // temperature = {(V25 - VSENSE) / Avg_Slope} + 25
38 mjames 279
 
280
  /* get the ADC reading corresponding to ADC channel 16 after turning on the ADC */
281
 
39 mjames 282
  float temp_val = FILT_Samples[ADC_TEMP_CHAN] * ADC_Scale;
38 mjames 283
  /* renormalise temperature value to account for different ADC Vref  : normalise to that which we would get for a 3000mV reference */
45 mjames 284
  temp_val = (1.43 - temp_val) / 4.3e-3 + 25;
38 mjames 285
 
45 mjames 286
  int32_t result = temp_val;
38 mjames 287
 
45 mjames 288
  //  int32_t result = 800 * ((int32_t) temp_val - TS_CAL30);
289
  //  result = result / (TS_CAL110 - TS_CAL30) + 300;
39 mjames 290
 
45 mjames 291
  plx_sendword(PLX_FluidTemp);
49 mjames 292
  PutCharSerial(&uc1, obsIndex[PLX_FluidTemp]++);
45 mjames 293
  plx_sendword(result);
38 mjames 294
}
295
 
296
// the MAP sensor is giving us a reading of
297
// 4.6 volts for 1019mB or 2.27 volts at the ADC input (resistive divider by 2.016)
298
// I believe the sensor reads  4.5V at 1000kPa and 0.5V at  0kPa
299
// Calibration is a bit off
300
// Real   Displayed
301
// 989    968
302
// 994.1    986
303
// 992.3  984
304
 
49 mjames 305
void ProcessMAP(void)
38 mjames 306
{
45 mjames 307
  // Using ADC_Samples[3] as the MAP input
39 mjames 308
  float reading = FILT_Samples[ADC_MAP_CHAN] * ADC_Scale;
45 mjames 309
  reading = reading * 2.016; // real voltage
38 mjames 310
  // values computed from slope / intercept of map.ods
45 mjames 311
  // reading = (reading) * 56.23 + 743.2; // do not assume 0.5 volt offset : reading from 0 to 4.5 instead of 0.5 to 4.5
38 mjames 312
  // using a pressure gauge.
45 mjames 313
  reading = (reading)*150 + 326;
38 mjames 314
 
45 mjames 315
  plx_sendword(PLX_MAP);
49 mjames 316
  PutCharSerial(&uc1, obsIndex[PLX_MAP]++);
45 mjames 317
  plx_sendword((uint16_t)reading);
38 mjames 318
}
319
 
320
// the Oil pressi sensor is giving us a reading of
321
// 4.5 volts for 100 PSI or  2.25 volts at the ADC input (resistive divider by 2.016)
322
// I believe the sensor reads  4.5V at 100PSI and 0.5V at  0PSI
323
// an observation of 1024 is 200PSI, so observation of 512 is 100 PSI.
324
 
49 mjames 325
void ProcessOilPress(void)
38 mjames 326
{
45 mjames 327
  // Using ADC_Samples[2] as the MAP input
39 mjames 328
  float reading = FILT_Samples[ADC_PRESSURE_CHAN] * ADC_Scale;
45 mjames 329
  reading = reading * 2.00;            // real voltage
330
  reading = (reading - 0.5) * 512 / 4; // this is 1023 * 100/200
38 mjames 331
 
45 mjames 332
  plx_sendword(PLX_FluidPressure);
49 mjames 333
  PutCharSerial(&uc1, obsIndex[PLX_FluidPressure]++);
45 mjames 334
  plx_sendword((uint16_t)reading);
38 mjames 335
}
336
 
49 mjames 337
void ProcessTiming(void)
38 mjames 338
{
45 mjames 339
  plx_sendword(PLX_Timing);
49 mjames 340
  PutCharSerial(&uc1, obsIndex[PLX_Timing]++);
45 mjames 341
  plx_sendword(64 - 15); // make it negative
38 mjames 342
}
343
 
344
/* USER CODE END 0 */
345
 
346
/**
46 mjames 347
 * @brief  The application entry point.
348
 * @retval int
349
 */
38 mjames 350
int main(void)
351
{
352
  /* USER CODE BEGIN 1 */
353
 
354
  /* USER CODE END 1 */
355
 
356
  /* MCU Configuration--------------------------------------------------------*/
357
 
358
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
359
  HAL_Init();
360
 
361
  /* USER CODE BEGIN Init */
362
 
363
  /* USER CODE END Init */
364
 
365
  /* Configure the system clock */
366
  SystemClock_Config();
367
 
368
  /* USER CODE BEGIN SysInit */
369
 
370
  /* USER CODE END SysInit */
371
 
372
  /* Initialize all configured peripherals */
373
  MX_GPIO_Init();
374
  MX_DMA_Init();
375
  MX_ADC1_Init();
376
  MX_CAN_Init();
377
  MX_SPI1_Init();
378
  MX_TIM2_Init();
379
  MX_TIM3_Init();
380
  MX_TIM4_Init();
381
  MX_USART1_UART_Init();
382
  /* USER CODE BEGIN 2 */
45 mjames 383
  HAL_MspInit();
38 mjames 384
 
385
  // Not using HAL USART code
45 mjames 386
  __HAL_RCC_USART1_CLK_ENABLE(); // PLX comms port
38 mjames 387
  /* setup the USART control blocks */
45 mjames 388
  init_usart_ctl(&uc1, &huart1);
38 mjames 389
 
45 mjames 390
  EnableSerialRxInterrupt(&uc1);
38 mjames 391
 
45 mjames 392
  HAL_SPI_MspInit(&hspi1);
38 mjames 393
 
45 mjames 394
  HAL_ADC_MspInit(&hadc1);
38 mjames 395
 
45 mjames 396
  HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Samples, ADC_CHANNELS);
38 mjames 397
 
45 mjames 398
  HAL_ADC_Start_IT(&hadc1);
38 mjames 399
 
45 mjames 400
  HAL_TIM_Base_MspInit(&htim4);
401
  HAL_TIM_Base_Start_IT(&htim4);
38 mjames 402
 
403
  // initialise all the STMCubeMX stuff
45 mjames 404
  HAL_TIM_Base_MspInit(&htim2);
38 mjames 405
  // Start the counter
45 mjames 406
  HAL_TIM_Base_Start(&htim2);
41 mjames 407
  // Start the input capture and the rising edge interrupt
45 mjames 408
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
41 mjames 409
  // Start the input capture and the falling edge interrupt
45 mjames 410
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
38 mjames 411
 
45 mjames 412
  HAL_TIM_Base_MspInit(&htim3);
38 mjames 413
  __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
45 mjames 414
  uint32_t Ticks = HAL_GetTick() + 100;
38 mjames 415
  int CalCounter = 0;
416
 
45 mjames 417
  PowerTempTimer = HAL_GetTick() + 1000; /* wait 10 seconds before powering up the CHT sensor */
38 mjames 418
 
45 mjames 419
  ResetRxBuffer(&uc1);
49 mjames 420
 
421
  PLX_SensorInfo info; ///< sensor info structure for getting idents
422
 
423
  memset(obsIndex, 0, PLX_MAX_OBS); // zero incoming obsevation index
424
  int infoCount = -1;               ///< counting bytes when we are copying them across
38 mjames 425
  /* USER CODE END 2 */
426
 
427
  /* Infinite loop */
428
  /* USER CODE BEGIN WHILE */
429
  while (1)
45 mjames 430
  {
38 mjames 431
    /* USER CODE END WHILE */
432
 
433
    /* USER CODE BEGIN 3 */
434
 
45 mjames 435
    if (HAL_GetTick() > Ticks)
436
    {
437
      Ticks += 100;
438
      filter_ADC_samples();
439
      // delay to calibrate ADC
440
      if (CalCounter < 1000)
441
      {
442
        CalCounter += 100;
443
      }
38 mjames 444
 
45 mjames 445
      if (CalCounter == 900)
446
      {
447
        CalibrateADC();
448
      }
449
    }
450
    /* when the starter motor is on then power down the CHT sensors as they seem to fail */
38 mjames 451
 
45 mjames 452
    if (HAL_GPIO_ReadPin(STARTER_ON_GPIO_Port, STARTER_ON_Pin) == GPIO_PIN_RESET)
453
    {
454
      if (Starter_Debounce < STARTER_LIMIT)
455
      {
456
        Starter_Debounce++;
457
      }
458
    }
459
    else
460
    {
461
      if (Starter_Debounce > 0)
462
      {
463
        Starter_Debounce--;
464
      }
465
    }
38 mjames 466
 
45 mjames 467
    if (Starter_Debounce == STARTER_LIMIT)
468
    {
469
      EnableTempSensors(DISABLE);
470
      PowerTempTimer = HAL_GetTick() + 1000;
471
    }
472
    else
473
    /* if the PowerTempTimer is set then wait for it to timeout, then power up CHT */
474
    {
475
      if ((PowerTempTimer > 0) && (HAL_GetTick() > PowerTempTimer))
476
      {
477
        EnableTempSensors(ENABLE);
478
        PowerTempTimer = 0;
479
      }
480
    }
38 mjames 481
 
45 mjames 482
    // check to see if we have any incoming data, copy and append if so, if no data then create our own frames.
483
    char send = 0;
38 mjames 484
 
45 mjames 485
    // poll the  input for a stop bit or timeout
486
    if (PollSerial(&uc1))
487
    {
488
      resetSerialTimeout();
49 mjames 489
      uint8_t c = GetCharSerial(&uc1);
490
      // code added to read in all data, extract the observation index maximum for each type of data
491
      if (c == PLX_Start)
492
      {
493
        infoCount = 0;
494
      }
495
      else
496
      {
497
        info.bytes[infoCount++] = c;
498
        // process the sensor info field : discover maximum observation index
499
        if (infoCount == sizeof(PLX_SensorInfo))
500
        {
501
          infoCount = 0;
502
          int addr = ConvPLXAddr(&info);
503
          if (addr < PLX_MAX_OBS && (obsIndex[addr] <= info.Instance))
504
            obsIndex[addr] = info.Instance + 1;
505
        }
506
      }
507
 
45 mjames 508
      if (c != PLX_Stop)
509
      {
510
        PutCharSerial(&uc1, c); // echo all but the stop bit
511
      }
512
      else
513
      {           // must be a stop character
514
        send = 1; // start our sending process.
515
      }
516
    }
38 mjames 517
 
45 mjames 518
    // sort out auto-sending
519
    if (TimerFlag)
520
    {
521
      TimerFlag = 0;
522
      if (NoSerialIn)
523
      {
524
        PutCharSerial(&uc1, PLX_Start);
525
        send = 1;
526
      }
527
    }
528
    if (send)
529
    {
530
      send = 0;
38 mjames 531
 
45 mjames 532
      // send the observations
49 mjames 533
      ProcessRPM();
534
      ProcessTemp(0, PLX_X_CHT);
535
      ProcessTemp(1, PLX_X_CHT);
536
      ProcessTemp(2, PLX_AIT);
537
      ProcessTemp(3, PLX_AIT);
45 mjames 538
      ProcessBatteryVoltage(0); // Batt 1
539
      ProcessBatteryVoltage(1); // Batt 2
49 mjames 540
      ProcessCPUTemperature();  //  built in temperature sensor
38 mjames 541
 
49 mjames 542
      ProcessMAP();
543
      ProcessOilPress();
544
      memset(obsIndex, 0, PLX_MAX_OBS); // zero incoming obsevation index
38 mjames 545
 
45 mjames 546
      PutCharSerial(&uc1, PLX_Stop);
38 mjames 547
    }
45 mjames 548
  }
38 mjames 549
 
550
  /* USER CODE END 3 */
551
}
552
 
553
/**
46 mjames 554
 * @brief System Clock Configuration
555
 * @retval None
556
 */
38 mjames 557
void SystemClock_Config(void)
558
{
559
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
560
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
561
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
562
 
563
  /** Initializes the RCC Oscillators according to the specified parameters
46 mjames 564
   * in the RCC_OscInitTypeDef structure.
565
   */
38 mjames 566
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
567
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
568
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
569
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
570
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
571
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
572
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
573
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
574
  {
575
    Error_Handler();
576
  }
45 mjames 577
 
38 mjames 578
  /** Initializes the CPU, AHB and APB buses clocks
46 mjames 579
   */
580
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
38 mjames 581
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
582
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
583
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
584
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
585
 
586
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
587
  {
588
    Error_Handler();
589
  }
590
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
591
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
592
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
593
  {
594
    Error_Handler();
595
  }
596
}
597
 
598
/**
46 mjames 599
 * @brief ADC1 Initialization Function
600
 * @param None
601
 * @retval None
602
 */
38 mjames 603
static void MX_ADC1_Init(void)
604
{
605
 
606
  /* USER CODE BEGIN ADC1_Init 0 */
607
 
608
  /* USER CODE END ADC1_Init 0 */
609
 
610
  ADC_ChannelConfTypeDef sConfig = {0};
611
 
612
  /* USER CODE BEGIN ADC1_Init 1 */
613
 
614
  /* USER CODE END ADC1_Init 1 */
45 mjames 615
 
38 mjames 616
  /** Common config
46 mjames 617
   */
38 mjames 618
  hadc1.Instance = ADC1;
619
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
620
  hadc1.Init.ContinuousConvMode = DISABLE;
621
  hadc1.Init.DiscontinuousConvMode = DISABLE;
622
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
623
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
624
  hadc1.Init.NbrOfConversion = 7;
625
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
626
  {
627
    Error_Handler();
628
  }
45 mjames 629
 
38 mjames 630
  /** Configure Regular Channel
46 mjames 631
   */
38 mjames 632
  sConfig.Channel = ADC_CHANNEL_0;
633
  sConfig.Rank = ADC_REGULAR_RANK_1;
39 mjames 634
  sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
38 mjames 635
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
636
  {
637
    Error_Handler();
638
  }
45 mjames 639
 
38 mjames 640
  /** Configure Regular Channel
46 mjames 641
   */
38 mjames 642
  sConfig.Channel = ADC_CHANNEL_1;
643
  sConfig.Rank = ADC_REGULAR_RANK_2;
644
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
645
  {
646
    Error_Handler();
647
  }
45 mjames 648
 
38 mjames 649
  /** Configure Regular Channel
46 mjames 650
   */
38 mjames 651
  sConfig.Channel = ADC_CHANNEL_2;
652
  sConfig.Rank = ADC_REGULAR_RANK_3;
653
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
654
  {
655
    Error_Handler();
656
  }
45 mjames 657
 
38 mjames 658
  /** Configure Regular Channel
46 mjames 659
   */
38 mjames 660
  sConfig.Channel = ADC_CHANNEL_3;
661
  sConfig.Rank = ADC_REGULAR_RANK_4;
662
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
663
  {
664
    Error_Handler();
665
  }
45 mjames 666
 
38 mjames 667
  /** Configure Regular Channel
46 mjames 668
   */
39 mjames 669
  sConfig.Channel = ADC_CHANNEL_4;
38 mjames 670
  sConfig.Rank = ADC_REGULAR_RANK_5;
671
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
672
  {
673
    Error_Handler();
674
  }
45 mjames 675
 
38 mjames 676
  /** Configure Regular Channel
46 mjames 677
   */
38 mjames 678
  sConfig.Channel = ADC_CHANNEL_VREFINT;
679
  sConfig.Rank = ADC_REGULAR_RANK_6;
680
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
681
  {
682
    Error_Handler();
683
  }
45 mjames 684
 
38 mjames 685
  /** Configure Regular Channel
46 mjames 686
   */
39 mjames 687
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
38 mjames 688
  sConfig.Rank = ADC_REGULAR_RANK_7;
689
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
690
  {
691
    Error_Handler();
692
  }
693
  /* USER CODE BEGIN ADC1_Init 2 */
694
 
695
  /* USER CODE END ADC1_Init 2 */
696
}
697
 
698
/**
46 mjames 699
 * @brief CAN Initialization Function
700
 * @param None
701
 * @retval None
702
 */
38 mjames 703
static void MX_CAN_Init(void)
704
{
705
 
706
  /* USER CODE BEGIN CAN_Init 0 */
707
 
708
  /* USER CODE END CAN_Init 0 */
709
 
710
  /* USER CODE BEGIN CAN_Init 1 */
711
 
712
  /* USER CODE END CAN_Init 1 */
713
  hcan.Instance = CAN1;
714
  hcan.Init.Prescaler = 16;
715
  hcan.Init.Mode = CAN_MODE_NORMAL;
716
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
717
  hcan.Init.TimeSeg1 = CAN_BS1_1TQ;
718
  hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
719
  hcan.Init.TimeTriggeredMode = DISABLE;
720
  hcan.Init.AutoBusOff = DISABLE;
721
  hcan.Init.AutoWakeUp = DISABLE;
722
  hcan.Init.AutoRetransmission = DISABLE;
723
  hcan.Init.ReceiveFifoLocked = DISABLE;
724
  hcan.Init.TransmitFifoPriority = DISABLE;
725
  if (HAL_CAN_Init(&hcan) != HAL_OK)
726
  {
727
    Error_Handler();
728
  }
729
  /* USER CODE BEGIN CAN_Init 2 */
730
 
731
  /* USER CODE END CAN_Init 2 */
732
}
733
 
734
/**
46 mjames 735
 * @brief SPI1 Initialization Function
736
 * @param None
737
 * @retval None
738
 */
38 mjames 739
static void MX_SPI1_Init(void)
740
{
741
 
742
  /* USER CODE BEGIN SPI1_Init 0 */
743
 
744
  /* USER CODE END SPI1_Init 0 */
745
 
746
  /* USER CODE BEGIN SPI1_Init 1 */
747
 
748
  /* USER CODE END SPI1_Init 1 */
749
  /* SPI1 parameter configuration*/
750
  hspi1.Instance = SPI1;
751
  hspi1.Init.Mode = SPI_MODE_MASTER;
752
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
753
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
754
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
755
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
756
  hspi1.Init.NSS = SPI_NSS_SOFT;
41 mjames 757
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
38 mjames 758
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
759
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
760
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
761
  hspi1.Init.CRCPolynomial = 10;
762
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
763
  {
764
    Error_Handler();
765
  }
766
  /* USER CODE BEGIN SPI1_Init 2 */
767
 
768
  /* USER CODE END SPI1_Init 2 */
769
}
770
 
771
/**
46 mjames 772
 * @brief TIM2 Initialization Function
773
 * @param None
774
 * @retval None
775
 */
38 mjames 776
static void MX_TIM2_Init(void)
777
{
778
 
779
  /* USER CODE BEGIN TIM2_Init 0 */
780
 
781
  /* USER CODE END TIM2_Init 0 */
782
 
783
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
784
  TIM_MasterConfigTypeDef sMasterConfig = {0};
785
  TIM_IC_InitTypeDef sConfigIC = {0};
786
 
787
  /* USER CODE BEGIN TIM2_Init 1 */
788
 
789
  /* USER CODE END TIM2_Init 1 */
790
  htim2.Instance = TIM2;
41 mjames 791
  htim2.Init.Prescaler = 719;
38 mjames 792
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
793
  htim2.Init.Period = 65535;
794
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
795
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
796
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
797
  {
798
    Error_Handler();
799
  }
800
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
801
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
802
  {
803
    Error_Handler();
804
  }
805
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
806
  {
807
    Error_Handler();
808
  }
809
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
810
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
811
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
812
  {
813
    Error_Handler();
814
  }
815
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
816
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
817
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
818
  sConfigIC.ICFilter = 15;
819
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
820
  {
821
    Error_Handler();
822
  }
41 mjames 823
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
824
  sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
825
  sConfigIC.ICFilter = 0;
826
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
827
  {
828
    Error_Handler();
829
  }
38 mjames 830
  /* USER CODE BEGIN TIM2_Init 2 */
831
 
832
  /* USER CODE END TIM2_Init 2 */
833
}
834
 
835
/**
46 mjames 836
 * @brief TIM3 Initialization Function
837
 * @param None
838
 * @retval None
839
 */
38 mjames 840
static void MX_TIM3_Init(void)
841
{
842
 
843
  /* USER CODE BEGIN TIM3_Init 0 */
844
 
845
  /* USER CODE END TIM3_Init 0 */
846
 
847
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
848
  TIM_MasterConfigTypeDef sMasterConfig = {0};
849
  TIM_OC_InitTypeDef sConfigOC = {0};
850
 
851
  /* USER CODE BEGIN TIM3_Init 1 */
852
 
853
  /* USER CODE END TIM3_Init 1 */
854
  htim3.Instance = TIM3;
41 mjames 855
  htim3.Init.Prescaler = 719;
38 mjames 856
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
41 mjames 857
  htim3.Init.Period = 199;
38 mjames 858
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
859
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
860
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
861
  {
862
    Error_Handler();
863
  }
864
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
865
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
866
  {
867
    Error_Handler();
868
  }
869
  if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
870
  {
871
    Error_Handler();
872
  }
873
  if (HAL_TIM_OnePulse_Init(&htim3, TIM_OPMODE_SINGLE) != HAL_OK)
874
  {
875
    Error_Handler();
876
  }
877
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
878
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
879
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
880
  {
881
    Error_Handler();
882
  }
883
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
41 mjames 884
  sConfigOC.Pulse = 198;
38 mjames 885
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
886
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
887
  if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
888
  {
889
    Error_Handler();
890
  }
891
  /* USER CODE BEGIN TIM3_Init 2 */
892
 
893
  /* USER CODE END TIM3_Init 2 */
894
}
895
 
896
/**
46 mjames 897
 * @brief TIM4 Initialization Function
898
 * @param None
899
 * @retval None
900
 */
38 mjames 901
static void MX_TIM4_Init(void)
902
{
903
 
904
  /* USER CODE BEGIN TIM4_Init 0 */
905
 
906
  /* USER CODE END TIM4_Init 0 */
907
 
908
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
909
  TIM_MasterConfigTypeDef sMasterConfig = {0};
910
 
911
  /* USER CODE BEGIN TIM4_Init 1 */
912
 
913
  /* USER CODE END TIM4_Init 1 */
914
  htim4.Instance = TIM4;
41 mjames 915
  htim4.Init.Prescaler = 719;
38 mjames 916
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
917
  htim4.Init.Period = 9999;
918
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
919
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
920
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
921
  {
922
    Error_Handler();
923
  }
924
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
925
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
926
  {
927
    Error_Handler();
928
  }
929
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
930
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
931
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
932
  {
933
    Error_Handler();
934
  }
935
  /* USER CODE BEGIN TIM4_Init 2 */
936
 
937
  /* USER CODE END TIM4_Init 2 */
938
}
939
 
940
/**
46 mjames 941
 * @brief USART1 Initialization Function
942
 * @param None
943
 * @retval None
944
 */
38 mjames 945
static void MX_USART1_UART_Init(void)
946
{
947
 
948
  /* USER CODE BEGIN USART1_Init 0 */
949
 
950
  /* USER CODE END USART1_Init 0 */
951
 
952
  /* USER CODE BEGIN USART1_Init 1 */
953
 
954
  /* USER CODE END USART1_Init 1 */
955
  huart1.Instance = USART1;
956
  huart1.Init.BaudRate = 19200;
957
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
958
  huart1.Init.StopBits = UART_STOPBITS_1;
959
  huart1.Init.Parity = UART_PARITY_NONE;
960
  huart1.Init.Mode = UART_MODE_TX_RX;
961
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
962
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
963
  if (HAL_UART_Init(&huart1) != HAL_OK)
964
  {
965
    Error_Handler();
966
  }
967
  /* USER CODE BEGIN USART1_Init 2 */
968
 
969
  /* USER CODE END USART1_Init 2 */
970
}
971
 
972
/**
46 mjames 973
 * Enable DMA controller clock
974
 */
38 mjames 975
static void MX_DMA_Init(void)
976
{
977
 
978
  /* DMA controller clock enable */
979
  __HAL_RCC_DMA1_CLK_ENABLE();
980
 
981
  /* DMA interrupt init */
982
  /* DMA1_Channel1_IRQn interrupt configuration */
983
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
984
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
985
}
986
 
987
/**
46 mjames 988
 * @brief GPIO Initialization Function
989
 * @param None
990
 * @retval None
991
 */
38 mjames 992
static void MX_GPIO_Init(void)
993
{
994
  GPIO_InitTypeDef GPIO_InitStruct = {0};
995
 
996
  /* GPIO Ports Clock Enable */
997
  __HAL_RCC_GPIOC_CLK_ENABLE();
998
  __HAL_RCC_GPIOD_CLK_ENABLE();
999
  __HAL_RCC_GPIOA_CLK_ENABLE();
1000
  __HAL_RCC_GPIOB_CLK_ENABLE();
1001
 
1002
  /*Configure GPIO pin Output Level */
1003
  HAL_GPIO_WritePin(LED_Blink_GPIO_Port, LED_Blink_Pin, GPIO_PIN_RESET);
1004
 
1005
  /*Configure GPIO pin Output Level */
46 mjames 1006
  HAL_GPIO_WritePin(GPIOB, SPI_CS_Clk_Pin | SPI_CS_D_Pin | ENA_AUX_5V_Pin, GPIO_PIN_RESET);
38 mjames 1007
 
1008
  /*Configure GPIO pin : LED_Blink_Pin */
1009
  GPIO_InitStruct.Pin = LED_Blink_Pin;
1010
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
1011
  GPIO_InitStruct.Pull = GPIO_NOPULL;
1012
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
1013
  HAL_GPIO_Init(LED_Blink_GPIO_Port, &GPIO_InitStruct);
1014
 
43 mjames 1015
  /*Configure GPIO pins : SPI_CS_Clk_Pin SPI_CS_D_Pin ENA_AUX_5V_Pin */
46 mjames 1016
  GPIO_InitStruct.Pin = SPI_CS_Clk_Pin | SPI_CS_D_Pin | ENA_AUX_5V_Pin;
38 mjames 1017
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
1018
  GPIO_InitStruct.Pull = GPIO_NOPULL;
1019
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
1020
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
1021
 
1022
  /*Configure GPIO pin : STARTER_ON_Pin */
1023
  GPIO_InitStruct.Pin = STARTER_ON_Pin;
1024
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
1025
  GPIO_InitStruct.Pull = GPIO_NOPULL;
1026
  HAL_GPIO_Init(STARTER_ON_GPIO_Port, &GPIO_InitStruct);
1027
}
1028
 
1029
/* USER CODE BEGIN 4 */
1030
 
1031
/* USER CODE END 4 */
1032
 
1033
/**
46 mjames 1034
 * @brief  This function is executed in case of error occurrence.
1035
 * @retval None
1036
 */
38 mjames 1037
void Error_Handler(void)
1038
{
1039
  /* USER CODE BEGIN Error_Handler_Debug */
45 mjames 1040
  /* User can add his own implementation to report the HAL error return state */
38 mjames 1041
 
1042
  /* USER CODE END Error_Handler_Debug */
1043
}
1044
 
46 mjames 1045
#ifdef USE_FULL_ASSERT
38 mjames 1046
/**
46 mjames 1047
 * @brief  Reports the name of the source file and the source line number
1048
 *         where the assert_param error has occurred.
1049
 * @param  file: pointer to the source file name
1050
 * @param  line: assert_param error line source number
1051
 * @retval None
1052
 */
38 mjames 1053
void assert_failed(uint8_t *file, uint32_t line)
1054
{
1055
  /* USER CODE BEGIN 6 */
1056
  /* User can add his own implementation to report the file name and line number,
1057
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
1058
  /* USER CODE END 6 */
1059
}
1060
#endif /* USE_FULL_ASSERT */