/******************************************************************************* * Description : PLC_Tx_begin * Syntax : * Parameters I: * Parameters O: * return : *******************************************************************************/ void PLC_Tx_begin(u8 *data) { PLC_Tx_bitCnt = 0u; PLC_Tx_byteCnt = 0u; if (((*data) & 0x80) == 0x80) { TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 98); //285KHz(0,98) Freq_cnt = MAX_285K; } else { TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 500); //255KHz(0,88) Freq_cnt = MAX_255K; } // digitalWrite(0, HIGH); //P0.0 = 1 SCC // digitalWrite(1, HIGH); //P0.1 = 1 SCCOUT digitalWrite(36, HIGH); //P0.1 = 1 SCCOUT // Freq_cnt = 0; /* Start Timer1 counting */ TIMER_Start(TIMER1); }
/******************************************************************************* * Description : PLC Tx ISR * Syntax : * Parameters I: * Parameters O: * return : *******************************************************************************/ void TMR1_IRQHandler(void) { u8 temp_bit = 0u; // if(TIMER_GetIntFlag(TIMER1) == 1) if ((TIMER1->TISR & TIMER_TISR_TIF_Msk) == 1) { /* Clear Timer1 time-out interrupt flag */ //TIMER_ClearIntFlag(TIMER1); TIMER1->TISR = TIMER_TISR_TIF_Msk; // TimerIntCnt[1]++; Freq_cnt--; // Freq_cnt ^= 1; P36 ^= HIGH; //P0.1 = 1 SCCOUT /* Tx running */ if (Freq_cnt < 0) { PLC_Tx_bitCnt++; if (PLC_Tx_bitCnt >= 8u) { PLC_Tx_bitCnt = 0u; PLC_Tx_byteCnt++; } temp_bit = (PLC_Tx_PN9[PLC_Tx_byteCnt] << PLC_Tx_bitCnt) & 0x80; if (0x80 == temp_bit) { // TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 98); //285KHz(0,98) Freq_cnt = MAX_285K; } else { // TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 500); //255KHz(0,88) Freq_cnt = MAX_255K; } } else { } /* check Tx ending */ if (PLC_Tx_byte <= PLC_Tx_byteCnt) { /* Stop Timer1 counting */ TIMER_Close(TIMER1); P36 = 0; //P0.0 = 0 } } }
__INLINE void PhaseChangedRoutine(void) { FLAG_PHASE_CHANGED = RESET; tMotor.structMotor.unPhaseChangeCNT++; if (TRUE == tMotor.structMotor.MSR.bZeroCrossDetecting) { // iPhaseChangeTime = TIMER_GetCounter(TIMER1); // Miss ZXD or ZXD success filter // If continuously detected more than MIN_SUCC_ZXD_THRESHOLD ZX, OK! GOOD!! if (TRUE == tMotor.structMotor.MSR.bThisPhaseDetectedZX) { tMotor.structMotor.MSR.unMissedZXD_CNT = 0; if (tMotor.structMotor.MSR.unSuccessZXD_CNT > MIN_SUCC_ZXD_THRESHOLD) { tMotor.structMotor.MSR.bLocked = TRUE; } else { tMotor.structMotor.MSR.unSuccessZXD_CNT++; } } else // If continuously missing detected more than MAX_MISS_ZXD_THRESHOLD ZX, loss lock { tMotor.structMotor.MSR.unSuccessZXD_CNT = 0; // If ZX was not detected in last phase, unLastZXDetectedTime was also not updated // Guess one value unLastZXDetectedTime = GET_TIMER_DIFF((tMotor.structMotor.unActualPeriod >> 2), TIMER_GetCounter(TIMER1)); if (tMotor.structMotor.MSR.unMissedZXD_CNT > MAX_MISS_ZXD_THRESHOLD) { if (TRUE == tMotor.structMotor.MSR.bLocked) { tMotor.structMotor.MSR.bLocked = FALSE; MOTOR_SHUT_DOWN; setError(ERR_INTERNAL); } } else { tMotor.structMotor.MSR.unMissedZXD_CNT++; } } } if (TRUE == tMotor.structMotor.MSR.bLocked) { // Set a rough next phase change time as the same with last phase // After detected ZX in TIM1 interrupt, next phase change time will be re-configured TIMER_SET_CMP_VALUE(TIMER0, tMotor.structMotor.unActualPeriod << 1); } tMotor.structMotor.MSR.bThisPhaseDetectedZX = FALSE; // For debug GPIO_TOGGLE(P50); }
int Timer_InterTimerTriggerMode(void) { int volatile i; /* Init System, IP clock and multi-function I/O In the end of SYS_Init() will issue SYS_LockReg() to lock protected register. If user want to write protected register, please issue SYS_UnlockReg() to unlock protected register if necessary */ SysInit(); /* Init UART to 115200-8n1 for print message */ UART_Open(UART0, 115200); /* This sample code demonstrate inter timer trigger mode using Timer0 and Timer1 * In this mode, Timer0 is working as counter, and triggers Timer1. Using Timer1 * to calculate the amount of time used by Timer0 to count specified amount of events. * By dividing the time period recorded in Timer1 by the event counts, we get * the event frequency. */ printf("Inter timer trigger mode demo code\n"); printf("Please connect input source with Timer 0 counter pin PB.8, press any key to continue\n"); UART_GetChar(); // Give a dummy target frequency here. Will over write prescale and compare value with macro TIMER_Open(TIMER0, TIMER_ONESHOT_MODE, 100); // Update prescale and compare value. Calculate average frequency every 1000 events TIMER_SET_PRESCALE_VALUE(TIMER0, 0); TIMER_SET_CMP_VALUE(TIMER0, 1000); // Update Timer 1 prescale value. So Timer 1 clock is 1MHz TIMER_SET_PRESCALE_VALUE(TIMER1, 11); // We need capture interrupt NVIC_EnableIRQ(TMR1_IRQn); while(1) { complete = 0; // Count event by timer 0, disable drop count (set to 0), disable timeout (set to 0). Enable interrupt after complete TIMER_EnableFreqCounter(TIMER0, 0, 0, TRUE); while(complete == 0); } }
int Timer_FreeCountingMode(void) { int volatile i; /* Init System, IP clock and multi-function I/O In the end of SYS_Init() will issue SYS_LockReg() to lock protected register. If user want to write protected register, please issue SYS_UnlockReg() to unlock protected register if necessary */ SysInit(); /* Init UART to 115200-8n1 for print message */ UART_Open(UART0, 115200); printf("\nThis sample code demonstrate timer free counting mode.\n"); printf("Please connect input source with Timer 0 capture pin PD.11, press any key to continue\n"); UART_GeyChar(); // Give a dummy target frequency here. Will over write capture resolution with macro TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000000); // Update prescale to set proper resolution. // Timer 0 clock source is 12MHz, to set resolution to 1us, we need to // set clock divider to 12. e.g. set prescale to 12 - 1 = 11 TIMER_SET_PRESCALE_VALUE(TIMER0, 11); // Set compare value as large as possible, so don't need to worry about counter overrun too frequently. TIMER_SET_CMP_VALUE(TIMER0, 0xFFFFFF); // Configure Timer 0 free counting mode, capture TDR value on rising edge TIMER_EnableCapture(TIMER0, TIMER_CAPTURE_FREE_COUNTING_MODE, TIMER_CAPTURE_RISING_EDGE); // Start Timer 0 TIMER_Start(TIMER0); // Enable timer interrupt TIMER_EnableCaptureInt(TIMER0); NVIC_EnableIRQ(TMR0_IRQn); while(1); }
__INLINE void BLDCRampUp_Manager(void) { if (SET == FLAG_PHASE_CHANGED) { PhaseChangedRoutine(); if (unPhaseChangeCNT_AtCurrentPeriod > CHANGE_DT_PR_AFTER_PHASE_CHANGED_NUM) { unPhaseChangeCNT_AtCurrentPeriod = 0; // Change duty and period // MOTOR_RAMPUP_DT_INCR(tMotor.structMotor.ACT_DUTY); MOTOR_RAMPUP_PR_DCR(tMotor.structMotor.unActualPeriod); if (tMotor.structMotor.unActualPeriod <= MOTOR_RAMPUP_PR_MIN) { unPeriodChangeCNT_AfterPR_ReachMini++; } } unPhaseChangeCNT_AtCurrentPeriod++; // MOTOR_SET_DUTY(tMotor.structMotor.ACT_DUTY); TIMER_SET_CMP_VALUE(TIMER0, tMotor.structMotor.unActualPeriod); PHASE_INCREASE(unCurrentPhase); // Modify PWM->PHCHGNXT at last because I don't know how long needed to reload PHCH with PHCHNEXT after TIM0 time-out PWM->PHCHGNXT = GET_PHASE_VALUE(unCurrentPhase); } }
// Take charge of all Motot control void BLDC_SensorLessManager(void) { uint16_t unMotorAlreadyRotatingPhaseTime; static uint32_t iEnterTimeBeforeWait; dutyProtection(); phaseDurationProtection(unLastPhaseChangeTime); switch (tMotorState) { case MOTOR_IDLE: if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { unRotateDetectStartTime = unSystemTick; tRotateDetectState = DETECT_START; tMotorState = MOTOR_START; } break; case MOTOR_START: if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { // Later implement this when motor can rotate // Then stop it while rotating to measure the waveform // Manually rotate it is too slow unMotorAlreadyRotatingPhaseTime = canMotorContinueRunning(); if (unMotorAlreadyRotatingPhaseTime != IS_ROTATING_DETECTING) { if (unMotorAlreadyRotatingPhaseTime > 0) { // 1 to 65534 tMotorState = MOTOR_LOCKED; } else { // When back to Idle state the motor was already shut down // MOTOR_SHUT_DOWN; unCurrentPhase = 0; unLocateIndex = 0; tMotor.structMotor.MSR.unMissedZXD_CNT = 0; unLastPhaseChangeTime = unSystemTick; tMotor.structMotor.MSR.bMotorPowerOn = TRUE; // Clear start detect zero cross flag tMotor.structMotor.MSR.bZeroCrossDetecting = FALSE; tMotor.structMotor.MSR.bLocked = FALSE; //setPhaseManually(tMotor.structMotor.LCT_DUTY, unCurrentPhase); BRG_ENABLE; tMotorState = MOTOR_LOCATE; } } } else { BLDC_stopMotor(); } break; case MOTOR_LOCATE: if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { if (BLDC_LocatingManager() == STATUS_FINISHED) { iEnterTimeBeforeWait = unSystemTick; tMotorState = MOTOR_WAIT_AFTER_LOCATE; } } else { BLDC_stopMotor(); } break; case MOTOR_WAIT_AFTER_LOCATE: if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { if ((uint32_t)(unSystemTick - iEnterTimeBeforeWait) >= WAIT_AFTER_LOCATE_TIME) { tMotor.structMotor.unActualDuty = tMotor.structMotor.unRampUpDuty; tMotor.structMotor.unActualPeriod = tMotor.structMotor.unRampUpPeriod; tMotor.structMotor.MSR.bMotorPowerOn = TRUE; PHASE_INCREASE(unCurrentPhase); setPhaseManually(tMotor.structMotor.unActualDuty, unCurrentPhase); BRG_ENABLE; // Set timer 0 valure, use timer 0 to change phase automatically // ************************************************************************ // ----==== From here current unCurrentPhase is actually next phase ====---- // ----==== Because we want to use the HW auto phase changer (PWM->PHCHGNXT) ====---- // So increase unCurrentPhase again. Want to get real current phase value? Read PWM->PHCHG. // ************************************************************************ PHASE_INCREASE(unCurrentPhase); PWM->PHCHGNXT = GET_PHASE_VALUE(unCurrentPhase); // !!!! Need to make sure CPU runs to here every min tMotor.structMotor.ACT_PERIOD time !!! // !!!! If not , timer counter may already passed tMotor.structMotor.ACT_PERIOD, !!!! // !!!! then need to count to max timer counter number (which is 2^24), !!!! // !!!! go back to 0 and triger interrupt when reach ACT_PERIOD again !!!! TIMER_SET_CMP_VALUE(TIMER0, tMotor.structMotor.unActualPeriod); TIMER_Start(TIMER0); // Once started, running and interrupting until Motor stop TIMER_EnableInt(TIMER0); unPeriodChangeCNT_AfterPR_ReachMini = 0; unPhaseChangeCNT_AtCurrentDuty = 0; unPhaseChangeCNT_AtCurrentPeriod = 0; tMotorState = MOTOR_RAMPUP_WO_ZXD; } } else { BLDC_stopMotor(); } break; case MOTOR_RAMPUP_WO_ZXD: // without zero cross detection if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { BLDCRampUp_Manager(); if (tMotor.structMotor.unActualPeriod <= MOTOR_START_ZXD_SPEED) //(iRampUpPeriodMiniCNT > MOTOR_START_ZXD_MINROT_CNT) // { tMotor.structMotor.MSR.bThisPhaseDetectedZX = FALSE; tMotor.structMotor.MSR.bZeroCrossDetecting = TRUE; // Speed is enough for zero cross detecting // Prepare everything // T0 used to change phase automatically -- already configured // T1 used to filter ZX // TIMER_SET_CMP_VALUE(TIMER1, GET_TIM1_CMP_VALUE(TIMER1->TDR + AVOID_ZXD_AFTER_PHCHG)); // FLAG_TIM1_USEAGE = ENUM_TIM1_AVOID_ZXD; ACMP0_ENABLE; TIMER_Start(TIMER1); // Once started, running until Motor stop // TIMER_EnableInt(TIMER1); // Suppose last ZX detected time // unLastZXDetectedTime = MINI51_TIM_CNT_MAX - tMotor.structMotor.ACT_PERIOD / 2; tMotorState = MOTOR_RAMPUP_W_ZXD; } } else { BLDC_stopMotor(); } break; case MOTOR_RAMPUP_W_ZXD: // with zero cross detection if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { if (TRUE == tMotor.structMotor.MSR.bLocked) { // Finally, everything was prepared: // T0 used to change phase automatically // T1 used to filter ZX tMotorState = MOTOR_LOCKED; } else { if (unPeriodChangeCNT_AfterPR_ReachMini < RAMP_UP_MIN_PERIOD_NUM_THRS) { BLDCRampUp_Manager(); } else { setError(ERR_RAMPUP_FAIL); } } } else { BLDC_stopMotor(); } break; case MOTOR_LOCKED: if (tMotor.structMotor.MCR.bMotorNeedToRun && NO_MOTOR_EEROR) { BLDCSpeedManager(); // Mainly PWM duty increase/decrease } else { BLDC_stopMotor(); } break; default: break; } }
void HardwareTimer::setCompare(uint32_t val) { TIMER_SET_CMP_VALUE(dev, val); }
/*---------------------------------------------------------------------------------------------------------*/ int main(void) { volatile uint32_t u32InitCount; /* Unlock protected registers */ SYS_UnlockReg(); /* Init System, peripheral clock and multi-function I/O */ SYS_Init(); /* Lock protected registers */ SYS_LockReg(); /* Init UART0 for printf */ UART0_Init(); printf("\n\nCPU @ %d Hz\n", SystemCoreClock); printf("+-------------------------------------------------+\n"); printf("| Timer1 External Counter Input Sample Code |\n"); printf("+-------------------------------------------------+\n\n"); printf("# Timer Settings:\n"); printf(" Timer1: Clock source is HCLK(50 MHz); Continuous counting mode; Interrupt enable;\n"); printf(" External counter input enable; TCMP is 56789.\n"); printf("# Connect P2.0 to T1 pin and pull P2.0 High/Low as T1 counter input source.\n\n"); /* Configure P2.0 as GPIO output pin and pull pin status to Low first */ GPIO_SetMode(P2, 0, GPIO_PMD_OUTPUT); P20 = 0; /* Initial Timer1 default setting */ TIMER_Open(TIMER1, TIMER_CONTINUOUS_MODE, 1); /* Configure Timer1 setting for external counter input function */ TIMER_SELECT_TOUT_PIN(TIMER1, TIMER_TOUT_PIN_FROM_TX_PIN); TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 56789); TIMER_EnableEventCounter(TIMER1, TIMER_COUNTER_FALLING_EDGE); TIMER_EnableInt(TIMER1); /* Enable Timer1 NVIC */ NVIC_EnableIRQ(TMR1_IRQn); /* Clear Timer1 interrupt counts to 0 */ g_au32TMRINTCount[1] = 0; /* Start Timer1 counting */ TIMER_Start(TIMER1); /* To check if TDR of Timer1 must be 0 as default value */ if(TIMER_GetCounter(TIMER1) != 0) { printf("Default counter value is not 0. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); } /* To generate one counter event to T1 pin */ GeneratePORT2Counter(0, 1); /* To check if TDR of Timer1 must be 1 */ while(TIMER_GetCounter(TIMER1) == 0); if(TIMER_GetCounter(TIMER1) != 1) { printf("Get unexpected counter value. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); } /* To generate remains counts to T1 pin */ GeneratePORT2Counter(0, (56789 - 1)); while(1) { if((g_au32TMRINTCount[1] == 1) && (TIMER_GetCounter(TIMER1) == 56789)) { printf("Timer1 external counter input function ... PASS.\n"); break; } } /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); }
/*---------------------------------------------------------------------------------------------------------*/ int main(void) { volatile uint32_t u32InitCount; uint32_t au32CAPValus[10]; /* Unlock protected registers */ SYS_UnlockReg(); /* Init System, peripheral clock and multi-function I/O */ SYS_Init(); /* Lock protected registers */ SYS_LockReg(); /* Init UART0 for printf */ UART0_Init(); printf("\n\nCPU @ %d Hz\n", SystemCoreClock); printf("+---------------------------------------------------+\n"); printf("| Timer External Capture Function Sample Code |\n"); printf("+---------------------------------------------------+\n\n"); printf("# Timer Settings:\n"); printf(" Timer0: Clock source is 12 MHz; Toggle-output mode and frequency is 500 Hz.\n"); printf(" Timer3: Clock source is 12 MHz; Toggle-output mode and frequency is 1 Hz.\n"); printf(" Timer2: Clock source is HCLK(72 MHz); Continuous counting mode; TCMP is 0xFFFFFF;\n"); printf(" Counter pin enable; Capture pin and capture interrupt enable;\n"); printf("# Generate 500 Hz frequency from TM0 and connect TM0 pin to Timer2 counter pin.\n"); printf("# Generate 1 Hz frequency from TM3 and connect TM3 pin to TM2_EXT capture pin.\n"); printf("# Get 500 event counts from Timer2 counter pin when each TM2_EXT pin interrupt occurred.\n\n"); /* Initial Timer0 and Timer3 default setting */ TIMER_Open(TIMER0, TIMER_TOGGLE_MODE, 1000); TIMER_Open(TIMER3, TIMER_TOGGLE_MODE, 2); /* Initial Timer2 default setting */ TIMER_Open(TIMER2, TIMER_CONTINUOUS_MODE, 1); /* Configure Timer2 setting for external counter input and capture function */ TIMER_SET_PRESCALE_VALUE(TIMER2, 0); TIMER_SET_CMP_VALUE(TIMER2, 0xFFFFFF); TIMER_EnableEventCounter(TIMER2, TIMER_COUNTER_FALLING_EDGE); TIMER_EnableCapture(TIMER2, TIMER_CAPTURE_FREE_COUNTING_MODE, TIMER_CAPTURE_FALLING_EDGE); TIMER_EnableCaptureInt(TIMER2); /* Enable Timer2 NVIC */ NVIC_EnableIRQ(TMR2_IRQn); /* Clear Timer2 interrupt counts to 0 */ u32InitCount = g_au32TMRINTCount[2] = 0; /* Start Timer0, Timer2 and Timer3 counting */ TIMER_Start(TIMER0); TIMER_Start(TIMER2); TIMER_Start(TIMER3); /* Check TM2_EXT interrupt counts */ while(1) { if(g_au32TMRINTCount[2] != u32InitCount) { au32CAPValus[u32InitCount] = TIMER_GetCaptureData(TIMER2); printf("[%2d] - %4d\n", g_au32TMRINTCount[2], au32CAPValus[u32InitCount]); if(u32InitCount > 1) { if((au32CAPValus[u32InitCount] - au32CAPValus[u32InitCount - 1]) != 500) { printf("*** FAIL ***\n"); while(1); } } u32InitCount = g_au32TMRINTCount[2]; } if(u32InitCount == 10) break; } /* Stop Timer0, Timer2 and Timer3 counting */ TIMER_Close(TIMER0); TIMER_Close(TIMER2); TIMER_Close(TIMER3); printf("*** PASS ***\n"); while(1); }