//========================================================================= __myevic__ void SetPWMClock() { uint32_t clk; if ( gFlags.pwm_pll ) { clk = CLK_CLKSEL2_PWM0SEL_PLL; PWMCycles = CLK_GetPLLClockFreq() / BBC_PWM_FREQ; } else { clk = CLK_CLKSEL2_PWM0SEL_PCLK0; PWMCycles = CLK_GetPCLK0Freq() / BBC_PWM_FREQ; } MaxDuty = PWMCycles - 1; MinBuck = PWMCycles / 48; MaxBoost = PWMCycles / 12; ProbeDuty = PWMCycles / 8; BoostWindow = PWMCycles / 19; #define MaxBuck MaxDuty #define MinBoost MaxDuty if ( ISCUBO200 || ISRX200S || ISRX23 || ISRX300 ) { MaxDuty = 95 * PWMCycles / 100; } CLK_EnableModuleClock( PWM0_MODULE ); CLK_SetModuleClock( PWM0_MODULE, clk, 0 ); SYS_ResetModule( PWM0_RST ); }
/** * @brief This function make USCI_SPI module be ready to transfer. * By default, the USCI_SPI transfer sequence is MSB first, the slave selection * signal is active low and the automatic slave select function is disabled. In * Slave mode, the u32BusClock must be NULL and the USCI_SPI clock * divider setting will be 0. * @param[in] uspi The pointer of the specified USCI_SPI module. * @param[in] u32MasterSlave Decide the USCI_SPI module is operating in master mode or in slave mode. Valid values are: * - \ref USPI_SLAVE * - \ref USPI_MASTER * @param[in] u32SPIMode Decide the transfer timing. Valid values are: * - \ref USPI_MODE_0 * - \ref USPI_MODE_1 * - \ref USPI_MODE_2 * - \ref USPI_MODE_3 * @param[in] u32DataWidth The data width of a USCI_SPI transaction. * @param[in] u32BusClock The expected frequency of USCI_SPI bus clock in Hz. * @return Actual frequency of USCI_SPI peripheral clock. */ uint32_t USPI_Open(USPI_T *uspi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock) { uint32_t u32ClkDiv = 0ul; uint32_t u32Pclk; uint32_t u32UspiClk = 0ul; if(uspi == (USPI_T *)USPI0) { u32Pclk = CLK_GetPCLK0Freq(); } else { u32Pclk = CLK_GetPCLK1Freq(); } if(u32BusClock != 0ul) { u32ClkDiv = (uint32_t) ((((((u32Pclk/2ul)*10ul)/(u32BusClock))+5ul)/10ul)-1ul); /* Compute proper divider for USCI_SPI clock */ } else {} /* Enable USCI_SPI protocol */ uspi->CTL &= ~USPI_CTL_FUNMODE_Msk; uspi->CTL = 1ul << USPI_CTL_FUNMODE_Pos; /* Data format configuration */ if(u32DataWidth == 16ul) { u32DataWidth = 0ul; } else {} uspi->LINECTL &= ~USPI_LINECTL_DWIDTH_Msk; uspi->LINECTL |= (u32DataWidth << USPI_LINECTL_DWIDTH_Pos); /* MSB data format */ uspi->LINECTL &= ~USPI_LINECTL_LSB_Msk; /* Set slave selection signal active low */ if(u32MasterSlave == USPI_MASTER) { uspi->LINECTL |= USPI_LINECTL_CTLOINV_Msk; } else { uspi->CTLIN0 |= USPI_CTLIN0_ININV_Msk; } /* Set operating mode and transfer timing */ uspi->PROTCTL &= ~(USPI_PROTCTL_SCLKMODE_Msk | USPI_PROTCTL_AUTOSS_Msk | USPI_PROTCTL_SLAVE_Msk); uspi->PROTCTL |= (u32MasterSlave | u32SPIMode); /* Set USCI_SPI bus clock */ uspi->BRGEN &= ~USPI_BRGEN_CLKDIV_Msk; uspi->BRGEN |= (u32ClkDiv << USPI_BRGEN_CLKDIV_Pos); uspi->PROTCTL |= USPI_PROTCTL_PROTEN_Msk; if(u32BusClock != 0ul) { u32UspiClk = (uint32_t)( u32Pclk / ((u32ClkDiv+1ul)<<1) ); } else {} return u32UspiClk; }
/** * @brief Get the actual frequency of USCI_SPI bus clock. Only available in Master mode. * @param[in] uspi The pointer of the specified USCI_SPI module. * @return Actual USCI_SPI bus clock frequency. */ uint32_t USPI_GetBusClock(USPI_T *uspi) { uint32_t u32BusClk; uint32_t u32ClkDiv; u32ClkDiv = (uspi->BRGEN & USPI_BRGEN_CLKDIV_Msk) >> USPI_BRGEN_CLKDIV_Pos; if(uspi == USPI0) { u32BusClk = (uint32_t)( CLK_GetPCLK0Freq() / ((u32ClkDiv+1ul)<<1) ); } else { u32BusClk = (uint32_t)( CLK_GetPCLK1Freq() / ((u32ClkDiv+1ul)<<1) ); } return u32BusClk; }
/** * @brief Set the USCI_SPI bus clock. Only available in Master mode. * @param[in] uspi The pointer of the specified USCI_SPI module. * @param[in] u32BusClock The expected frequency of USCI_SPI bus clock. * @return Actual frequency of USCI_SPI peripheral clock. */ uint32_t USPI_SetBusClock(USPI_T *uspi, uint32_t u32BusClock) { uint32_t u32ClkDiv; uint32_t u32Pclk; if(uspi == USPI0) { u32Pclk = CLK_GetPCLK0Freq(); } else { u32Pclk = CLK_GetPCLK1Freq(); } u32ClkDiv = (uint32_t) ((((((u32Pclk/2ul)*10ul)/(u32BusClock))+5ul)/10ul)-1ul); /* Compute proper divider for USCI_SPI clock */ /* Set USCI_SPI bus clock */ uspi->BRGEN &= ~USPI_BRGEN_CLKDIV_Msk; uspi->BRGEN |= (u32ClkDiv << USPI_BRGEN_CLKDIV_Pos); return ( u32Pclk / ((u32ClkDiv+1ul)<<1) ); }
/** * @brief Configure BPWM capture and get the nearest unit time. * @param[in] bpwm The pointer of the specified BPWM module * - BPWM0 : BPWM Group 0 * - BPWM1 : BPWM Group 1 * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 * @param[in] u32UnitTimeNsec The unit time of counter * @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used * @return The nearest unit time in nano second. * @details This function is used to Configure BPWM capture and get the nearest unit time. */ uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge) { uint32_t u32Src; uint32_t u32PWMClockSrc; uint32_t u32NearestUnitTimeNsec; uint16_t u16Prescale = 1U, u16CNR = 0xFFFFU; if(bpwm == BPWM0) { u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; } else { /* (bpwm == BPWM1) */ u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; } if(u32Src == 0U) { /* clock source is from PLL clock */ u32PWMClockSrc = CLK_GetPLLClockFreq(); } else { /* clock source is from PCLK */ SystemCoreClockUpdate(); if(bpwm == BPWM0) { u32PWMClockSrc = CLK_GetPCLK0Freq(); } else {/* (bpwm == BPWM1) */ u32PWMClockSrc = CLK_GetPCLK1Freq(); } } u32PWMClockSrc /= 1000UL; for(u16Prescale = 1U; u16Prescale <= 0x1000U; u16Prescale++) { uint32_t u32Exit = 0U; u32NearestUnitTimeNsec = (1000000UL * u16Prescale) / u32PWMClockSrc; if(u32NearestUnitTimeNsec < u32UnitTimeNsec) { if (u16Prescale == 0x1000U) { /* limit to the maximum unit time(nano second) */ u32Exit = 1U; } else { u32Exit = 0U; } if (!(1000000UL * (u16Prescale + 1UL) > (u32NearestUnitTimeNsec * u32PWMClockSrc))) { u32Exit = 1U; } else { u32Exit = 0U; } } else { u32Exit = 1U; } if (u32Exit == 1U) { break; } else {} } /* convert to real register value */ /* all channels share a prescaler */ u16Prescale -= 1U; BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u16Prescale); /* set BPWM to down count type(edge aligned) */ (bpwm)->CTL1 = (1UL); BPWM_SET_CNR(bpwm, u32ChannelNum, u16CNR); return (u32NearestUnitTimeNsec); }
/** * @brief This function Configure BPWM generator and get the nearest frequency in edge aligned auto-reload mode * @param[in] bpwm The pointer of the specified BPWM module * - BPWM0 : BPWM Group 0 * - BPWM1 : BPWM Group 1 * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 * @param[in] u32Frequency Target generator frequency * @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%... * @return Nearest frequency clock in nano second * @note Since all channels shares a prescaler. Call this API to configure BPWM frequency may affect * existing frequency of other channel. */ uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle) { uint32_t u32Src; uint32_t u32PWMClockSrc; uint32_t i; uint32_t u32Prescale = 1U, u32CNR = 0xFFFFU; if(bpwm == BPWM0) { u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; } else { /* (bpwm == BPWM1) */ u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; } if(u32Src == 0U) { /* clock source is from PLL clock */ u32PWMClockSrc = CLK_GetPLLClockFreq(); } else { /* clock source is from PCLK */ SystemCoreClockUpdate(); if(bpwm == BPWM0) { u32PWMClockSrc = CLK_GetPCLK0Freq(); } else { /* (bpwm == BPWM1) */ u32PWMClockSrc = CLK_GetPCLK1Freq(); } } for(u32Prescale = 1U; u32Prescale < 0xFFFU; u32Prescale++) { /* prescale could be 0~0xFFF */ i = (u32PWMClockSrc / u32Frequency) / u32Prescale; /* If target value is larger than CNR, need to use a larger prescaler */ if(i < (0x10000U)) { u32CNR = i; break; } } /* Store return value here 'cos we're gonna change u16Prescale & u16CNR to the real value to fill into register */ i = u32PWMClockSrc / (u32Prescale * u32CNR); /* convert to real register value */ /* all channels share a prescaler */ u32Prescale -= 1U; BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u32Prescale); /* set BPWM to down count type(edge aligned) */ (bpwm)->CTL1 = (1UL); u32CNR -= 1U; BPWM_SET_CNR(bpwm, u32ChannelNum, u32CNR); if(u32DutyCycle) { BPWM_SET_CMR(bpwm, u32ChannelNum, u32DutyCycle * (u32CNR + 1UL) / 100UL - 1UL); (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << ((u32ChannelNum * (2U)) + (uint32_t)BPWM_WGCTL0_PRDPCTLn_Pos)); (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * (2U) + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos)); } else { BPWM_SET_CMR(bpwm, u32ChannelNum, 0U); (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL0_ZPCTLn_Pos)); (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos)); } return(i); }