/*********************************************************************************************************************** * Copyright (C) All rights reserved. ***********************************************************************************************************************/ /*********************************************************************************************************************** * @file timm_user.c * @brief This file implements device driver for TMM module. * @version 1.0.0 * @date 2020/04/02 ***********************************************************************************************************************/ /*********************************************************************************************************************** Includes ***********************************************************************************************************************/ #include "BAT32A239.h" #include "userdefine.h" #include "timm.h" /* Start user code for include. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** Pragma directive ***********************************************************************************************************************/ //void IRQ27_Handler(void) __attribute__((alias("tmm0_interrupt"))); //void IRQ28_Handler(void) __attribute__((alias("tmm1_interrupt"))); /* Start user code for pragma. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** Global variables and functions ***********************************************************************************************************************/ /* TMM0 input capture mode */ volatile uint16_t g_tmm0_intTaken_a = 0U; volatile uint16_t g_tmm0_intTaken_b = 0U; volatile uint32_t g_tmm0_active_width_a = 0UL; volatile uint32_t g_tmm0_active_width_b = 0UL; volatile uint32_t g_tmm0_active_width_c = 0UL; volatile uint32_t g_tmm0_active_width_d = 0UL; volatile uint32_t g_tmm0_active_width_elc = 0UL; volatile uint32_t g_tmm0_overflow_count_a = 0UL; volatile uint32_t g_tmm0_overflow_count_b = 0UL; /* TMM1 input capture mode */ volatile uint16_t g_tmm1_intTaken_a = 0U; volatile uint16_t g_tmm1_intTaken_b = 0U; volatile uint32_t g_tmm1_active_width_a = 0UL; volatile uint32_t g_tmm1_active_width_b = 0UL; volatile uint32_t g_tmm1_active_width_c = 0UL; volatile uint32_t g_tmm1_active_width_d = 0UL; volatile uint32_t g_tmm1_active_width_elc = 0UL; volatile uint32_t g_tmm1_overflow_count_a = 0UL; volatile uint32_t g_tmm1_overflow_count_b = 0UL; /* Motor Driver */ volatile uint16_t g_u2_pwm_duty; /* PWM duty : No scaling */ volatile uint8_t g_u1_v_pattern; /* voltage pattern */ volatile uint8_t g_u1_direction; /* rotation direction (0:CW ,1:CCW) */ volatile uint8_t g_u1_v_pattern_open[2][7] = { {0, MTR_PATTERN_CW_U_V, /* 5 */ MTR_PATTERN_CW_W_V, /* 1 */ MTR_PATTERN_CW_W_U, /* 3 */ MTR_PATTERN_CW_V_U, /* 2 */ MTR_PATTERN_CW_V_W, /* 6 */ MTR_PATTERN_CW_U_W}, /* 4 */ {0, MTR_PATTERN_CCW_U_W, /* 4 */ MTR_PATTERN_CCW_V_W, /* 6 */ MTR_PATTERN_CCW_V_U, /* 2 */ MTR_PATTERN_CCW_W_U, /* 3 */ MTR_PATTERN_CCW_W_V, /* 1 */ MTR_PATTERN_CCW_U_V} /* 5 */ }; /* array of voltage pattern for openloop drive */ /* Start user code for global. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** * Function Name: tmm0_interrupt * @brief timm0 interrupt service routine for input capture mode * @param None * @return None ***********************************************************************************************************************/ void tmm0_interrupt(void) { INTC_ClearPendingIRQ(TMM0_IRQn); /* clear INTTMM0 interrupt flag */ uint8_t tmsr0_temp = TMM->TMSR0; uint8_t tmier0_temp = TMM->TMIER0; TMM->TMIER0 = 0x00U; if ((TMM->TMSR0 & _10_TMM0_INTOV_GENERATE_FLAG) == _10_TMM0_INTOV_GENERATE_FLAG) { TMM->TMSR0 = tmsr0_temp & (uint8_t)~_10_TMM0_INTOV_GENERATE_FLAG; g_tmm0_overflow_count_a += 1U; g_tmm0_overflow_count_b += 1U; } if ((TMM->TMSR0 & _01_TMM0_INTA_GENERATE_FLAG) == _01_TMM0_INTA_GENERATE_FLAG) { TMM->TMSR0 = tmsr0_temp & (uint8_t)~_01_TMM0_INTA_GENERATE_FLAG; g_tmm0_intTaken_a++; if (g_tmm0_overflow_count_a == 0U) { g_tmm0_active_width_a = (TMM->TMGRA0 - TMM->TMGRC0); } else { g_tmm0_active_width_a = (TMM->TMGRA0 - TMM->TMGRC0) + (0x10000UL * g_tmm0_overflow_count_a); g_tmm0_overflow_count_a = 0U; } } if ((TMM->TMSR0 & _02_TMM0_INTB_GENERATE_FLAG) == _02_TMM0_INTB_GENERATE_FLAG) { TMM->TMSR0 = tmsr0_temp & (uint8_t)~(_02_TMM0_INTB_GENERATE_FLAG); g_tmm0_intTaken_b++; if (g_tmm0_overflow_count_b == 0U) { g_tmm0_active_width_b = (TMM->TMGRB0 - TMM->TMGRD0); } else { g_tmm0_active_width_b = (TMM->TMGRB0 - TMM->TMGRD0) + (0x10000UL * g_tmm0_overflow_count_b); g_tmm0_overflow_count_b = 0U; } } if ((TMM->TMSR0 & _04_TMM0_INTC_GENERATE_FLAG) == _04_TMM0_INTC_GENERATE_FLAG) { TMM->TMSR0 = tmsr0_temp & (uint8_t)~_04_TMM0_INTC_GENERATE_FLAG; } if ((TMM->TMSR0 & _08_TMM0_INTD_GENERATE_FLAG) == _08_TMM0_INTD_GENERATE_FLAG) { TMM->TMSR0 = tmsr0_temp & (uint8_t)~_08_TMM0_INTD_GENERATE_FLAG; } TMM->TMIER0 = tmier0_temp; } /*********************************************************************************************************************** * Function Name: tmm1_interrupt * @brief timm1 interrupt service routine for input capture mode * @param None * @return None ***********************************************************************************************************************/ void tmm1_interrupt(void) { INTC_ClearPendingIRQ(TMM1_IRQn); /* clear INTTMM0 interrupt flag */ uint8_t tmsr1_temp = TMM->TMSR1; uint8_t tmier1_temp = TMM->TMIER1; TMM->TMIER1 = 0x00U; if ((TMM->TMSR1 & _10_TMM1_INTOV_GENERATE_FLAG) == _10_TMM1_INTOV_GENERATE_FLAG) { TMM->TMSR1 = tmsr1_temp & (uint8_t)~_10_TMM1_INTOV_GENERATE_FLAG; g_tmm1_overflow_count_a += 1U; g_tmm1_overflow_count_b += 1U; } if ((TMM->TMSR1 & _01_TMM1_INTA_GENERATE_FLAG) == _01_TMM1_INTA_GENERATE_FLAG) { TMM->TMSR1 = tmsr1_temp & (uint8_t)~_01_TMM1_INTA_GENERATE_FLAG; g_tmm1_intTaken_a++; if (g_tmm1_overflow_count_a == 0U) { g_tmm1_active_width_a = (TMM->TMGRA1 - TMM->TMGRC1); } else { g_tmm1_active_width_a = (TMM->TMGRA1 - TMM->TMGRC1) + (0x10000UL * g_tmm1_overflow_count_a); g_tmm1_overflow_count_a = 0U; } } if ((TMM->TMSR1 & _02_TMM1_INTB_GENERATE_FLAG) == _02_TMM1_INTB_GENERATE_FLAG) { TMM->TMSR1 = tmsr1_temp & (uint8_t)~(_02_TMM1_INTB_GENERATE_FLAG); g_tmm1_intTaken_b++; if (g_tmm1_overflow_count_b == 0U) { g_tmm1_active_width_b = (TMM->TMGRB1 - TMM->TMGRD1); } else { g_tmm1_active_width_b = (TMM->TMGRB1 - TMM->TMGRD1) + (0x10000UL * g_tmm1_overflow_count_b); g_tmm1_overflow_count_b = 0U; } } if ((TMM->TMSR1 & _04_TMM1_INTC_GENERATE_FLAG) == _04_TMM1_INTC_GENERATE_FLAG) { TMM->TMSR1 = tmsr1_temp & (uint8_t)~_04_TMM1_INTC_GENERATE_FLAG; } if ((TMM->TMSR1 & _08_TMM1_INTD_GENERATE_FLAG) == _08_TMM1_INTD_GENERATE_FLAG) { TMM->TMSR1 = tmsr1_temp & (uint8_t)~_08_TMM1_INTD_GENERATE_FLAG; } TMM->TMIER1 = tmier1_temp; } /****************************************************************************** * Function Name : mtr_init_trd * @brief Initialize Timer M * @param none * @return none ******************************************************************************/ void mtr_init_tmm(void) { TMM0_PWM_Complementary_3Phase(TMM_CLOCK_FCLK, MTR_CARRIER_SET, MTR_DEADTIME_SET); } /****************************************************************************** * Function Name : mtr_change_pattern * @brief Change voltage pattern * @param u1_pattern - Voltage pattern * @return none ******************************************************************************/ void mtr_change_pattern(uint8_t u1_pattern) { /*========================*/ /* stop PWM timer */ /*========================*/ //TMM->TMSTR = 0x0C; /* stop TM0 */ /*======================*/ /* set register */ /*======================*/ /* PWM output arm setting */ switch (u1_pattern) { case MTR_V_PWM_WN_ON: TMM->TMOER1 = 0xAF; /* Vp/Vn : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_CLR(); /* Un = OFF("Low") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_CLR(); /* Vn = OFF("Low") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_SET(); /* Wn = ON ("High") */ break; case MTR_W_PWM_VN_ON: TMM->TMOER1 = 0x5F; /* Wp/Wn : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_CLR(); /* Un = OFF("Low") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_SET(); /* Vn = ON ("High") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_CLR(); /* Wn = OFF("Low") */ break; case MTR_W_PWM_UN_ON: TMM->TMOER1 = 0x5F; /* Wp/Wn : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_SET(); /* Un = ON ("High") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_CLR(); /* Vn = OFF("Low") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_CLR(); /* Wn = OFF("Low") */ break; case MTR_U_PWM_WN_ON: TMM->TMOER1 = 0xF5; /* Up/Un : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_CLR(); /* Un = OFF("Low") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_CLR(); /* Vn = OFF("Low") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_SET(); /* Wn = ON ("High") */ break; case MTR_U_PWM_VN_ON: TMM->TMOER1 = 0xF5; /* Up/Un : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_CLR(); /* Un = OFF("Low") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_SET(); /* Vn = ON ("High") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_CLR(); /* Wn = OFF("Low") */ break; case MTR_V_PWM_UN_ON: TMM->TMOER1 = 0xAF; /* Vp/Vn : PWM output enable */ MTR_PORT_UP_CLR(); /* Up = OFF("Low") */ MTR_PORT_UN_SET(); /* Un = ON ("High") */ MTR_PORT_VP_CLR(); /* Vp = OFF("Low") */ MTR_PORT_VN_CLR(); /* Vn = OFF("Low") */ MTR_PORT_WP_CLR(); /* Wp = OFF("Low") */ MTR_PORT_WN_CLR(); /* Wn = OFF("Low") */ break; /* the default case is intentionally combined */ default: break; } TMM->TMGRD0 = (int16_t)MTR_CARRIER_SET - g_u2_pwm_duty; /* duty of U phase */ TMM->TMGRC1 = (int16_t)MTR_CARRIER_SET - g_u2_pwm_duty; /* duty of V phase */ TMM->TMGRD1 = (int16_t)MTR_CARRIER_SET - g_u2_pwm_duty; /* duty of W phase */ /*===========================*/ /* restart PWM timer */ /*===========================*/ //TMM->TM0 = (uint16_t)MTR_DEADTIME_SET; /* reset TM0 */ //TMM->TM1 = 0; //TMM->TMSTR = 0x0F; /* start TM0 */ } /****************************************************************************** * Function Name : mtr_pattern_up_chopping * @brief Set voltage pattern upper arm chopping PWM * @param u1_pattern : voltage pattern * @return none ******************************************************************************/ void mtr_pattern_up_chopping(uint8_t u1_pattern) { /*** set voltage pattern ***/ if (MTR_CW == g_u1_direction) /* check rotation direction */ { switch (u1_pattern) { case MTR_PATTERN_CW_W_V: /* from W phase to V phase */ g_u1_v_pattern = MTR_W_PWM_VN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_WP); break; case MTR_PATTERN_CW_U_V: /* from U phase to V phase */ g_u1_v_pattern = MTR_U_PWM_VN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_UP); break; case MTR_PATTERN_CW_U_W: /* from U phase to W phase */ g_u1_v_pattern = MTR_U_PWM_WN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_UP); break; case MTR_PATTERN_CW_V_W: /* from V phase to W phase */ g_u1_v_pattern = MTR_V_PWM_WN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_VP); break; case MTR_PATTERN_CW_V_U: /* from V phase to U phase */ g_u1_v_pattern = MTR_V_PWM_UN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_VP); break; case MTR_PATTERN_CW_W_U: /* from W phase to U phase */ g_u1_v_pattern = MTR_W_PWM_UN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_WP); break; default: /* pseudo Hall signal pattern error */ g_u1_v_pattern = MTR_PATTERN_ERROR; break; } } else if (MTR_CCW == g_u1_direction) /* check rotation direction */ { switch (u1_pattern) { case MTR_PATTERN_CCW_W_V: /* from W phase to V phase */ g_u1_v_pattern = MTR_W_PWM_VN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_WP); break; case MTR_PATTERN_CCW_W_U: /* from W phase to U phase */ g_u1_v_pattern = MTR_W_PWM_UN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_WP); break; case MTR_PATTERN_CCW_V_U: /* from V phase to U phase */ g_u1_v_pattern = MTR_V_PWM_UN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_VP); break; case MTR_PATTERN_CCW_V_W: /* from V phase to W phase */ g_u1_v_pattern = MTR_V_PWM_WN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_VP); break; case MTR_PATTERN_CCW_U_W: /* from U phase to W phase */ g_u1_v_pattern = MTR_U_PWM_WN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_UP); break; case MTR_PATTERN_CCW_U_V: /* from U phase to V phase */ g_u1_v_pattern = MTR_U_PWM_VN_ON; //mtr_set_tau_window_signal(MTR_TAU_TIMER_UP); break; default: /* pseudo Hall signal pattern error */ g_u1_v_pattern = MTR_PATTERN_ERROR; break; } } else { /* Do Nothing */ } } /****************************************************************************** * Function Name : mtr_pattern_set * @brief Set voltage pattern * @param u1_pattern - voltage pattern value * @return none ******************************************************************************/ void mtr_pattern_set(uint8_t u1_pattern) { /*** set voltage pattern ***/ mtr_pattern_up_chopping(u1_pattern); /* Upper arm chopping pattern */ mtr_change_pattern(g_u1_v_pattern); /* change voltage pattern */ } /* Start user code for adding. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */