// Define to prevent recursive inclusion #ifndef SETUP_H #define SETUP_H #include "stm32f4xx_hal.h" TIM_HandleTypeDef htim_right; TIM_HandleTypeDef htim_left; ADC_HandleTypeDef hadc; I2C_HandleTypeDef hi2c1; volatile adc_buf_t adc_buffer; extern board_t board; void MX_GPIO_Clocks_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_CAN1_CLK_ENABLE(); __HAL_RCC_CAN2_CLK_ENABLE(); } void MX_GPIO_Common_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = { 0 }; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Pin = board.hall_left.hall_pinA; HAL_GPIO_Init(board.hall_left.hall_portA, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.hall_left.hall_pinB; HAL_GPIO_Init(board.hall_left.hall_portB, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.hall_left.hall_pinC; HAL_GPIO_Init(board.hall_left.hall_portC, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.hall_right.hall_pinA; HAL_GPIO_Init(board.hall_right.hall_portA, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.hall_right.hall_pinB; HAL_GPIO_Init(board.hall_right.hall_portB, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.hall_right.hall_pinC; HAL_GPIO_Init(board.hall_right.hall_portC, &GPIO_InitStruct); GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pin = CHARGER_PIN; HAL_GPIO_Init(CHARGER_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pin = BUTTON_PIN; HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pin = board.led_pinR; HAL_GPIO_Init(board.led_portR, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.led_pinG; HAL_GPIO_Init(board.led_portG, &GPIO_InitStruct); GPIO_InitStruct.Pin = board.led_pinB; HAL_GPIO_Init(board.led_portB, &GPIO_InitStruct); if (board.can_pinEN != 0) { GPIO_InitStruct.Pin = board.can_pinEN; HAL_GPIO_Init(board.can_portEN, &GPIO_InitStruct); } if (board.ignition_pin != 0) { GPIO_InitStruct.Pin = board.ignition_pin; HAL_GPIO_Init(board.ignition_port, &GPIO_InitStruct); } GPIO_InitStruct.Pin = BUZZER_PIN; HAL_GPIO_Init(BUZZER_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = OFF_PIN; HAL_GPIO_Init(OFF_PORT, &GPIO_InitStruct); GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pin = LEFT_DC_CUR_PIN; HAL_GPIO_Init(LEFT_DC_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_U_CUR_PIN; HAL_GPIO_Init(LEFT_U_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_V_CUR_PIN; HAL_GPIO_Init(LEFT_V_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_DC_CUR_PIN; HAL_GPIO_Init(RIGHT_DC_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_U_CUR_PIN; HAL_GPIO_Init(RIGHT_U_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_V_CUR_PIN; HAL_GPIO_Init(RIGHT_V_CUR_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = BATT_PIN; HAL_GPIO_Init(BATT_PORT, &GPIO_InitStruct); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Alternate = GPIO_AF3_TIM8; GPIO_InitStruct.Pin = LEFT_TIM_UH_PIN; HAL_GPIO_Init(LEFT_TIM_UH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_TIM_VH_PIN; HAL_GPIO_Init(LEFT_TIM_VH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_TIM_WH_PIN; HAL_GPIO_Init(LEFT_TIM_WH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_TIM_UL_PIN; HAL_GPIO_Init(LEFT_TIM_UL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_TIM_VL_PIN; HAL_GPIO_Init(LEFT_TIM_VL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = LEFT_TIM_WL_PIN; HAL_GPIO_Init(LEFT_TIM_WL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; GPIO_InitStruct.Pin = RIGHT_TIM_UH_PIN; HAL_GPIO_Init(RIGHT_TIM_UH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_TIM_VH_PIN; HAL_GPIO_Init(RIGHT_TIM_VH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_TIM_WH_PIN; HAL_GPIO_Init(RIGHT_TIM_WH_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_TIM_UL_PIN; HAL_GPIO_Init(RIGHT_TIM_UL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_TIM_VL_PIN; HAL_GPIO_Init(RIGHT_TIM_VL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = RIGHT_TIM_WL_PIN; HAL_GPIO_Init(RIGHT_TIM_WL_PORT, &GPIO_InitStruct); // CAN bus GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = board.can_alt_rx; GPIO_InitStruct.Pin = board.can_pinRX; HAL_GPIO_Init(board.can_portRX, &GPIO_InitStruct); GPIO_InitStruct.Alternate = board.can_alt_tx; GPIO_InitStruct.Pin = board.can_pinTX; HAL_GPIO_Init(board.can_portTX, &GPIO_InitStruct); } void MX_I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = { 0 }; GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); __HAL_RCC_I2C1_CLK_ENABLE(); hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = (I2C_CLOCKSPEED * 1000); hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(&hi2c1); } void MX_TIM_Init(void) { __HAL_RCC_TIM1_CLK_ENABLE(); __HAL_RCC_TIM8_CLK_ENABLE(); TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig; TIM_SlaveConfigTypeDef sTimConfig; htim_right.Instance = RIGHT_TIM; htim_right.Init.Prescaler = 0; htim_right.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; htim_right.Init.Period = CORE_FREQ / 2 / PWM_FREQ; htim_right.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim_right.Init.RepetitionCounter = 0; htim_right.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_PWM_Init(&htim_right); sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim_right, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_SET; HAL_TIM_PWM_ConfigChannel(&htim_right, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_ConfigChannel(&htim_right, &sConfigOC, TIM_CHANNEL_2); HAL_TIM_PWM_ConfigChannel(&htim_right, &sConfigOC, TIM_CHANNEL_3); sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; sBreakDeadTimeConfig.DeadTime = DEAD_TIME; sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; HAL_TIMEx_ConfigBreakDeadTime(&htim_right, &sBreakDeadTimeConfig); htim_left.Instance = LEFT_TIM; htim_left.Init.Prescaler = 0; htim_left.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; htim_left.Init.Period = CORE_FREQ / 2 / PWM_FREQ; htim_left.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim_left.Init.RepetitionCounter = 0; htim_left.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_PWM_Init(&htim_left); sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; HAL_TIMEx_MasterConfigSynchronization(&htim_left, &sMasterConfig); sTimConfig.InputTrigger = TIM_TS_ITR0; sTimConfig.SlaveMode = TIM_SLAVEMODE_GATED; HAL_TIM_SlaveConfigSynchronization(&htim_left, &sTimConfig); // Start counting >0 to effectively offset timers by the time it takes for one ADC conversion to complete. // This method allows that the Phase currents ADC measurements are properly aligned with LOW-FET ON region for both motors LEFT_TIM->CNT = ADC_TOTAL_CONV_TIME; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_SET; HAL_TIM_PWM_ConfigChannel(&htim_left, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_ConfigChannel(&htim_left, &sConfigOC, TIM_CHANNEL_2); HAL_TIM_PWM_ConfigChannel(&htim_left, &sConfigOC, TIM_CHANNEL_3); sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; sBreakDeadTimeConfig.DeadTime = DEAD_TIME; sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; HAL_TIMEx_ConfigBreakDeadTime(&htim_left, &sBreakDeadTimeConfig); LEFT_TIM->BDTR &= ~TIM_BDTR_MOE; RIGHT_TIM->BDTR &= ~TIM_BDTR_MOE; HAL_TIM_PWM_Start(&htim_left, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim_left, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim_left, TIM_CHANNEL_3); HAL_TIMEx_PWMN_Start(&htim_left, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim_left, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim_left, TIM_CHANNEL_3); HAL_TIM_PWM_Start(&htim_right, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim_right, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim_right, TIM_CHANNEL_3); HAL_TIMEx_PWMN_Start(&htim_right, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim_right, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim_right, TIM_CHANNEL_3); htim_left.Instance->RCR = 1; __HAL_TIM_ENABLE(&htim_right); } void MX_ADC_Init(void) { ADC_MultiModeTypeDef multimode; ADC_ChannelConfTypeDef sConfig; __HAL_RCC_ADC1_CLK_ENABLE(); hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 8; HAL_ADC_Init(&hadc); HAL_ADCEx_MultiModeConfigChannel(&hadc, &multimode); sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; sConfig.Channel = ADC_CHANNEL_5; // pa5 left b -> right sConfig.Rank = 1; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_6; // pa6 left c -> right sConfig.Rank = 2; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_0; // pa0 right a -> left sConfig.Rank = 3; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_1; // pa1 right b -> left sConfig.Rank = 4; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_3; // pa3 left cur -> right sConfig.Rank = 5; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_2; // pa2 right cur -> left sConfig.Rank = 6; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = ADC_CHANNEL_4; // pa4 vbat sConfig.Rank = 7; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES; sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; // internal temp sConfig.Rank = 8; HAL_ADC_ConfigChannel(&hadc, &sConfig); hadc.Instance->CR2 |= ADC_CR2_DMA | ADC_CR2_DDS | ADC_CCR_TSVREFE; __HAL_ADC_ENABLE(&hadc); __HAL_RCC_DMA2_CLK_ENABLE(); DMA2_Stream0->CR = 0; DMA2_Stream0->NDTR = 8; DMA2_Stream0->PAR = (uint32_t)&(ADC1->DR); DMA2_Stream0->M0AR = (uint32_t)&adc_buffer; DMA2_Stream0->CR = DMA_SxCR_MSIZE_1 | DMA_SxCR_PSIZE_1 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE; DMA2_Stream0->CR &= ~DMA_SxCR_CHSEL; DMA2_Stream0->FCR &= ~DMA_SxFCR_DMDIS; DMA2_Stream0->CR |= DMA_SxCR_EN; HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); } #endif