void TFC_InitMotorPWM() { //Clock Setup for the TPM requires a couple steps. //1st, set the clock mux //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) SIM_SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1); //We want the MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) //Enable the Clock to the FTM0 Module //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; //The TPM Module has Clock. Now set up the peripheral //Blow away the control registers to ensure that the counter is not running TPM0_SC = 0; TPM0_CONF = 0; //Set TPM module to continue in debug mode TPM0_CONF |= 0x00000060; //While the counter is disabled we can setup the prescaler TPM0_SC = TPM_SC_PS(FTM0_CLK_PRESCALE); //Setup the mod register to get the correct PWM Period TPM0_MOD = FTM0_CLOCK/(1<<FTM0_CLK_PRESCALE)/FTM0_OVERFLOW_FREQUENCY; //Setup Channels 0,1,2,3 TPM0_C0SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; TPM0_C1SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; TPM0_C2SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; TPM0_C3SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; //Enable the Counter //Set the Default duty cycle to 50% duty cycle TFC_SetMotorPWM(0.0,0.0); //Enable the TPM Counter TPM0_SC |= TPM_SC_CMOD(1); //Enable the FTM functions on the the port PORTC_PCR1 = PORT_PCR_MUX(4); PORTC_PCR2 = PORT_PCR_MUX(4); PORTC_PCR3 = PORT_PCR_MUX(4); PORTC_PCR4 = PORT_PCR_MUX(4); }
void app_InitServos() { //Clock Setup for the TPM requires a couple steps. //1st, set the clock mux //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) SIM_SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1); //We want the MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) //Enable the Clock to the FTM0 Module //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; //The TPM Module has Clock. Now set up the peripheral //Blow away the control registers to ensure that the counter is not running TPM1_SC = 0; TPM1_CONF = 0; //While the counter is disabled we can setup the prescaler TPM1_SC = TPM_SC_PS(FTM1_CLK_PRESCALE); TPM1_SC |= TPM_SC_TOIE_MASK; //Enable Interrupts for the Timer Overflow //Setup the mod register to get the correct PWM Period TPM1_MOD = FTM1_CLOCK/(1<<(FTM1_CLK_PRESCALE+1))/FTM1_OVERFLOW_FREQUENCY; //Setup Channels 0 and 1 TPM1_C0SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; TPM1_C1SC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; //Enable the Counter //Set the Default duty cycle to servo neutral app_SetServo(0, 0.0); app_SetServo(1, 0.0); //Enable the TPM COunter TPM1_SC |= TPM_SC_CMOD(1); //Enable TPM1 IRQ on the NVIC enable_irq (INT_TPM1-16); //Enable the FTM functions on the the port PORTB_PCR0 = PORT_PCR_MUX(3); PORTB_PCR1 = PORT_PCR_MUX(3); }
void TPM_vfnStartTimer(uint8_t bTPMToEnable, uint8_t bTPMPrescaler) { uint32_t * pdwTPM_SCRegister; if(bTPMToEnable < MAX_TPM) { pdwTPM_SCRegister = (uint32_t*)TPM_gapdwRegisters[bTPMToEnable][TPM_SC]; /* Enable module with internal CLK and */ *pdwTPM_SCRegister = TPM_SC_CMOD(0x01)|TPM_SC_PS(bTPMPrescaler); } }
void Timer_Config(void){ //TPM0->SC = (1UL << 6)|(1UL << 2)|(1UL << 1)|(1UL << 3)|TPM_SC_TOF_MASK; TPM0->CNT = 0; //TPM0->SC = (1UL << 6); //TPM0->MOD = 131; NVIC_EnableIRQ(17); SIM->SCGC6 |=SIM_SCGC6_TPM0_MASK; //TPM0->STATUS = 0x100; TPM0->MOD = 0x12C0; TPM0->SC = TPM_SC_TOIE_MASK|TPM_SC_CMOD(1); }
/* ===================================================================*/ LDD_TDeviceData* TU2_Init(LDD_TUserData *UserDataPtr) { TU2_TDeviceData *DeviceDataPrv; if (PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU2_ID] == NULL) { /* Allocate device structure */ /* {FreeRTOS RTOS Adapter} Driver memory allocation: RTOS function call is defined by FreeRTOS RTOS Adapter property */ DeviceDataPrv = (TU2_TDeviceData *)pvPortMalloc(sizeof(TU2_TDeviceData)); #if FreeRTOS_CHECK_MEMORY_ALLOCATION_ERRORS if (DeviceDataPrv == NULL) { return (NULL); } #endif DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr = 1U; /* First initialization */ } else { /* Memory is already allocated */ DeviceDataPrv = (TU2_TDeviceDataPtr) PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU2_ID]; DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr++; /* Increment counter of initialization */ return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ } /* SIM_SCGC6: TPM1=1 */ SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; /* TPM1_SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,DMA=0,TOF=0,TOIE=0,CPWMS=0,CMOD=0,PS=0 */ TPM1_SC = (TPM_SC_CMOD(0x00) | TPM_SC_PS(0x00)); /* Clear status and control register */ /* TPM1_CNT: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,COUNT=0 */ TPM1_CNT = TPM_CNT_COUNT(0x00); /* Reset counter register */ /* TPM1_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM1_C0SC = 0x00U; /* Clear channel status and control register */ /* TPM1_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM1_C1SC = 0x00U; /* Clear channel status and control register */ /* TPM1_MOD: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,MOD=0x02B3 */ TPM1_MOD = TPM_MOD_MOD(0x02B3); /* Set up modulo register */ /* TPM1_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=1,MSA=0,ELSB=1,ELSA=1,??=0,DMA=0 */ TPM1_C0SC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_ELSA_MASK); /* Set up channel status and control register */ /* TPM1_C0V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0 */ TPM1_C0V = TPM_CnV_VAL(0x00); /* Set up channel value register */ /* PORTE_PCR20: ISF=0,MUX=3 */ PORTE_PCR20 = (uint32_t)((PORTE_PCR20 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x04) )) | (uint32_t)( PORT_PCR_MUX(0x03) )); DeviceDataPrv->Source = TPM_PDD_SYSTEM; /* Store clock source */ /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_TU2_ID,DeviceDataPrv); return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); uint32_t clkdiv = 0; float clkval; if (mcgpllfll_frequency()) { SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK clkval = mcgpllfll_frequency() / 1000000.0f; } else { SIM->SOPT2 |= SIM_SOPT2_TPMSRC(2); // Clock source: ExtOsc clkval = extosc_frequency() / 1000000.0f; } while (clkval > 1) { clkdiv++; clkval /= 2.0; if (clkdiv == 7) break; } pwm_clock = clkval; unsigned int port = (unsigned int)pin >> PORT_SHIFT; unsigned int tpm_n = (pwm >> TPM_SHIFT); unsigned int ch_n = (pwm & 0xFF); SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port); SIM->SCGC6 |= 1 << (SIM_SCGC6_TPM0_SHIFT + tpm_n); TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n); tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(clkdiv); // (clock)MHz / clkdiv ~= (0.75)MHz tpm->CONTROLS[ch_n].CnSC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); /* No Interrupts; High True pulses on Edge Aligned PWM */ obj->CnV = &tpm->CONTROLS[ch_n].CnV; obj->MOD = &tpm->MOD; obj->CNT = &tpm->CNT; // default to 20ms: standard for servos, and fine for e.g. brightness control pwmout_period_ms(obj, 20); pwmout_write (obj, 0); // Wire pinout pinmap_pinout(pin, PinMap_PWM); }
void TPM_init_PWM(TPM_MemMapPtr TPMx, int clock_source, int module, int clock_mode, int ps, int counting_mode) { if(TPMx == TPM0_BASE_PTR) SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; else if(TPMx == TPM1_BASE_PTR) SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; else SIM_SCGC6 |= SIM_SCGC6_TPM2_MASK; SIM_SOPT2 |= SIM_SOPT2_TPMSRC(clock_source); TPM_MOD_REG(TPMx) = module; TPM_SC_REG(TPMx) |= TPM_SC_CMOD(clock_mode) | TPM_SC_PS(ps); if(counting_mode) TPM_SC_REG(TPMx) |= TPM_SC_CPWMS_MASK; }
/*configures TPM0_CH3 green LED to be PWM controlled*/ void tpm_init(void) { SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; //enable TPM clock gate SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1) | SIM_SOPT2_PLLFLLSEL_MASK; //select PLL as clock source of TPM0_MOD = 1000; #ifdef FRDM_REVA TPM0_C3SC = TPM_CnSC_MSB_MASK |TPM_CnSC_ELSB_MASK; //PWM edge aligned TPM0_C3V = 500; #else TPM0_C5SC = TPM_CnSC_MSB_MASK |TPM_CnSC_ELSB_MASK; //PWM edge aligned TPM0_C5V = 500; #endif TPM0_SC |= TPM_SC_PS(0) | TPM_SC_CMOD(1); }
void tpm_init(void){ PORTD->PCR[5] = PORT_PCR_MUX(4); //TPM0_CH5 PORTE->PCR[29] = PORT_PCR_MUX(3); //TPM0_CH2 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; //dolaczenie sygnalu taktujacego do modulu TMP SIM->SCGC5 |= (SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK); //dolaczenie sygnalu taktujacego do portu D i E, zrobione tez w leds initializze SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // MCGFLLCLK clock or MCGPLLCLK/2 SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //MCGPLLCLK clock with fixed divide by two TPM0->MOD = TPM_MOD_MOD(4095); TPM0->CNT |= TPM_CNT_COUNT_SHIFT; //reset counter //edge aligned pwm TPM0->CONTROLS[2].CnSC |= TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; //high true pulses TPM0->CONTROLS[5].CnSC |= TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_ELSA_MASK; //low true pulses //edge aligned pwm end //center aligned PWM /* TPM0->CONTROLS[2].CnSC |= TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; //high-true pulses TPM0->CONTROLS[5].CnSC |= TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; //low true pulses */ //center aligned PWM end TPM0->CONTROLS[2].CnV = TPM_CnV_VAL(0); //poczatkowa wartosc wspolczyynika wypelninia TPM0->CONTROLS[5].CnV = TPM_CnV_VAL(0); //poczatkowa wartosc wspolczyynika wypelninia TPM0->SC = TPM_SC_PS(0x07) | TPM_SC_CPWMS_MASK | TPM_SC_CMOD(0x01); //divide by 128 !! //upcounting //increment every counter clock }
void Echo_init(void){ // PORTE 20 CONFIG (TPM1 Channel 0) SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; PORTE->PCR[ECHO_PIN] |= PORT_PCR_MUX(0x03); //*************************************************************** // TPM1 CONFIG SIM->SOPT2 |= SIM_SOPT2_TPMSRC(3); // MCGIRC MCG->C1 |= MCG_C1_IRCLKEN_MASK; // MCGIRCLK active. MCG->C2 |= MCG_C2_IRCS_MASK; // External FAST (4MHz) reference clock is selected. SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK; TPM1->SC |= TPM_SC_PS(1) // Divide by 2 (1MHz) | TPM_SC_CMOD(0x01); // Enabling TPM1 NVIC_ClearPendingIRQ(TPM1_IRQn); NVIC_EnableIRQ(TPM1_IRQn); NVIC_SetPriority(TPM1_IRQn, 1); TPM1->CONTROLS[0].CnSC |= TPM_CnSC_ELSA_MASK // Input capture -> every edge | TPM_CnSC_ELSB_MASK | TPM_CnSC_CHIE_MASK; // Channel int. enabled }
/* ===================================================================*/ LDD_TDeviceData* TU1_Init(LDD_TUserData *UserDataPtr) { TU1_TDeviceData *DeviceDataPrv; if (PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU1_ID] == NULL) { /* Allocate device structure */ /* {Default RTOS Adapter} Driver memory allocation: Dynamic allocation is simulated by a pointer to the static object */ DeviceDataPrv = &DeviceDataPrv__DEFAULT_RTOS_ALLOC; DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr = 1U; /* First initialization */ } else { /* Memory is already allocated */ DeviceDataPrv = (TU1_TDeviceDataPtr) PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU1_ID]; DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr++; /* Increment counter of initialization */ return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ } /* SIM_SCGC6: TPM0=1 */ SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; /* TPM0_SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,DMA=0,TOF=0,TOIE=0,CPWMS=0,CMOD=0,PS=0 */ TPM0_SC = (TPM_SC_CMOD(0x00) | TPM_SC_PS(0x00)); /* Clear status and control register */ /* TPM0_CNT: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,COUNT=0 */ TPM0_CNT = TPM_CNT_COUNT(0x00); /* Reset counter register */ /* TPM0_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C0SC = 0x00U; /* Clear channel status and control register */ /* TPM0_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C1SC = 0x00U; /* Clear channel status and control register */ /* TPM0_C2SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C2SC = 0x00U; /* Clear channel status and control register */ /* TPM0_C3SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C3SC = 0x00U; /* Clear channel status and control register */ /* TPM0_C4SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C4SC = 0x00U; /* Clear channel status and control register */ /* TPM0_C5SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM0_C5SC = 0x00U; /* Clear channel status and control register */ /* TPM0_MOD: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,MOD=0x0830 */ TPM0_MOD = TPM_MOD_MOD(0x0830); /* Set up modulo register */ /* TPM0_C5SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=1,MSA=0,ELSB=1,ELSA=1,??=0,DMA=0 */ TPM0_C5SC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_ELSA_MASK); /* Set up channel status and control register */ /* TPM0_C5V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0 */ TPM0_C5V = TPM_CnV_VAL(0x00); /* Set up channel value register */ /* TPM0_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=1,MSA=0,ELSB=1,ELSA=1,??=0,DMA=0 */ TPM0_C0SC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_ELSA_MASK); /* Set up channel status and control register */ /* TPM0_C0V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0 */ TPM0_C0V = TPM_CnV_VAL(0x00); /* Set up channel value register */ /* PORTD_PCR5: ISF=0,MUX=4 */ PORTD_PCR5 = (uint32_t)((PORTD_PCR5 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x03) )) | (uint32_t)( PORT_PCR_MUX(0x04) )); /* PORTD_PCR0: ISF=0,MUX=4 */ PORTD_PCR0 = (uint32_t)((PORTD_PCR0 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x03) )) | (uint32_t)( PORT_PCR_MUX(0x04) )); DeviceDataPrv->Source = TPM_PDD_SYSTEM; /* Store clock source */ /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_TU1_ID,DeviceDataPrv); return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ }
void Timer_TPM::__start_timer() { TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register TPM0->SC |= TPM_SC_TOIE_MASK; //Enable interrupt TPM0->SC |= TPM_SC_CMOD(1); //Start the timer. Timer will increment on the TPM clock edges, not an external clock }
void setupTPM() { /******* FIRST: Setup TPM Clocks **********/ /* LED Timers: slow enough to be seen by the human eye, fast * enough to be a seamless fade --> 200Hz frequency (200 ticks/sec) * * Accomplished by dividing the fast 4 MHz clock by 128 by setting * the prescaler bits to 7 [DIVIDE_BY_128] and further divide it by * 155 setting the modulus register to 154 [DIVIDE_TO_200HZ] * * 4 MHz / 128 / 155 = ~200Hz (201.61Hz) */ // TPM0: Used to toggle blue LED TPM0_BASE_PTR->SC = TPM_SC_CMOD(1) | TPM_SC_PS(DIVIDE_BY_128); TPM0_BASE_PTR->MOD = DIVIDE_TO_200HZ; // TPM2: Used to toggle green/red LEDs TPM2_BASE_PTR->SC = TPM_SC_CMOD(1) | TPM_SC_PS(DIVIDE_BY_128); TPM2_BASE_PTR->MOD = DIVIDE_TO_200HZ; /* * Profiling timer: required to have 10us period -> 100 kHz * Accomplished by dividing the fast 4 MHz clock by 8 by setting * the prescaler bits to 3 [DIVIDE_BY_8] and further divide it by * 5 setting the modulus register to 4 [DIVIDE_TO_10kHZ] * * 4 MHz / 8 / 5 = 100 kHz */ // TPM1: Used to profile functions TPM1_BASE_PTR->SC = TPM_SC_CMOD(1) | TPM_SC_PS(DIVIDE_BY_8); TPM1_BASE_PTR->MOD = DIVIDE_TO_10kHZ; /* PORTB clock is enabled by writing to the SGC5 register. Turn on clock gating to PortB * module (red and green LEDs) and PortD module (blue LED) */ SIM_BASE_PTR->SCGC5 |= SIM_SCGC5_PORTB_MASK| SIM_SCGC5_PORTD_MASK; /******* SECOND: Setup TPM in PWM Mode **********/ /* * Configure the timer in the PWM mode to manually change the value of the PTB18/19 [red/blue] pins * The PTB18 and PTB19 pins are multiplexed with channel 0 of the TPM2 module. Switch the pins to * be the TPM outputs instead of normal GPIO pins by writing the PCR register. */ PORTB_BASE_PTR->PCR[RED_PIN] = PORTB_BASE_PTR->PCR[GREEN_PIN] = PORT_PCR_MUX(TPM_OUTPUT_SELECTION); /* * Do the same for PTD1 [blue] pin */ PORTD_PCR1 = PORT_PCR_MUX(4); // TPM0_CH1 enable on PTD1 (blue) PTB_BASE_PTR->PDDR = 1 << RED_PIN; // Configure Red Pin to be output /* * Configure TPM0/TPM2 to run in the PWM mode and generate short impulses (1/8 of the timer period) * */ TPM2_BASE_PTR->CONTROLS[RED_LED].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; TPM2_BASE_PTR->CONTROLS[GREEN_LED].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; TPM0_BASE_PTR->CONTROLS[BLUE_LED].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; /******* THIRD : Set default LED values = Off initially **********/ TPM2_BASE_PTR->CONTROLS[RED_LED].CnV = 0x0; TPM2_BASE_PTR->CONTROLS[GREEN_LED].CnV = 0x0; TPM0_BASE_PTR->CONTROLS[BLUE_LED].CnV = 0x0; /******* LAST : Enable interrupts **********/ NVIC_EnableIRQ(TPM0_IRQn); // Use TPM1 for profiler timer NVIC_EnableIRQ(TPM1_IRQn); // Use TPM1 for profiler timer }
/** init the timer TPM1 for measuring temperature using input capture * */ void smt160_init() { int prio = 2; // priorita interruptu; 0 az 3, 0 = max /* Initialize our global variables */ gsmt_start = 0; gsmt_pulse = 0; gsmt_period = 0; gsmt_tmp_pulse = 0; gsmt_pulses = 0; gsmt_period_sum = 0; gsmt_sumcnt = 0; /* Enable Port A clock (pins used for input capture) */ SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; /* enable input pins for TPM1 channels 0 and 1 The timer channel is Alt 3 function of the pins */ PORTA_PCR12 = PORT_PCR_MUX(3); /* PTA12 = channel 0 for TPM1 */ PORTA_PCR13 = PORT_PCR_MUX(1); /* using PTA13 as GPIO for deciding falling/rising */ GPIOA_PDDR &= ~(1 << SMT160_INPUT_PIN_NO); /* set PTA13 to input mode */ /* Enable clock for timer TMP1 */ SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; /* and clock source */ SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1); // select the PLLFLLCLK as TPM clock source /* Set timer to input capture mode etc. */ TPM1_SC = TPM_SC_CMOD(1) | TPM_SC_PS(0); //0x08; // CMOD = 01, prescaler = 1 /* test TOF interrupt TPM1_SC |= TPM_SC_TOIE_MASK; TPM1_MOD = 10000; */ #if 0 // Input capture config // Version with 2 input pins used: channel 0 detects pulses, channel 1 // detects period. TPM1_C0SC = 0; /* clear any pending interrupt and set all values to default */ TPM1_C0SC |= TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK; /* input capture on falling and rising edges */ TPM1_C0SC |= TPM_CnSC_CHIE_MASK; /* enable channel interrupt */ TPM1_C1SC = 0; /* clear any pending interrupt and set all values to default */ TPM1_C1SC |= TPM_CnSC_ELSA_MASK; /* input capture on rising edges only */ TPM1_C1SC |= TPM_CnSC_CHIE_MASK; /* enable channel interrupt */ #endif // Input capture config // Version with 1 pin used; wait for rising edge TPM1_C0SC = 0; /* clear any pending interrupt and set all values to default */ /* input capture on rising and falling edge + enable channel interrupt */ TPM1_C0SC |= TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_CHIE_MASK; // Enable the interrupt // Note: sample code package provides function for this in arm_cm0.c; (enable_irq(interrupt);) // CMSIS compatible environment should implement NVIC_EnableIRQ((IRQn_Type)interrupt); // In NVIC there are 32-bit registers where each bit corresponds to 1 interrupt // The number of the interrupt used in NVIC is "non-core" int number, which is the // absolute number - 16. (there are 16 core interrupts which are not controlled by NVIC) // ICPR register = clear pending flag (writing 1 clears pending interrupt) // ISER register = enable interrupt by writing 1 to its bit NVIC_ICPR |= (1 << (INT_TPM1 - 16) ); // clear possibly pending interrupt NVIC_ISER |= (1 << (INT_TPM1 - 16) ); // enable the interrupt // Set priority for the interrupt // Bit field starting location = 8 * (IRQ mod 4) + 6 = // Zde IRQ = 18 (cislo TPM1 int v MKL25Z4.h - 16) // start = 8 * 18 mod 4 + 6 = 8 * 2 + 6 = 22 NVIC_IPR4 = ((prio & 0x03) << 22); EnableInterrupts; }
void Start_TPM(void) { // Enable counter TPM0->SC |= TPM_SC_CMOD(1); }
/* ===================================================================*/ LDD_TDeviceData* TU2_Init(LDD_TUserData *UserDataPtr) { TU2_TDeviceData *DeviceDataPrv; if (PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU2_ID] == NULL) { /* Allocate device structure */ /* {FreeRTOS RTOS Adapter} Driver memory allocation: Dynamic allocation is simulated by a pointer to the static object */ DeviceDataPrv = &DeviceDataPrv__DEFAULT_RTOS_ALLOC; DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr = 1U; /* First initialization */ } else { /* Memory is already allocated */ DeviceDataPrv = (TU2_TDeviceDataPtr) PE_LDD_DeviceDataList[PE_LDD_COMPONENT_TU2_ID]; DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ DeviceDataPrv->InitCntr++; /* Increment counter of initialization */ return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ } /* Interrupt vector(s) allocation */ /* {FreeRTOS RTOS Adapter} Set interrupt vector: IVT is static, ISR parameter is passed by the global variable */ INT_TPM1__BAREBOARD_RTOS_ISRPARAM = DeviceDataPrv; /* SIM_SCGC6: TPM1=1 */ SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; /* TPM1_SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,DMA=0,TOF=0,TOIE=0,CPWMS=0,CMOD=0,PS=0 */ TPM1_SC = (TPM_SC_CMOD(0x00) | TPM_SC_PS(0x00)); /* Clear status and control register */ /* TPM1_CNT: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,COUNT=0 */ TPM1_CNT = TPM_CNT_COUNT(0x00); /* Reset counter register */ /* TPM1_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM1_C0SC = 0x00U; /* Clear channel status and control register */ /* TPM1_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */ TPM1_C1SC = 0x00U; /* Clear channel status and control register */ /* TPM1_MOD: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,MOD=0xFFFF */ TPM1_MOD = TPM_MOD_MOD(0xFFFF); /* Set up modulo register */ /* TPM1_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=1,MSB=1,MSA=0,ELSB=1,ELSA=1,??=0,DMA=0 */ TPM1_C1SC = TPM_CnSC_CHIE_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK | TPM_CnSC_ELSA_MASK; /* Set up channel status and control register */ /* TPM1_C1V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0 */ TPM1_C1V = TPM_CnV_VAL(0x00); /* Set up channel value register */ /* PORTB_PCR1: ISF=0,MUX=3 */ PORTB_PCR1 = (uint32_t)((PORTB_PCR1 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x04) )) | (uint32_t)( PORT_PCR_MUX(0x03) )); DeviceDataPrv->EnEvents = 0x01U; /* Enable selected events */ DeviceDataPrv->Source = TPM_PDD_SYSTEM; /* Store clock source */ /* NVIC_IPR4: PRI_18=0x80 */ NVIC_IPR4 = (uint32_t)((NVIC_IPR4 & (uint32_t)~(uint32_t)( NVIC_IP_PRI_18(0x7F) )) | (uint32_t)( NVIC_IP_PRI_18(0x80) )); /* NVIC_ISER: SETENA|=0x00040000 */ NVIC_ISER |= NVIC_ISER_SETENA(0x00040000); /* TPM1_SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,DMA=0,TOF=0,TOIE=0,CPWMS=0,CMOD=0,PS=4 */ TPM1_SC = (TPM_SC_CMOD(0x00) | TPM_SC_PS(0x04)); /* Set up status and control register */ /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_TU2_ID,DeviceDataPrv); return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the device data structure */ }