diff --git a/project/mdk/stm32_template.uvprojx b/project/mdk/stm32_template.uvprojx
index 398b2e7..70d0467 100644
--- a/project/mdk/stm32_template.uvprojx
+++ b/project/mdk/stm32_template.uvprojx
@@ -10,8 +10,8 @@
stm32f407_template
0x4
ARM-ADS
- 5060960::V5.06 update 7 (build 960)::.\ARMCC
- 0
+ 6150000::V6.15::ARMCLANG
+ 1
STM32F407ZGTx
@@ -313,7 +313,7 @@
1
- 4
+ 2
0
0
1
@@ -328,7 +328,7 @@
1
0
0
- 5
+ 3
3
1
1
@@ -478,6 +478,11 @@
1
..\..\src\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c
+
+ stm32f4xx_ll_tim.c
+ 1
+ ..\..\src\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_tim.c
+
@@ -513,6 +518,11 @@
1
..\..\src\Bsp\stm32f4xx_it.c
+
+ timer.c
+ 1
+ ..\..\src\Bsp\timer.c
+
diff --git a/src/Bsp/board.c b/src/Bsp/board.c
index 3ad70ee..567f7fd 100644
--- a/src/Bsp/board.c
+++ b/src/Bsp/board.c
@@ -39,7 +39,7 @@ void SystemClock_Config(void)
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
diff --git a/src/Bsp/gpio.c b/src/Bsp/gpio.c
index eed7065..5de18b6 100644
--- a/src/Bsp/gpio.c
+++ b/src/Bsp/gpio.c
@@ -42,11 +42,11 @@ void led_ctrl(uint8_t cmd)
{
if (cmd)
{
- HAL_GPIO_WritePin(LED1_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
+ HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
}
else
{
- HAL_GPIO_WritePin(LED1_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
}
}
diff --git a/src/Bsp/gpio.h b/src/Bsp/gpio.h
index 082d402..e7c8257 100644
--- a/src/Bsp/gpio.h
+++ b/src/Bsp/gpio.h
@@ -18,7 +18,7 @@ extern "C"
/* Includes ------------------------------------------------------------------*/
-#include "main.h"
+#include "stm32f4xx_hal.h"
#define LED0_Pin GPIO_PIN_15
#define LED0_GPIO_Port GPIOA
diff --git a/src/Bsp/stm32f4xx_hal_conf.h b/src/Bsp/stm32f4xx_hal_conf.h
index 5acf6bc..45cb5d4 100644
--- a/src/Bsp/stm32f4xx_hal_conf.h
+++ b/src/Bsp/stm32f4xx_hal_conf.h
@@ -62,7 +62,7 @@
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
-/* #define HAL_TIM_MODULE_ENABLED */
+#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
diff --git a/src/Bsp/timer.c b/src/Bsp/timer.c
new file mode 100644
index 0000000..7efe8c4
--- /dev/null
+++ b/src/Bsp/timer.c
@@ -0,0 +1,282 @@
+/**
+ * @file timer.c
+ * @author jimingqing
+ * @date 2023-08-14
+ * @version 0.0.1
+ * @copyright XiazhiTech Copyright (c) 2023
+ *
+ * @brief
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "timer.h"
+#include "board.h"
+#include "stm32f4xx_ll_tim.h"
+
+TIM_HandleTypeDef htim1;
+TIM_HandleTypeDef htim3;
+
+/**
+ * @brief TIM1 Initialization Function
+ * @param None
+ * @retval None
+ */
+void MX_TIM1_Init(void)
+{
+ TIM_SlaveConfigTypeDef sSlaveConfig = {0};
+ TIM_MasterConfigTypeDef sMasterConfig = {0};
+ TIM_OC_InitTypeDef sConfigOC = {0};
+ TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
+
+ /**
+ * 定时器主频84M 不分频
+ */
+ htim1.Instance = TIM1;
+ htim1.Init.Prescaler = 0;
+ htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
+ htim1.Init.Period = (84 * 1000000 / 16000);
+ htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;
+ htim1.Init.RepetitionCounter = 1;
+ htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
+ sSlaveConfig.InputTrigger = TIM_TS_ITR1;
+ if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+ sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_PWM1;
+ sConfigOC.Pulse = 0;
+ sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
+ sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+ sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
+ sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
+ sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_PWM2;
+ sConfigOC.Pulse = ((84 * 1000000 / 16000) - 1);
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
+ sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
+ sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
+ // sBreakDeadTimeConfig.DeadTime = ((DEAD_TIME_COUNTS) / 2);
+ sBreakDeadTimeConfig.DeadTime = 100;
+ sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
+ sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW;
+ sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
+ if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+}
+
+/**
+ * @brief TIM3 Initialization Function
+ * @param None
+ * @retval None
+ */
+void MX_TIM3_Init(void)
+{
+
+ TIM_ClockConfigTypeDef sClockSourceConfig = {0};
+ TIM_HallSensor_InitTypeDef sConfig = {0};
+ TIM_MasterConfigTypeDef sMasterConfig = {0};
+
+ htim3.Instance = TIM3;
+ htim3.Init.Prescaler = 0;
+ htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
+ htim3.Init.Period = 65535;
+ htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
+ if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
+ sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
+ sConfig.IC1Filter = 11;
+ sConfig.Commutation_Delay = 0;
+ if (HAL_TIMEx_HallSensor_Init(&htim3, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;
+ sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+}
+
+/**
+ * @brief TIM_Base MSP Initialization
+ * This function configures the hardware resources used in this example
+ * @param htim_base: TIM_Base handle pointer
+ * @retval None
+ */
+void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ if (htim_base->Instance == TIM1)
+ {
+ /* Peripheral clock enable */
+ __HAL_RCC_TIM1_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+
+ /**TIM1 GPIO Configuration
+ PA10 ------> TIM1_CH3
+ PA9 ------> TIM1_CH2
+ PA8 ------> TIM1_CH1
+ PB13 ------> TIM1_CH1N
+ PB14 ------> TIM1_CH2N
+ PB15 ------> TIM1_CH3N
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+ }
+ else if (htim_base->Instance == TIM3)
+ {
+ /* Peripheral clock enable */
+ __HAL_RCC_TIM3_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ /**TIM3 GPIO Configuration
+ PC8 ------> TIM3_CH3
+ PC7 ------> TIM3_CH2
+ PC6 ------> TIM3_CH1
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+ }
+}
+
+/**
+ * @brief TIM_Base MSP De-Initialization
+ * This function freeze the hardware resources used in this example
+ * @param htim_base: TIM_Base handle pointer
+ * @retval None
+ */
+void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim_base)
+{
+ if (htim_base->Instance == TIM1)
+ {
+ /* Peripheral clock disable */
+ __HAL_RCC_TIM1_CLK_DISABLE();
+
+ /* TIM1 interrupt DeInit */
+ HAL_NVIC_DisableIRQ(TIM1_BRK_TIM9_IRQn);
+ HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
+ }
+ else if (htim_base->Instance == TIM3)
+ {
+
+ /* Peripheral clock disable */
+ __HAL_RCC_TIM3_CLK_DISABLE();
+
+ /**TIM3 GPIO Configuration
+ PC8 ------> TIM3_CH3
+ PC7 ------> TIM3_CH2
+ PC6 ------> TIM3_CH1
+ */
+ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8);
+
+ /* TIM3 interrupt DeInit */
+ HAL_NVIC_DisableIRQ(TIM3_IRQn);
+ }
+}
+
+/**
+ * @brief This function handles first motor TIMx Update interrupt request.
+ * @param None
+ * @retval None
+ */
+void TIM1_UP_TIM10_IRQHandler(void)
+{
+ // LL_TIM_ClearFlag_UPDATE(PWM_Handle_M1.pParams_str->TIMx);
+ // R3_2_TIMx_UP_IRQHandler(&PWM_Handle_M1);
+}
+
+/**
+ * @brief This function handles first motor BRK interrupt.
+ * @param None
+ * @retval None
+ */
+void TIM1_BRK_TIM9_IRQHandler(void)
+{
+ // if (LL_TIM_IsActiveFlag_BRK(PWM_Handle_M1.pParams_str->TIMx))
+ // {
+ // LL_TIM_ClearFlag_BRK(PWM_Handle_M1.pParams_str->TIMx);
+ // R3_2_BRK_IRQHandler(&PWM_Handle_M1);
+ // }
+ // /* Systick is not executed due low priority so is necessary to call MC_Scheduler here.*/
+ // MC_Scheduler();
+}
+
+/**
+ * @brief This function handles TIMx global interrupt request for M1 Speed Sensor.
+ * @param None
+ * @retval None
+ */
+void TIM3_IRQHandler(void)
+{
+ /* HALL Timer Update IT always enabled, no need to check enable UPDATE state */
+ if (LL_TIM_IsActiveFlag_UPDATE(TIM3))
+ {
+ LL_TIM_ClearFlag_UPDATE(TIM3);
+ // HALL_TIMx_UP_IRQHandler(&HALL_M1);
+ }
+
+ /* HALL Timer CC1 IT always enabled, no need to check enable CC1 state */
+ if (LL_TIM_IsActiveFlag_CC1(TIM3))
+ {
+ LL_TIM_ClearFlag_CC1(TIM3);
+ // HALL_TIMx_CC_IRQHandler(&HALL_M1);
+ }
+}
diff --git a/src/Bsp/timer.h b/src/Bsp/timer.h
new file mode 100644
index 0000000..95bdac1
--- /dev/null
+++ b/src/Bsp/timer.h
@@ -0,0 +1,30 @@
+/**
+ * @file gpio.h
+ * @author jimingqing
+ * @date 2023-08-14
+ * @version 0.0.1
+ * @copyright XiazhiTech Copyright (c) 2023
+ *
+ * @brief
+ */
+
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* Includes ------------------------------------------------------------------*/
+
+#include "stm32f4xx_hal.h"
+
+ void MX_TIM1_Init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__ __TIMER_H__ */
+
+/* END OF FILE ---------------------------------------------------------------*/
diff --git a/src/Foc/hall.c b/src/Foc/hall.c
new file mode 100644
index 0000000..435c8f8
--- /dev/null
+++ b/src/Foc/hall.c
@@ -0,0 +1,116 @@
+#include "hall.h"
+
+/**
+ * @brief 更新HALL状态
+ * @param handle
+ * @param new_state
+ */
+void calc_hall_angle(hall_handle_t *handle, uint8_t new_state)
+{
+ switch (new_state)
+ {
+ case HALL_STATE_5:
+ if (handle->state == HALL_STATE_4)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = handle->PhaseShift;
+ }
+ else if (handle->state == HALL_STATE_1)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift + S16_60_PHASE_SHIFT);
+ }
+ else
+ {
+ }
+ break;
+
+ case HALL_STATE_1:
+ if (handle->state == HALL_STATE_5)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = handle->PhaseShift + S16_60_PHASE_SHIFT;
+ }
+ else if (handle->state == HALL_STATE_3)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift + S16_120_PHASE_SHIFT);
+ }
+ else
+ {
+ }
+ break;
+
+ case HALL_STATE_3:
+ if (handle->state == HALL_STATE_1)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift + S16_120_PHASE_SHIFT);
+ }
+ else if (handle->state == HALL_STATE_2)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift + S16_120_PHASE_SHIFT +
+ S16_60_PHASE_SHIFT);
+ }
+ else
+ {
+ }
+
+ break;
+
+ case HALL_STATE_2:
+ if (handle->state == HALL_STATE_3)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift + S16_120_PHASE_SHIFT + S16_60_PHASE_SHIFT);
+ }
+ else if (handle->state == HALL_STATE_6)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift - S16_120_PHASE_SHIFT);
+ }
+ else
+ {
+ }
+ break;
+
+ case HALL_STATE_6:
+ if (handle->state == HALL_STATE_2)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift - S16_120_PHASE_SHIFT);
+ }
+ else if (handle->state == HALL_STATE_4)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift - S16_60_PHASE_SHIFT);
+ }
+ else
+ {
+ }
+ break;
+
+ case HALL_STATE_4:
+ if (handle->state == HALL_STATE_6)
+ {
+ handle->Direction = POSITIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift - S16_60_PHASE_SHIFT);
+ }
+ else if (handle->state == HALL_STATE_5)
+ {
+ handle->Direction = NEGATIVE;
+ handle->MeasuredElAngle = (int16_t)(handle->PhaseShift);
+ }
+ else
+ {
+ }
+ break;
+
+ default:
+ /* Bad hall sensor configutarion so update the speed reliability */
+ handle->SensorIsReliable = false;
+
+ break;
+ }
+}
\ No newline at end of file
diff --git a/src/Foc/hall.h b/src/Foc/hall.h
new file mode 100644
index 0000000..26c04c1
--- /dev/null
+++ b/src/Foc/hall.h
@@ -0,0 +1,44 @@
+/**
+ * @file hall.h
+ * @author jimingqing
+ * @date 2023-05-25
+ * @version 0.0.1
+ * @copyright XiazhiTech Copyright (c) 2023
+ *
+ * @brief
+ */
+#include "stm32f407xx.h"
+
+#define HALL_STATE_0 (uint8_t)0
+#define HALL_STATE_1 (uint8_t)1
+#define HALL_STATE_2 (uint8_t)2
+#define HALL_STATE_3 (uint8_t)3
+#define HALL_STATE_4 (uint8_t)4
+#define HALL_STATE_5 (uint8_t)5
+#define HALL_STATE_6 (uint8_t)6
+#define HALL_STATE_7 (uint8_t)7
+
+#define S16_120_PHASE_SHIFT (int16_t)(65536 / 3)
+#define S16_60_PHASE_SHIFT (int16_t)(65536 / 6)
+
+enum
+{
+ NEGATIVE = -1,
+ POSITIVE = 1,
+
+}
+
+typedef struct
+{
+ // |||
+ // |||
+ // |||
+ uint8_t state; // 霍尔状态真值表
+
+ int16_t phase_shift; // 同步电角度
+
+ int8_t direction; // 转子方向
+ int16_t measure_elec_angle; // 测量转子电角度
+ int16_t control_elec_angle; // 控制转子电角度
+
+} hall_handle_t;
diff --git a/src/Foc/main.c b/src/Foc/main.c
new file mode 100644
index 0000000..72e23b1
--- /dev/null
+++ b/src/Foc/main.c
@@ -0,0 +1,11 @@
+
+
+int main()
+{
+ /**
+ * 开环控制
+ * 1. 计算电角度
+ * 2.
+ */
+
+}
diff --git a/src/Foc/math.c b/src/Foc/math.c
new file mode 100644
index 0000000..943042b
--- /dev/null
+++ b/src/Foc/math.c
@@ -0,0 +1,110 @@
+#include "math.h"
+
+#define SIN_MASK 0x0300u
+#define U0_90 0x0200u
+#define U90_180 0x0300u
+#define U180_270 0x0000u
+#define U270_360 0x0100u
+
+const int16_t hSin_Cos_Table[256] = {
+ 0x0000, 0x00C9, 0x0192, 0x025B, 0x0324, 0x03ED, 0x04B6, 0x057F,
+ 0x0648, 0x0711, 0x07D9, 0x08A2, 0x096A, 0x0A33, 0x0AFB, 0x0BC4,
+ 0x0C8C, 0x0D54, 0x0E1C, 0x0EE3, 0x0FAB, 0x1072, 0x113A, 0x1201,
+ 0x12C8, 0x138F, 0x1455, 0x151C, 0x15E2, 0x16A8, 0x176E, 0x1833,
+ 0x18F9, 0x19BE, 0x1A82, 0x1B47, 0x1C0B, 0x1CCF, 0x1D93, 0x1E57,
+ 0x1F1A, 0x1FDD, 0x209F, 0x2161, 0x2223, 0x22E5, 0x23A6, 0x2467,
+ 0x2528, 0x25E8, 0x26A8, 0x2767, 0x2826, 0x28E5, 0x29A3, 0x2A61,
+ 0x2B1F, 0x2BDC, 0x2C99, 0x2D55, 0x2E11, 0x2ECC, 0x2F87, 0x3041,
+ 0x30FB, 0x31B5, 0x326E, 0x3326, 0x33DF, 0x3496, 0x354D, 0x3604,
+ 0x36BA, 0x376F, 0x3824, 0x38D9, 0x398C, 0x3A40, 0x3AF2, 0x3BA5,
+ 0x3C56, 0x3D07, 0x3DB8, 0x3E68, 0x3F17, 0x3FC5, 0x4073, 0x4121,
+ 0x41CE, 0x427A, 0x4325, 0x43D0, 0x447A, 0x4524, 0x45CD, 0x4675,
+ 0x471C, 0x47C3, 0x4869, 0x490F, 0x49B4, 0x4A58, 0x4AFB, 0x4B9D,
+ 0x4C3F, 0x4CE0, 0x4D81, 0x4E20, 0x4EBF, 0x4F5D, 0x4FFB, 0x5097,
+ 0x5133, 0x51CE, 0x5268, 0x5302, 0x539B, 0x5432, 0x54C9, 0x5560,
+ 0x55F5, 0x568A, 0x571D, 0x57B0, 0x5842, 0x58D3, 0x5964, 0x59F3,
+ 0x5A82, 0x5B0F, 0x5B9C, 0x5C28, 0x5CB3, 0x5D3E, 0x5DC7, 0x5E4F,
+ 0x5ED7, 0x5F5D, 0x5FE3, 0x6068, 0x60EB, 0x616E, 0x61F0, 0x6271,
+ 0x62F1, 0x6370, 0x63EE, 0x646C, 0x64E8, 0x6563, 0x65DD, 0x6656,
+ 0x66CF, 0x6746, 0x67BC, 0x6832, 0x68A6, 0x6919, 0x698B, 0x69FD,
+ 0x6A6D, 0x6ADC, 0x6B4A, 0x6BB7, 0x6C23, 0x6C8E, 0x6CF8, 0x6D61,
+ 0x6DC9, 0x6E30, 0x6E96, 0x6EFB, 0x6F5E, 0x6FC1, 0x7022, 0x7083,
+ 0x70E2, 0x7140, 0x719D, 0x71F9, 0x7254, 0x72AE, 0x7307, 0x735E,
+ 0x73B5, 0x740A, 0x745F, 0x74B2, 0x7504, 0x7555, 0x75A5, 0x75F3,
+ 0x7641, 0x768D, 0x76D8, 0x7722, 0x776B, 0x77B3, 0x77FA, 0x783F,
+ 0x7884, 0x78C7, 0x7909, 0x794A, 0x7989, 0x79C8, 0x7A05, 0x7A41,
+ 0x7A7C, 0x7AB6, 0x7AEE, 0x7B26, 0x7B5C, 0x7B91, 0x7BC5, 0x7BF8,
+ 0x7C29, 0x7C59, 0x7C88, 0x7CB6, 0x7CE3, 0x7D0E, 0x7D39, 0x7D62,
+ 0x7D89, 0x7DB0, 0x7DD5, 0x7DFA, 0x7E1D, 0x7E3E, 0x7E5F, 0x7E7E,
+ 0x7E9C, 0x7EB9, 0x7ED5, 0x7EEF, 0x7F09, 0x7F21, 0x7F37, 0x7F4D,
+ 0x7F61, 0x7F74, 0x7F86, 0x7F97, 0x7FA6, 0x7FB4, 0x7FC1, 0x7FCD,
+ 0x7FD8, 0x7FE1, 0x7FE9, 0x7FF0, 0x7FF5, 0x7FF9, 0x7FFD, 0x7FFE};
+
+/**
+ * @brief This function transforms stator voltage qVq and qVd, that belong to
+ * a rotor flux synchronous rotating frame, to a stationary reference
+ * frame, so as to obtain qValpha and qVbeta:
+ * Valfa= Vq*Cos(theta)+ Vd*Sin(theta)
+ * Vbeta=-Vq*Sin(theta)+ Vd*Cos(theta)
+ * @param Input: stator voltage Vq and Vd in qd_t format
+ * @param Theta: rotating frame angular position in q1.15 format
+ * @retval Stator voltage Valpha and Vbeta in qd_t format
+ */
+alphabeta_t math_rev_park(qd_t input, int16_t theta)
+{
+ alphabeta_t output;
+ int32_t alpha_tmp1, alpha_tmp2, beta_tmp1, beta_tmp2;
+
+ int32_t shindex;
+ uint16_t uhindex;
+ int16_t hSin = 0, hCos = 0;
+
+ /* 10 bit index computation */
+ shindex = ((int32_t)32768 + (int32_t)theta);
+ uhindex = (uint16_t)shindex;
+ uhindex = uhindex >> 6;
+ // uhindex /= (uint16_t)64;
+
+ /**
+ | hAngle | angle | std |
+ | (0,16384] | U0_90 | (0,0.5] |
+ | (16384,32767] | U90_180 | (0.5,0.99] |
+ | (-16384,-1] | U270_360 | (0,-0.5] |
+ | (-16384,-32768] | U180_270 | (-0.5,-1) |
+ */
+ switch ((uint16_t)(uhindex)&SIN_MASK)
+ {
+ case U0_90:
+ hSin = hSin_Cos_Table[(uint8_t)(uhindex)];
+ hCos = hSin_Cos_Table[(uint8_t)(0xFFu - (uint8_t)(uhindex))];
+ break;
+
+ case U90_180:
+ hSin = hSin_Cos_Table[(uint8_t)(0xFFu - (uint8_t)(uhindex))];
+ hCos = -hSin_Cos_Table[(uint8_t)(uhindex)];
+ break;
+
+ case U180_270:
+ hSin = -hSin_Cos_Table[(uint8_t)(uhindex)];
+ hCos = -hSin_Cos_Table[(uint8_t)(0xFFu - (uint8_t)(uhindex))];
+ break;
+
+ case U270_360:
+ hSin = -hSin_Cos_Table[(uint8_t)(0xFFu - (uint8_t)(uhindex))];
+ hCos = hSin_Cos_Table[(uint8_t)(uhindex)];
+ break;
+ default:
+ break;
+ }
+
+ /*No overflow guaranteed*/
+ alpha_tmp1 = input.q * (int32_t)hCos;
+ alpha_tmp2 = input.d * (int32_t)hSin;
+ output.alpha = (int16_t)(((alpha_tmp1) + (alpha_tmp2)) >> 15);
+
+ beta_tmp1 = input.q * (int32_t)hSin;
+ beta_tmp2 = input.d * (int32_t)hCos;
+ output.beta = (int16_t)((beta_tmp2 - beta_tmp1) >> 15);
+
+ return (output);
+}
\ No newline at end of file
diff --git a/src/Foc/math.h b/src/Foc/math.h
new file mode 100644
index 0000000..0a494d5
--- /dev/null
+++ b/src/Foc/math.h
@@ -0,0 +1,53 @@
+#include "type.h"
+
+#define SQRT_2 1.4142
+#define SQRT_3 1.732
+
+/**
+ * @brief Macro to compute logarithm of two
+ */
+#define LOG2(x) \
+ ((x) == 65535 ? 16 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 15 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 14 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 13 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 12 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 11 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 10 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 9 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 8 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 * 2 ? 7 : ((x) == 2 * 2 * 2 * 2 * 2 * 2 ? 6 : ((x) == 2 * 2 * 2 * 2 * 2 ? 5 : ((x) == 2 * 2 * 2 * 2 ? 4 : ((x) == 2 * 2 * 2 ? 3 : ((x) == 2 * 2 ? 2 : ((x) == 2 ? 1 : ((x) == 1 ? 0 : -1)))))))))))))))))
+
+/**
+ * @brief This function transforms stator currents Ia and qIb (which are
+ * directed along axes each displaced by 120 degrees) into currents
+ * Ialpha and Ibeta in a stationary qd reference frame.
+ * Ialpha = Ia
+ * Ibeta = -(2*Ib+Ia)/sqrt(3)
+ * @param Curr_Input: stator current Ia and Ib in ab_t format
+ * @retval Stator current Ialpha and Ibeta in alphabeta_t format
+ */
+alphabeta_t math_clarke(ab_t Input);
+
+/**
+ * @brief This function transforms stator values alpha and beta, which
+ * belong to a stationary qd reference frame, to a rotor flux
+ * synchronous reference frame (properly oriented), so as Iq and Id.
+ * Id= Ialpha *sin(theta)+qIbeta *cos(Theta)
+ * Iq=qIalpha *cos(Theta)-qIbeta *sin(Theta)
+ * @param Curr_Input: stator values alpha and beta in alphabeta_t format
+ * @param Theta: rotating frame angular position in q1.15 format
+ * @retval Stator current q and d in qd_t format
+ */
+qd_t math_park(alphabeta_t Input, int16_t Theta);
+
+/**
+ * @brief This function transforms stator voltage qVq and qVd, that belong to
+ * a rotor flux synchronous rotating frame, to a stationary reference
+ * frame, so as to obtain qValpha and qVbeta:
+ * Valfa= Vq*Cos(theta)+ Vd*Sin(theta)
+ * Vbeta=-Vq*Sin(theta)+ Vd*Cos(theta)
+ * @param Curr_Input: stator voltage Vq and Vd in qd_t format
+ * @param Theta: rotating frame angular position in q1.15 format
+ * @retval Stator values alpha and beta in alphabeta_t format
+ */
+alphabeta_t math_rev_park(qd_t Input, int16_t Theta);
+
+/**
+ * @brief It calculates the square root of a non-negative s32. It returns 0
+ * for negative s32.
+ * @param Input int32_t number
+ * @retval int32_t Square root of Input (0 if Input<0)
+ */
+int32_t math_sqrt(int32_t wInput);
diff --git a/src/Foc/svpwm.c b/src/Foc/svpwm.c
new file mode 100644
index 0000000..42dc1b4
--- /dev/null
+++ b/src/Foc/svpwm.c
@@ -0,0 +1,87 @@
+#include "svpwm.h"
+void svpwm(int16_t alpha, int16_t beta)
+{
+ int32_t wX, wY, wZ, wUAlpha, wUBeta, wTimePhA, wTimePhB, wTimePhC;
+
+ wUAlpha = alpha * (int32_t)pHandle->hT_Sqrt3;
+ wUBeta = -(beta * (int32_t)(pHandle->PWMperiod)) * 2;
+
+ wX = wUBeta;
+ wY = (wUBeta + wUAlpha) / 2;
+ wZ = (wUBeta - wUAlpha) / 2;
+
+ /* Sector calculation from wX, wY, wZ */
+ if (wY < 0)
+ {
+ if (wZ < 0)
+ {
+ pHandle->Sector = SECTOR_5;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wY - wZ) / (int32_t)262144);
+ wTimePhB = wTimePhA + wZ / 131072;
+ wTimePhC = wTimePhA - wY / 131072;
+ pHandle->lowDuty = wTimePhC;
+ pHandle->midDuty = wTimePhA;
+ pHandle->highDuty = wTimePhB;
+ }
+ else /* wZ >= 0 */
+ if (wX <= 0)
+ {
+ pHandle->Sector = SECTOR_4;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wX - wZ) / (int32_t)262144);
+ wTimePhB = wTimePhA + wZ / 131072;
+ wTimePhC = wTimePhB - wX / 131072;
+ pHandle->lowDuty = wTimePhC;
+ pHandle->midDuty = wTimePhB;
+ pHandle->highDuty = wTimePhA;
+ }
+ else /* wX > 0 */
+ {
+ pHandle->Sector = SECTOR_3;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wY - wX) / (int32_t)262144);
+ wTimePhC = wTimePhA - wY / 131072;
+ wTimePhB = wTimePhC + wX / 131072;
+ pHandle->lowDuty = wTimePhB;
+ pHandle->midDuty = wTimePhC;
+ pHandle->highDuty = wTimePhA;
+ }
+ }
+ else /* wY > 0 */
+ {
+ if (wZ >= 0)
+ {
+ pHandle->Sector = SECTOR_2;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wY - wZ) / (int32_t)262144);
+ wTimePhB = wTimePhA + wZ / 131072;
+ wTimePhC = wTimePhA - wY / 131072;
+ pHandle->lowDuty = wTimePhB;
+ pHandle->midDuty = wTimePhA;
+ pHandle->highDuty = wTimePhC;
+ }
+ else /* wZ < 0 */
+ if (wX <= 0)
+ {
+ pHandle->Sector = SECTOR_6;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wY - wX) / (int32_t)262144);
+ wTimePhC = wTimePhA - wY / 131072;
+ wTimePhB = wTimePhC + wX / 131072;
+ pHandle->lowDuty = wTimePhA;
+ pHandle->midDuty = wTimePhC;
+ pHandle->highDuty = wTimePhB;
+ }
+ else /* wX > 0 */
+ {
+ pHandle->Sector = SECTOR_1;
+ wTimePhA = (int32_t)(pHandle->PWMperiod) / 4 + ((wX - wZ) / (int32_t)262144);
+ wTimePhB = wTimePhA + wZ / 131072;
+ wTimePhC = wTimePhB - wX / 131072;
+ pHandle->lowDuty = wTimePhA;
+ pHandle->midDuty = wTimePhB;
+ pHandle->highDuty = wTimePhC;
+ }
+ }
+
+ pHandle->CntPhA = (uint16_t)wTimePhA;
+ pHandle->CntPhB = (uint16_t)wTimePhB;
+ pHandle->CntPhC = (uint16_t)wTimePhC;
+
+}
\ No newline at end of file
diff --git a/src/Foc/svpwm.h b/src/Foc/svpwm.h
new file mode 100644
index 0000000..13dd56c
--- /dev/null
+++ b/src/Foc/svpwm.h
@@ -0,0 +1,18 @@
+/**
+ * @file svpwm.h
+ * @author jimingqing
+ * @date 2023-05-30
+ * @version 0.0.1
+ * @copyright XiazhiTech Copyright (c) 2023
+ *
+ * @brief
+ */
+
+#include "stm32f407xx.h"
+
+#define SECTOR_1 0u
+#define SECTOR_2 1u
+#define SECTOR_3 2u
+#define SECTOR_4 3u
+#define SECTOR_5 4u
+#define SECTOR_6 5u
\ No newline at end of file
diff --git a/src/Foc/type.h b/src/Foc/type.h
new file mode 100644
index 0000000..e3057d3
--- /dev/null
+++ b/src/Foc/type.h
@@ -0,0 +1,26 @@
+#include "stm32f407xx.h"
+
+/**
+ * @brief Two components q, d type definition
+ */
+typedef struct
+{
+ int16_t q;
+ int16_t d;
+} qd_t;
+/**
+ * @brief Two components a,b type definition
+ */
+typedef struct
+{
+ int16_t a;
+ int16_t b;
+} ab_t;
+/**
+ * @brief Two components alpha, beta type definition
+ */
+typedef struct
+{
+ int16_t alpha;
+ int16_t beta;
+} alphabeta_t;
\ No newline at end of file