void pwmout_period_us(pwmout_t* obj, int us) { TimHandle.Instance = (TIM_TypeDef *)(obj->pwm); float dc = pwmout_read(obj); __HAL_TIM_DISABLE(&TimHandle); TimHandle.Init.Period = us - 1; TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 us tick TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) { error("Cannot initialize PWM"); } // Set duty cycle again pwmout_write(obj, dc); // Save for future use obj->period = us; __HAL_TIM_ENABLE(&TimHandle); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (PWMName)NC) error("PwmOut pin mapping failed"); obj->pwm = pwm; obj->MR = PWM_MATCH[pwm]; // ensure the power is on LPC_SC->PCONP |= 1 << 6; // ensure clock to /4 LPC_SC->PCLKSEL0 &= ~(0x3 << 12); // pclk = /4 LPC_PWM1->PR = 0; // no pre-scale // ensure single PWM mode LPC_PWM1->MCR = 1 << 1; // reset TC on match 0 // enable the specific PWM output LPC_PWM1->PCR |= 1 << (8 + pwm); pwm_clock_mhz = SystemCoreClock / 4000000; // 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 pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (uint32_t)NC) { error("PwmOut pin mapping failed"); } 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); SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n); tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(6); // (48)MHz / 64 = (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 pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (uint32_t)NC) error("PwmOut pin mapping failed"); obj->pwm = pwm; // Timer registers timer_mr tid = pwm_timer_map[pwm]; LPC_TMR_TypeDef *timer = Timers[tid.timer]; // Disable timer timer->TCR = 0; // Power the correspondent timer LPC_SYSCON->SYSAHBCLKCTRL |= 1 << (tid.timer + 7); /* Enable PWM function */ timer->PWMC = (1 << 3)|(1 << 2)|(1 << 1)|(1 << 0); /* Reset Functionality on MR3 controlling the PWM period */ timer->MCR = 1 << 10; pwm_clock_mhz = SystemCoreClock / 1000000; // 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 pwmout_period_us(pwmout_t* obj, int us) { TimHandle.Instance = (TIM_TypeDef *)(obj->pwm); float dc = pwmout_read(obj); __HAL_TIM_DISABLE(&TimHandle); // Update the SystemCoreClock variable SystemCoreClockUpdate(); TimHandle.Init.Period = us - 1; TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; HAL_TIM_PWM_Init(&TimHandle); // Set duty cycle again pwmout_write(obj, dc); // Save for future use obj->period = us; __HAL_TIM_ENABLE(&TimHandle); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (PWMName)NC) error("PwmOut pin mapping failed"); unsigned int port = (unsigned int)pin >> PORT_SHIFT; unsigned int ftm_n = (pwm >> TPM_SHIFT); unsigned int ch_n = (pwm & 0xFF); SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port); SIM->SCGC6 |= 1 << (SIM_SCGC6_FTM0_SHIFT + ftm_n); FTM_Type *ftm = (FTM_Type *)(FTM0_BASE + 0x1000 * ftm_n); ftm->MODE |= FTM_MODE_WPDIS_MASK; //write protection disabled ftm->CONF |= FTM_CONF_BDMMODE(3); ftm->SC = FTM_SC_CLKS(1) | FTM_SC_PS(6); // (48)MHz / 64 = (0.75)MHz ftm->CONTROLS[ch_n].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK); /* No Interrupts; High True pulses on Edge Aligned PWM */ ftm->PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; //loading updated values enabled //ftm->SYNCONF |= FTM_SYNCONF_SWRSTCNT_MASK; ftm->MODE |= FTM_MODE_INIT_MASK; obj->CnV = &ftm->CONTROLS[ch_n].CnV; obj->MOD = &ftm->MOD; obj->CNT = &ftm->CNT; obj->SYNC = &ftm->SYNC; // 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 pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); // power on CPGSTBCR3 &= ~(1<<0); obj->pwm = pwm; if (((uint32_t)PORT[obj->pwm] & 0x00000010) != 0) { obj->ch = 2; PWMPWPR_2_BYTE_L = 0x00; } else { obj->ch = 1; PWMPWPR_1_BYTE_L = 0x00; } // Wire pinout pinmap_pinout(pin, PinMap_PWM); // default to 491us: standard for servos, and fine for e.g. brightness control pwmout_write(obj, 0); if ((obj->ch == 2) && (init_period_ch2 == 0)) { pwmout_period_us(obj, 491); init_period_ch2 = 1; } if ((obj->ch == 1) && (init_period_ch1 == 0)) { pwmout_period_us(obj, 491); init_period_ch1 = 1; } }
void pwmout_period_us(pwmout_t* obj, int us) { float dc = pwmout_read(obj); obj->period = us; // Set duty cycle again pwmout_write(obj, dc); }
void pwmout_pulsewidth_us(pwmout_t *obj, int us) { float seconds = 0; float value = 0; seconds = (float)(us / 1000000.0f); value = (((seconds / obj->period) * 100.0f) / 100.0f); pwmout_write(obj, value); }
void AmebaServo::writeMicroseconds(int value) { if (value < min) value = min; if (value > max) value = max; currentWidth = 180 * (value - min) / (max - min); pwmout_write( (pwmout_t *)gpio_pin_struct[servoPin], value * 1.0 / 20000); }
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 defined(TARGET_KL43Z) if (mcgirc_frequency()) { SIM->SOPT2 |= SIM_SOPT2_TPMSRC(3); // Clock source: MCGIRCLK clkval = mcgirc_frequency() / 1000000.0f; } else { SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: IRC48M clkval = CPU_INT_IRC_CLK_HZ / 1000000.0f; } #else 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; } #endif 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 pwmout_free(pwmout_t *obj) { // Stops and clear count operation TMRB_SetRunState(obj->channel, TMRB_STOP); pwmout_write(obj,0); obj->pin = NC; obj->channel = NULL; obj->trailing_timing = 0; obj->leading_timing = 0; obj->divisor = 0; }
void pwmout_free(pwmout_t *obj) { // Stops and clear count operation TMRB_SetRunState(obj->channel, TMRB_STOP); pwmout_write(obj,0); obj->channel = NULL; obj->trailing_timing = 0; obj->leading_timing = 0; obj->divisor = 0; TMRB_SetIdleMode(TSB_TB0, ENABLE); }
void pwmout_pulsewidth_us(pwmout_t *obj, int us) { float seconds = 0; float value = 0; MBED_ASSERT(obj->channel != NULL); seconds = (float)(us / 1000000.0f); value = (((seconds / obj->period) * 100.0f) / 100.0f); pwmout_write(obj, value); }
void pwmout_pulsewidth_us(pwmout_t* obj, int us) { float value = 0; if (obj->ch == 2) { if (period_ch2 != 0) { value = (float)us / (float)period_ch2; } } else { if (period_ch1 != 0) { value = (float)us / (float)period_ch1; } } pwmout_write(obj, value); }
//int main_app(IN u16 argc, IN u8 *argv[]) void main(void) { int i; for (i=0; i<4; i++) { pwmout_init(&pwm_led[i], pwm_led_pin[i]); pwmout_period_us(&pwm_led[i], PWM_PERIOD); } while (1) { #if USE_FLOAT for (i=0; i<4; i++) { pwmout_write(&pwm_led[i], pwms[i]); pwms[i] += steps[i]; if (pwms[i] >= 1.0) { steps[i] = -PWM_STEP; pwms[i] = 1.0; } if (pwms[i] <= 0.0) { steps[i] = PWM_STEP; pwms[i] = 0.0; } } #else for (i=0; i<4; i++) { pwmout_pulsewidth_us(&pwm_led[i], pwms[i]); pwms[i] += steps[i]; if (pwms[i] >= PWM_PERIOD) { steps[i] = -PWM_STEP; pwms[i] = PWM_PERIOD; } if (pwms[i] <= 0) { steps[i] = PWM_STEP; pwms[i] = 0; } } #endif // wait_ms(20); // RtlMsleepOS(25); pwm_delay(); } }
void pwmout_period_us(pwmout_t* obj, int us) { TimHandle.Instance = (TIM_TypeDef *)(obj->pwm); float dc = pwmout_read(obj); __HAL_TIM_DISABLE(&TimHandle); SystemCoreClockUpdate(); /* To make it simple, we use to possible prescaler values which lead to: * pwm unit = 1us, period/pulse can be from 1us to 65535us * or * pwm unit = 500us, period/pulse can be from 500us to ~32.76sec * Be careful that all the channels of a PWM shares the same prescaler */ if (us > 0xFFFF) { obj->prescaler = 500; } else { obj->prescaler = 1; } TimHandle.Init.Prescaler = ((SystemCoreClock / 1000000) * obj->prescaler) - 1; if (TimHandle.Init.Prescaler > 0xFFFF) error("PWM: out of range prescaler"); TimHandle.Init.Period = (us - 1) / obj->prescaler; if (TimHandle.Init.Period > 0xFFFF) error("PWM: out of range period"); TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) { error("Cannot initialize PWM\n"); } // Save for future use obj->period = us; // Set duty cycle again pwmout_write(obj, dc); __HAL_TIM_ENABLE(&TimHandle); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel uint8_t pwmOutSuccess = 0; PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); if(PWM_taken[(uint8_t)pwm]){ for(uint8_t i = 1; !pwmOutSuccess && (i<NO_PWMS) ;i++){ if(!PWM_taken[i]){ pwm = (PWMName)i; PWM_taken[i] = 1; pwmOutSuccess = 1; } } } else{ pwmOutSuccess = 1; PWM_taken[(uint8_t)pwm] = 1; } if(!pwmOutSuccess){ error("PwmOut pin mapping failed. All available PWM channels are in use."); } obj->pwm = pwm; obj->pin = pin; gpiote_init(pin,(uint8_t)pwm); ppi_init((uint8_t)pwm); if(pwm == 0){ NRF_POWER->TASKS_CONSTLAT = 1; } timer_init((uint8_t)pwm); //default to 20ms: standard for servos, and fine for e.g. brightness control pwmout_period_ms(obj, 20); pwmout_write (obj, 0); }
void pwmout_period_us(pwmout_t* obj, int us) { TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; float dc = pwmout_read(obj); TIM_Cmd(tim, DISABLE); obj->period = us; TIM_TimeBaseStructure.TIM_Period = obj->period - 1; TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure); // Set duty cycle again pwmout_write(obj, dc); TIM_ARRPreloadConfig(tim, ENABLE); TIM_Cmd(tim, ENABLE); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (PWMName)NC) error("PwmOut pin mapping failed"); uint32_t clkdiv = 0; float clkval = SystemCoreClock / 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 ftm_n = (pwm >> TPM_SHIFT); unsigned int ch_n = (pwm & 0xFF); SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port); SIM->SCGC6 |= 1 << (SIM_SCGC6_FTM0_SHIFT + ftm_n); FTM_Type *ftm = (FTM_Type *)(FTM0_BASE + 0x1000 * ftm_n); ftm->CONF |= FTM_CONF_BDMMODE(3); ftm->SC = FTM_SC_CLKS(1) | FTM_SC_PS(clkdiv); // (clock)MHz / clkdiv ~= (0.75)MHz ftm->CONTROLS[ch_n].CnSC = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK); /* No Interrupts; High True pulses on Edge Aligned PWM */ obj->CnV = &ftm->CONTROLS[ch_n].CnV; obj->MOD = &ftm->MOD; obj->CNT = &ftm->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 pwmout_init(pwmout_t* obj, PinName pin) { PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (PWMName)NC) { error("PwmOut pin mapping failed"); } obj->pwm_name = pwm; uint32_t pwm_base_clock; clock_manager_get_frequency(kBusClock, &pwm_base_clock); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; while (clkval > 1) { clkdiv++; clkval /= 2.0f; if (clkdiv == 7) { break; } } pwm_clock_mhz = clkval; uint32_t channel = pwm & 0xF; uint32_t instance = pwm >> TPM_SHIFT; clock_manager_set_gate(kClockModuleFTM, instance, true); ftm_hal_set_tof_frequency(instance, 3); ftm_hal_set_clock_source(instance, kClock_source_FTM_SystemClk); ftm_hal_set_clock_ps(instance, (ftm_clock_ps_t)clkdiv); ftm_hal_set_counter_init_val(instance, 0); // default to 20ms: standard for servos, and fine for e.g. brightness control pwmout_period_ms(obj, 20); pwmout_write (obj, 0); ftm_config_t config = { .mode = kFtmEdgeAlignedPWM, .channel = channel, .edge_mode = {.ftm_pwm_edge_mode = kFtmHighTrue} }; ftm_hal_enable_pwm_mode(instance, &config); // Wire pinout pinmap_pinout(pin, PinMap_PWM); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (PWMName)NC) error("PwmOut pin mapping failed"); obj->channel = pwm; obj->pwm = LPC_PWM0; if (obj->channel > 6) { // PWM1 is used if pwm > 6 obj->channel -= 6; obj->pwm = LPC_PWM1; } obj->MR = (__IO uint32_t *)((uint32_t)obj->pwm + PWM_mr_offset[obj->channel]); // ensure the power is on if (obj->pwm == LPC_PWM0) { LPC_SC->PCONP |= 1 << 5; } else { LPC_SC->PCONP |= 1 << 6; } obj->pwm->PR = 0; // no pre-scale // ensure single PWM mode obj->pwm->MCR = 1 << 1; // reset TC on match 0 // enable the specific PWM output obj->pwm->PCR |= 1 << (8 + obj->channel); pwm_clock_mhz = PeripheralClock / 1000000; // 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 pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); if (pwm == (uint32_t)NC) error("PwmOut pin mapping failed"); obj->pwm = pwm; // Timer registers timer_mr tid = pwm_timer_map[pwm]; LPC_TMR_TypeDef *timer = Timers[tid.timer]; // Disable timer timer->TCR = 0; // Power the correspondent timer LPC_SYSCON->SYSAHBCLKCTRL |= 1 << (tid.timer + 7); /* Enable PWM function */ timer->PWMC = (1 << 3)|(1 << 2)|(1 << 1)|(1 << 0); /* Reset Functionality on MR3 controlling the PWM period */ timer->MCR = 1 << 10; if (timer == LPC_TMR16B0 || timer == LPC_TMR16B1) { /* Set 16-bit timer prescaler to avoid timer expire for default 20ms */ /* This can be also modified by user application, but the prescaler value */ /* might be trade-off to timer accuracy */ timer->PR = 30; } // 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 pwmout_free(pwmout_t* obj) { pwmout_write(obj, 0); }
// Set the PWM period, keeping the duty cycle the same. void pwmout_period_us(pwmout_t* obj, int us) { float dc = pwmout_read(obj); *obj->MOD = PWM_CLOCK_MHZ * us; pwmout_write(obj, dc); }
void pwmout_period_us(pwmout_t* obj, int us) { TimHandle.Instance = (TIM_TypeDef *)(obj->pwm); RCC_ClkInitTypeDef RCC_ClkInitStruct; uint32_t PclkFreq; uint32_t APBxCLKDivider; float dc = pwmout_read(obj); __HAL_TIM_DISABLE(&TimHandle); // Get clock configuration // Note: PclkFreq contains here the Latency (not used after) HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &PclkFreq); // Get the PCLK and APBCLK divider related to the timer switch (obj->pwm) { // APB1 clock case PWM_2: case PWM_3: case PWM_4: case PWM_5: case PWM_12: case PWM_13: case PWM_14: PclkFreq = HAL_RCC_GetPCLK1Freq(); APBxCLKDivider = RCC_ClkInitStruct.APB1CLKDivider; break; // APB2 clock case PWM_1: case PWM_8: case PWM_9: case PWM_10: case PWM_11: PclkFreq = HAL_RCC_GetPCLK2Freq(); APBxCLKDivider = RCC_ClkInitStruct.APB2CLKDivider; break; default: return; } /* To make it simple, we use to possible prescaler values which lead to: * pwm unit = 1us, period/pulse can be from 1us to 65535us * or * pwm unit = 500us, period/pulse can be from 500us to ~32.76sec * Be careful that all the channels of a PWM shares the same prescaler */ if (us > 0xFFFF) { obj->prescaler = 500; } else { obj->prescaler = 1; } // TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx if (APBxCLKDivider == RCC_HCLK_DIV1) TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq) / 1000000) * obj->prescaler) - 1; // 1 us tick else TimHandle.Init.Prescaler = (uint16_t)(((PclkFreq * 2) / 1000000) * obj->prescaler) - 1; // 1 us tick if (TimHandle.Init.Prescaler > 0xFFFF) error("PWM: out of range prescaler"); TimHandle.Init.Period = (us - 1) / obj->prescaler; if (TimHandle.Init.Period > 0xFFFF) error("PWM: out of range period"); TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) { error("Cannot initialize PWM\n"); } // Save for future use obj->period = us; // Set duty cycle again pwmout_write(obj, dc); __HAL_TIM_ENABLE(&TimHandle); }
void pwmout_pulsewidth_us(pwmout_t* obj, int us) { float value = (float)us / (float)obj->period; pwmout_write(obj, value); }
// Set the PWM period, keeping the duty cycle the same. void pwmout_period_us(pwmout_t* obj, int us) { float dc = pwmout_read(obj); *obj->MOD = (uint32_t)(pwm_clock * (float)us) - 1; pwmout_write(obj, dc); }
void pwmout_init(pwmout_t* obj, PinName pin) { // determine the channel PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); if (pwm >= MTU2_PWM_OFFSET) { /* PWM by MTU2 */ int tmp_pwm; // power on CPGSTBCR3 &= ~(CPG_STBCR3_BIT_MSTP33); obj->pwm = pwm; tmp_pwm = (int)(obj->pwm - MTU2_PWM_OFFSET); if (((uint32_t)MTU2_PORT[tmp_pwm] & 0x00000040) == 0x00000040) { obj->ch = 4; MTU2TOER |= 0x36; } else if (((uint32_t)MTU2_PORT[tmp_pwm] & 0x00000030) == 0x00000030) { obj->ch = 3; MTU2TOER |= 0x09; } else if (((uint32_t)MTU2_PORT[tmp_pwm] & 0x00000020) == 0x00000020) { obj->ch = 2; } else if (((uint32_t)MTU2_PORT[tmp_pwm] & 0x00000010) == 0x00000010) { obj->ch = 1; } else { obj->ch = 0; } // Wire pinout pinmap_pinout(pin, PinMap_PWM); int bitmask = 1 << (pin & 0xf); *PMSR(PINGROUP(pin)) = (bitmask << 16) | 0; // default duty 0.0f pwmout_write(obj, 0); if (init_mtu2_period_ch[obj->ch] == 0) { // default period 1ms pwmout_period_us(obj, 1000); init_mtu2_period_ch[obj->ch] = 1; } } else { /* PWM */ // power on CPGSTBCR3 &= ~(CPG_STBCR3_BIT_MSTP30); obj->pwm = pwm; if (((uint32_t)PORT[obj->pwm] & 0x00000010) == 0x00000010) { obj->ch = 2; PWMPWPR_2_BYTE_L = 0x00; } else { obj->ch = 1; PWMPWPR_1_BYTE_L = 0x00; } // Wire pinout pinmap_pinout(pin, PinMap_PWM); // default to 491us: standard for servos, and fine for e.g. brightness control pwmout_write(obj, 0); if ((obj->ch == 2) && (init_period_ch2 == 0)) { pwmout_period_us(obj, 491); init_period_ch2 = 1; } if ((obj->ch == 1) && (init_period_ch1 == 0)) { pwmout_period_us(obj, 491); init_period_ch1 = 1; } } }
void pwmout_init(pwmout_t* obj, PinName pin) { MBED_ASSERT(pin != (uint32_t)NC); int sct_n = get_available_sct(); if (sct_n == -1) { error("No available SCT"); } sct_used |= (1 << sct_n); obj->pwm = SCTs[sct_n]; obj->pwm_ch = sct_n; LPC_SCT0_Type* pwm = obj->pwm; // Enable the SCT clock LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << (obj->pwm_ch + 2)); // Clear peripheral reset the SCT: LPC_SYSCON->PRESETCTRL1 |= (1 << (obj->pwm_ch + 2)); LPC_SYSCON->PRESETCTRL1 &= ~(1 << (obj->pwm_ch + 2)); switch(obj->pwm_ch) { case 0: // SCT0_OUT0 LPC_SWM->PINASSIGN[7] &= ~0x0000FF00; LPC_SWM->PINASSIGN[7] |= (pin << 8); break; case 1: // SCT1_OUT0 LPC_SWM->PINASSIGN[8] &= ~0x000000FF; LPC_SWM->PINASSIGN[8] |= (pin); break; case 2: // SCT2_OUT0 LPC_SWM->PINASSIGN[8] &= ~0xFF000000; LPC_SWM->PINASSIGN[8] |= (pin << 24); break; case 3: // SCT3_OUT0 LPC_SWM->PINASSIGN[9] &= ~0x00FF0000; LPC_SWM->PINASSIGN[9] |= (pin << 16); break; default: break; } // Two 16-bit counters, autolimit pwm->CONFIG &= ~(0x1); pwm->CONFIG |= (1 << 17); // halt and clear the counter pwm->CTRL |= (1 << 2) | (1 << 3); // System Clock -> us_ticker (1)MHz pwm->CTRL &= ~(0x7F << 5); pwm->CTRL |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5); // Match reload register pwm->MATCHREL0 = 20000; // 20ms pwm->MATCHREL1 = (pwm->MATCHREL0 / 4); // 50% duty pwm->OUT0_SET = (1 << 0); // event 0 pwm->OUT0_CLR = (1 << 1); // event 1 pwm->EV0_CTRL = (1 << 12); pwm->EV0_STATE = 0xFFFFFFFF; pwm->EV1_CTRL = (1 << 12) | (1 << 0); pwm->EV1_STATE = 0xFFFFFFFF; // unhalt the counter: // - clearing bit 2 of the CTRL register pwm->CTRL &= ~(1 << 2); // default to 20ms: standard for servos, and fine for e.g. brightness control pwmout_period_ms(obj, 20); pwmout_write (obj, 0); }