示例#1
0
int output_init(void) {
	setup_ctrl_gpio(M0INa);
	setup_ctrl_gpio(M0INb);
	setup_ctrl_gpio(M0ENa);
	setup_ctrl_gpio(M0ENb);
	setup_ctrl_gpio(M1INa);
	setup_ctrl_gpio(M1INb);
	setup_ctrl_gpio(M1ENa);
	setup_ctrl_gpio(M1ENb);

	rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN);
	setup_pwm_pin(M0PWM);
	setup_pwm_pin(M1PWM);

	timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
	timer_set_period(TIM2, 2000);
	timer_set_prescaler(TIM2, 1);

	timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_PWM1);
	timer_set_oc_mode(TIM2, TIM_OC2, TIM_OCM_PWM1);
	timer_enable_oc_preload(TIM2, TIM_OC1);
	timer_enable_oc_preload(TIM2, TIM_OC2);

	timer_set_oc_polarity_high(TIM2, TIM_OC1);
	timer_set_oc_polarity_high(TIM2, TIM_OC2);
	timer_enable_oc_output(TIM2, TIM_OC1);
	timer_enable_oc_output(TIM2, TIM_OC2);

	output_speed(0, 0);
	output_speed(1, 0);

	timer_enable_preload(TIM2);
	timer_enable_counter(TIM2);
	return 0;
}
示例#2
0
static void pwm_setup(void) {
	/* Configure GPIOs: OUT=PA7 */
	gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
	    GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM3_CH2 );

	timer_reset(TIM3);

	timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

	timer_disable_oc_output(TIM3, TIM_OC2);
	timer_set_oc_mode(TIM3, TIM_OC2, TIM_OCM_PWM1);
	timer_disable_oc_clear(TIM3, TIM_OC2);
	timer_set_oc_value(TIM3, TIM_OC2, 0);
	timer_enable_oc_preload(TIM3, TIM_OC2);
	timer_set_oc_polarity_high(TIM3, TIM_OC2);
	timer_enable_oc_output(TIM3, TIM_OC2);

	timer_set_dma_on_update_event(TIM3);
	timer_enable_irq(TIM3, TIM_DIER_UDE); // in fact, enable DMA on update

	timer_enable_preload(TIM3);
	timer_continuous_mode(TIM3);
	timer_set_period(TIM3, WSP);

	timer_enable_counter(TIM3);
}
示例#3
0
void BeepInit(void)
{
    rcc_peripheral_enable_clock(&RCC_APB1ENR, BEEP_RCC_APB1ENR_TIMEN);
    gpio_set_mode(BEEP_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, BEEP_PIN);

    timer_set_mode(BEEP_TIM, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    
    /* Period */
    timer_set_period(BEEP_TIM, 65535);

    /* Prescaler */
    timer_set_prescaler(BEEP_TIM, 5);
    timer_generate_event(BEEP_TIM, TIM_EGR_UG);

    /* ---- */
    /* Output compare 1 mode and preload */
    timer_set_oc_mode(BEEP_TIM, BEEP_TIM_OC, TIM_OCM_PWM1);
    timer_enable_oc_preload(BEEP_TIM, BEEP_TIM_OC);

    /* Polarity and state */
    timer_set_oc_polarity_low(BEEP_TIM, BEEP_TIM_OC);
    timer_enable_oc_output(BEEP_TIM, BEEP_TIM_OC);

    /* Capture compare value */
    timer_set_oc_value(BEEP_TIM, BEEP_TIM_OC, 0x8000);
    /* ---- */
    /* ARR reload enable */
    timer_enable_preload(BEEP_TIM);
}
示例#4
0
void PulseWidth::begin(uint16 period, bool microsecond_precision)
{
    if(timer_peripheral == TIM2)
        rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN);
    else if(timer_peripheral == TIM3)
        rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN);
    else
        return;

    timer_reset(timer_peripheral);

    /* Set the timers global mode to:
     * - use no divider
     * - alignment edge
     * - count direction up
     */
    timer_set_mode(timer_peripheral,
                   TIM_CR1_CKD_CK_INT,
                   TIM_CR1_CMS_EDGE,
                   TIM_CR1_DIR_UP);

	if(microsecond_precision)
    	timer_set_prescaler(timer_peripheral, 64);
    else
    	timer_set_prescaler(timer_peripheral, 64'000);
    
    timer_set_repetition_counter(timer_peripheral, 0);
    timer_enable_preload(timer_peripheral);
    timer_continuous_mode(timer_peripheral);
    timer_set_period(timer_peripheral, period);
}
示例#5
0
/** Set Timer configuration
 */
static inline void set_servo_timer(uint32_t timer, uint32_t period, uint8_t channels_mask) {
  timer_reset(timer);

  /* Timer global mode:
   * - No divider.
   * - Alignement edge.
   * - Direction up.
   */
  timer_set_mode(timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

  timer_set_prescaler(timer, (PCLK / ONE_MHZ_CLK) - 1); // 1uS

  timer_disable_preload(timer);

  timer_continuous_mode(timer);

  timer_set_period(timer, (ONE_MHZ_CLK / period) - 1);

  /* Disable outputs and configure channel if needed. */
  if (bit_is_set(channels_mask, 0)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC1);
  }
  if (bit_is_set(channels_mask, 1)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC2);
  }
  if (bit_is_set(channels_mask, 2)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC3);
  }
  if (bit_is_set(channels_mask, 3)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC4);
  }

  /*
   * Set initial output compare values.
   * Note: Maybe we should preload the compare registers with some sensible
   * values before we enable the timer?
   */
  //timer_set_oc_value(timer, TIM_OC1, 1000);
  //timer_set_oc_value(timer, TIM_OC2, 1000);
  //timer_set_oc_value(timer, TIM_OC3, 1000);
  //timer_set_oc_value(timer, TIM_OC4, 1000);

  /* -- Enable timer -- */
  /*
   * ARR reload enable.
   * Note: In our case it does not matter much if we do preload or not. As it
   * is unlikely we will want to change the frequency of the timer during
   * runtime anyways.
   */
  timer_enable_preload(timer);

  /* Counter enable. */
  timer_enable_counter(timer);
}
示例#6
0
void sound_set_frequency(uint32_t freq) {
    uint32_t prescaler, period;

    if (freq <= 200) {
        // switch off pwm
        timer_disable_oc_output(TIM1, TIM_OC1);
        // return;
    }

    // reset TIMx peripheral
    timer_reset(TIM1);

    // roughly factor into 16-bit
    period    = (rcc_timer_frequency / 1) / freq;
    prescaler = (period / 65536) + 1;
    period    = (period / prescaler);

    // Set the timers global mode to:
    // - use no divider
    // - alignment edge
    // - count direction up
    timer_set_mode(TIM1,
                   TIM_CR1_CKD_CK_INT,
                   TIM_CR1_CMS_EDGE,
                   TIM_CR1_DIR_UP);

    timer_set_prescaler(TIM1, prescaler - 1);
    timer_set_repetition_counter(TIM1, 0);

    timer_enable_preload(TIM1);
    timer_continuous_mode(TIM1);
    timer_set_period(TIM1, period - 1);

    // start with disabled pwm output
    timer_disable_oc_output(TIM1, TIM_OC1);

    // NOTE: on advanced timers as TIM1 we have
    //       to break the main output, otherwise
    //       no pwm output signal will be present on pin
    timer_enable_break_main_output(TIM1);

    // configure output mode
    timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1);
    // set period for 50/50 duty cycle
    timer_set_oc_value(TIM1, TIM_OC1, period / 2);
    // enable pwm output
    timer_enable_oc_output(TIM1, TIM_OC1);

    // start timer
    timer_enable_counter(TIM1);
}
示例#7
0
/*
                                --- FTFM (with edits) ---
Bullet points are the steps needed.

Pulse width modulation mode allows you to generate a signal with a frequency determined
by the value of the TIMx_ARR register (the period) and a duty cycle determined by the value of the
TIMx_CCRx register (the output compare value).
  -- Set TIMx_ARR to desired frequency
  -- Set TIMx_CCRx to desired duty cycle

The PWM mode can be selected independently on each channel (one PWM per OCx
output) by writing 110 (PWM mode 1) or ‘111 (PWM mode 2) in the OCxM bits in the
TIMx_CCMRx register.
  -- Write PWM Mode 1 or PWM Mode 2 to OCxM bits in TIMx_CCMRx register

You must enable the corresponding preload register by setting the
OCxPE bit in the TIMx_CCMRx register, and eventually the auto-reload preload register by
setting the ARPE bit in the TIMx_CR1 register.
  -- Set corresponding OCxPE bit in TIMx_CCMRx register
  -- Set ARPE bit in TIMx_CR1

As the preload registers are transferred to the shadow registers only when an update event
occurs, before starting the counter, you have to initialize all the registers by setting the UG
bit in the TIMx_EGR register.
  -- set UG bit in TIMx_EGR register

OCx polarity is software programmable using the CCxP bit in the TIMx_CCER register. It
can be programmed as active high or active low. OCx output is enabled by the CCxE bit in
the TIMx_CCER register. Refer to the TIMx_CCERx register description for more details.
  -- set desired polarity in TIMx_CCER
  -- set CCxE bit in TIMx_CCER  (enable output)
*/
static void
pwm_init(uint32_t timer,
         uint8_t channel,
         uint32_t period) {
  // Convert channel number to internal rep
  enum tim_oc_id chan;
  switch (channel) {
    case 1:   chan = TIM_OC1; break;
    case 2:   chan = TIM_OC2; break;
    case 3:   chan = TIM_OC3; break;
    case 4:   chan = TIM_OC4; break;
    default: assert(false); chan = -1; break;
  }

  // Timer Base Configuration
  // timer_reset(timer);
  timer_set_mode(timer, TIM_CR1_CKD_CK_INT, // clock division
                        TIM_CR1_CMS_EDGE,   // Center-aligned mode selection
                        TIM_CR1_DIR_UP);    // TIMx_CR1 DIR: Direction
  timer_continuous_mode(timer);             // Disables TIM_CR1_OPM (One pulse mode)
  timer_set_period(timer, period);                    // Sets TIMx_ARR
  timer_set_prescaler(timer, 1);               // Adjusts speed of timer
  timer_set_clock_division(timer, 0);            // Adjusts speed of timer
  timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);   // Master Mode Selection
  timer_enable_preload(timer);                        // Set ARPE bit in TIMx_CR1

  // Channel-specific settings
  timer_set_oc_value(timer, chan, 0);             // sets TIMx_CCRx
  timer_set_oc_mode(timer, chan, TIM_OCM_PWM1);   // Sets PWM Mode 1
  timer_enable_oc_preload(timer, chan);           // Sets OCxPE in TIMx_CCMRx
  timer_set_oc_polarity_high(timer, chan);        // set desired polarity in TIMx_CCER
  timer_enable_oc_output(timer, chan);             // set CCxE bit in TIMx_CCER  (enable output)

  // Initialize all counters in the register
  switch (timer) {
    case TIM1:  TIM1_EGR |= TIM_EGR_UG; break;
    case TIM2:  TIM2_EGR |= TIM_EGR_UG; break;
    case TIM3:  TIM3_EGR |= TIM_EGR_UG; break;
    case TIM4:  TIM4_EGR |= TIM_EGR_UG; break;
    case TIM5:  TIM5_EGR |= TIM_EGR_UG; break;
    case TIM6:  TIM6_EGR |= TIM_EGR_UG; break;
    case TIM7:  TIM7_EGR |= TIM_EGR_UG; break;
    case TIM8:  TIM8_EGR |= TIM_EGR_UG; break;
    default: assert(false); break;
    }
}
示例#8
0
文件: led.c 项目: hyrant/fulcrum
void LED_init(void)
{
    rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN);
    
    set_led(false);
     
    timer_reset(TIM2);
    timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_prescaler(TIM2, 256);
    timer_enable_preload(TIM2);
    timer_one_shot_mode(TIM2);
    timer_set_period(TIM2, (uint16_t)((rcc_ppre1_frequency/256) / 20));
    timer_enable_irq(TIM2, TIM_DIER_UIE);
    timer_clear_flag(TIM2, TIM_SR_UIF);
    
    nvic_enable_irq(NVIC_TIM2_IRQ);
    nvic_set_priority(NVIC_TIM2_IRQ, 128);
}
示例#9
0
void BACKLIGHT_Init()
{
    rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
    //Turn off backlight
    gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
                  GPIO_CNF_INPUT_FLOAT, GPIO1);

    //Configure Backlight PWM
    rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN);
    timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
                   TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_period(TIM3, 0x2CF);
    timer_set_prescaler(TIM3, 0);
    timer_generate_event(TIM3, TIM_EGR_UG);
    //timer_set_repetition_counter(TIM3, 0);
    timer_set_oc_mode(TIM3, TIM_OC4, TIM_OCM_PWM1);
    timer_enable_oc_preload(TIM3, TIM_OC4);

    timer_set_oc_polarity_high(TIM3, TIM_OC4);
    timer_enable_oc_output(TIM3, TIM_OC4);

    timer_enable_preload(TIM3);
}
示例#10
0
void PID_tim_init(void)
{
	/* Enable TIM1 clock. and Port E clock (for outputs) */
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_TIM1EN);
	rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPEEN);

	//Set TIM1 channel (and complementary) output to alternate function push-pull'.
	//f4 TIM1=> GIO9: CH1, GPIO11: CH2, GPIO13: CH3
	//f4 TIM1=> GIO8: CH1N, GPIO10: CH2N, GPIO12: CH3N
	gpio_mode_setup(GPIOE, GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO9 | GPIO11 | GPIO13);
	gpio_set_af(GPIOE, GPIO_AF1, GPIO9 | GPIO11 | GPIO13);
	gpio_mode_setup(GPIOE, GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO8 | GPIO10 | GPIO12);
	gpio_set_af(GPIOE, GPIO_AF1, GPIO8 | GPIO10 | GPIO12);

	/* Enable TIM1 commutation interrupt. */
	//nvic_enable_irq(NVIC_TIM1_TRG_COM_TIM11_IRQ);	//f4

	/* Reset TIM1 peripheral. */
	timer_reset(TIM1);

	/* Timer global mode:
	 * - No divider
	 * - Alignment edge
	 * - Direction up
	 */
	timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, //For dead time and filter sampling, not important for now.
		       TIM_CR1_CMS_CENTER_3,	//TIM_CR1_CMS_EDGE
						//TIM_CR1_CMS_CENTER_1
						//TIM_CR1_CMS_CENTER_2
						//TIM_CR1_CMS_CENTER_3 la frequencia del pwm se divide a la mitad. (frecuencia senoidal)
			 TIM_CR1_DIR_UP);

	timer_set_prescaler(TIM1, PRESCALE); //1 = disabled (max speed)
	timer_set_repetition_counter(TIM1, 0); //disabled
	timer_enable_preload(TIM1);
	timer_continuous_mode(TIM1);

	/* Period (32kHz). */
	timer_set_period(TIM1, PWM_PERIOD_ARR); //ARR (value compared against main counter to reload counter aka: period of counter)

	/* Configure break and deadtime. */
	//timer_set_deadtime(TIM1, deadtime_percentage*pwm_period_ARR);
	timer_set_enabled_off_state_in_idle_mode(TIM1);
	timer_set_enabled_off_state_in_run_mode(TIM1);
	timer_disable_break(TIM1);
	timer_set_break_polarity_high(TIM1);
	timer_disable_break_automatic_output(TIM1);
	timer_set_break_lock(TIM1, TIM_BDTR_LOCK_OFF);

	/* Disable outputs. */
	timer_disable_oc_output(TIM1, TIM_OC1);
	timer_disable_oc_output(TIM1, TIM_OC1N);
	timer_disable_oc_output(TIM1, TIM_OC2);
	timer_disable_oc_output(TIM1, TIM_OC2N);
	timer_disable_oc_output(TIM1, TIM_OC3);
	timer_disable_oc_output(TIM1, TIM_OC3N);

	/* -- OC1 and OC1N configuration -- */
	/* Configure global mode of line 1. */
	timer_enable_oc_preload(TIM1, TIM_OC1);
	timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1);
	/* Configure OC1. */
	timer_set_oc_polarity_high(TIM1, TIM_OC1);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC1); //When idle (braked) put 0 on output
	/* Configure OC1N. */
	timer_set_oc_polarity_high(TIM1, TIM_OC1N);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC1N);
	/* Set the capture compare value for OC1. */
	timer_set_oc_value(TIM1, TIM_OC1, INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR);

	/* -- OC2 and OC2N configuration -- */
	/* Configure global mode of line 2. */
	timer_enable_oc_preload(TIM1, TIM_OC2);
	timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1);
	/* Configure OC2. */
	timer_set_oc_polarity_high(TIM1, TIM_OC2);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC2);
	/* Configure OC2N. */
	timer_set_oc_polarity_high(TIM1, TIM_OC2N);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC2N);
	/* Set the capture compare value for OC2. */
	timer_set_oc_value(TIM1, TIM_OC2, INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR);

	/* -- OC3 and OC3N configuration -- */
	/* Configure global mode of line 3. */
	timer_enable_oc_preload(TIM1, TIM_OC3);
	timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1);
	/* Configure OC3. */
	timer_set_oc_polarity_high(TIM1, TIM_OC3);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC3);
	/* Configure OC3N. */
	timer_set_oc_polarity_high(TIM1, TIM_OC3N);
	timer_set_oc_idle_state_unset(TIM1, TIM_OC3N);
	/* Set the capture compare value for OC3. */
	timer_set_oc_value(TIM1, TIM_OC3, INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR);//100);

	/* Reenable outputs. */
	timer_enable_oc_output(TIM1, TIM_OC1);
	timer_enable_oc_output(TIM1, TIM_OC1N);
	timer_enable_oc_output(TIM1, TIM_OC2);
	timer_enable_oc_output(TIM1, TIM_OC2N);
	timer_enable_oc_output(TIM1, TIM_OC3);
	timer_enable_oc_output(TIM1, TIM_OC3N);

	/* ---- */

	/* ARR reload enable. */
	timer_enable_preload(TIM1);

	/*
	 * Enable preload of complementary channel configurations and
	 * update on COM event.
	 */
	//timer_enable_preload_complementry_enable_bits(TIM1);
	timer_disable_preload_complementry_enable_bits(TIM1);

	/* Enable outputs in the break subsystem. */
	timer_enable_break_main_output(TIM1);

	/* Generate update event to reload all registers before starting*/
	timer_generate_event(TIM1, TIM_EGR_UG);

	/* Counter enable. */
	timer_enable_counter(TIM1);

	/* Enable commutation interrupt. */
	//timer_enable_irq(TIM1, TIM_DIER_COMIE);

	/*********/
	/*Capture compare interrupt*/

	//enable capture compare interrupt
	timer_enable_update_event(TIM1);

	/* Enable commutation interrupt. */
	//timer_enable_irq(TIM1, TIM_DIER_CC1IE);	//Capture/compare 1 interrupt enable
	/* Enable commutation interrupt. */
	//timer_enable_irq(TIM1, TIM_DIER_CC1IE);
	timer_enable_irq(TIM1, TIM_DIER_UIE);
	nvic_enable_irq(NVIC_TIM1_UP_TIM10_IRQ);
}
示例#11
0
void actuators_pwm_arch_init(void) {

  /*-----------------------------------
   * Configure timer peripheral clocks
   *-----------------------------------*/
  /* TIM3, TIM4 and TIM5 clock enable */
  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN);
#if REMAP_SERVOS_5AND6
  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM5EN);
#else
  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
#endif
#if USE_SERVOS_7AND8
  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
#endif

  /*----------------
   * Configure GPIO
   *----------------*/
  /* GPIO A,B and C clock enable */
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
			  RCC_APB2ENR_IOPBEN |
			  RCC_APB2ENR_IOPCEN |
			  RCC_APB2ENR_AFIOEN);

  /* TIM3 GPIO for PWM1..4 */
  AFIO_MAPR |= AFIO_MAPR_TIM3_REMAP_FULL_REMAP;
  gpio_set_mode(GPIO_BANK_TIM3_FR,
	  GPIO_MODE_OUTPUT_50_MHZ,
	  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
	  GPIO_TIM3_FR_CH1 |
	  GPIO_TIM3_FR_CH2 |
	  GPIO_TIM3_FR_CH3 |
	  GPIO_TIM3_FR_CH4);

  /* TIM4 GPIO for PWM7..8 */
#if USE_SERVOS_7AND8
  gpio_set_mode(GPIO_BANK_TIM4,
	  GPIO_MODE_OUTPUT_50_MHZ,
	  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
	  GPIO_TIM4_CH1 |
	  GPIO_TIM4_CH2);
#endif

  /* TIM4/5 GPIO for PWM6..7 */
#if REMAP_SERVOS_5AND6
  gpio_set_mode(GPIO_BANK_TIM5,
	  GPIO_MODE_OUTPUT_50_MHZ,
	  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
	  GPIO_TIM5_CH1 |
	  GPIO_TIM5_CH2);
#else
  gpio_set_mode(GPIO_BANK_TIM4,
	  GPIO_MODE_OUTPUT_50_MHZ,
	  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
	  GPIO_TIM4_CH3 |
	  GPIO_TIM4_CH4);
#endif

  /*---------------
   * Timer 3 setup
   *---------------*/
  timer_reset(TIM3);

  /* Timer global mode:
   * - No divider.
   * - Alignement edge.
   * - Direction up.
   */
  timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
	  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

  timer_set_prescaler(TIM3, (PCLK / ONE_MHZ_CLK) - 1); // 1uS

  timer_disable_preload(TIM3);

  timer_continuous_mode(TIM3);

  timer_set_period(TIM3, (ONE_MHZ_CLK / SERVO_HZ) - 1);

  /* Disable outputs. */
  timer_disable_oc_output(TIM3, TIM_OC1);
  timer_disable_oc_output(TIM3, TIM_OC2);
  timer_disable_oc_output(TIM3, TIM_OC3);
  timer_disable_oc_output(TIM3, TIM_OC4);

  /* -- Channel configuration -- */
  actuators_pwm_arch_channel_init(TIM3, TIM_OC1);
  actuators_pwm_arch_channel_init(TIM3, TIM_OC2);
  actuators_pwm_arch_channel_init(TIM3, TIM_OC3);
  actuators_pwm_arch_channel_init(TIM3, TIM_OC4);

  /*
   * Set initial output compare values.
   * Note: Maybe we should preload the compare registers with some sensible
   * values before we enable the timer?
   */
  //timer_set_oc_value(TIM3, TIM_OC1, 1000);
  //timer_set_oc_value(TIM3, TIM_OC2, 1000);
  //timer_set_oc_value(TIM3, TIM_OC3, 1000);
  //timer_set_oc_value(TIM3, TIM_OC4, 1000);

  /* -- Enable timer -- */
  /*
   * ARR reload enable.
   * Note: In our case it does not matter much if we do preload or not. As it
   * is unlikely we will want to change the frequency of the timer during
   * runtime anyways.
   */
  timer_enable_preload(TIM3);

  /* Counter enable. */
  timer_enable_counter(TIM3);

#if (!REMAP_SERVOS_5AND6 || USE_SERVOS_7AND8)
#if !REMAP_SERVOS_5AND6
#pragma message "Not remapping servos 5 and 6 using PB8 and PB9 -> TIM4"
#endif
#if USE_SERVOS_7AND8
#pragma message "Enabeling sevros 7 and 8 on PB6, PB7 -> TIM4"
#endif
  /*---------------
   * Timer 4 setup
   *---------------*/
  timer_reset(TIM4);

  /* Timer global mode:
   * - No divider.
   * - Alignement edge.
   * - Direction up.
   */
  timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT,
	  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

  timer_set_prescaler(TIM4, (PCLK / ONE_MHZ_CLK) - 1); // 1uS

  timer_disable_preload(TIM4);

  timer_continuous_mode(TIM4);

#ifdef SERVO_HZ_SECONDARY
  timer_set_period(TIM4, (ONE_MHZ_CLK / SERVO_HZ_SECONDARY) - 1);
#else
  timer_set_period(TIM4, (ONE_MHZ_CLK / SERVO_HZ) - 1);
#endif

  /* Disable outputs. */
#if USE_SERVOS_7AND8
  timer_disable_oc_output(TIM4, TIM_OC1);
  timer_disable_oc_output(TIM4, TIM_OC2);
#endif
#if !REMAP_SERVOS_5AND6
  timer_disable_oc_output(TIM4, TIM_OC3);
  timer_disable_oc_output(TIM4, TIM_OC4);
#endif

  /* -- Channel configuration -- */
#if USE_SERVOS_7AND8
  actuators_pwm_arch_channel_init(TIM4, TIM_OC1);
  actuators_pwm_arch_channel_init(TIM4, TIM_OC2);
#endif
#if !REMAP_SERVOS_5AND6
  actuators_pwm_arch_channel_init(TIM4, TIM_OC3);
  actuators_pwm_arch_channel_init(TIM4, TIM_OC4);
#endif

  /*
   * Set initial output compare values.
   * Note: Maybe we should preload the compare registers with some sensible
   * values before we enable the timer?
   */
#if USE_SERVOS_7AND8
  //timer_set_oc_value(TIM4, TIM_OC1, 1000);
  //timer_set_oc_value(TIM4, TIM_OC2, 1000);
#endif
#if ! REMAP_SERVOS_5AND6
  //timer_set_oc_value(TIM4, TIM_OC3, 1000);
  //timer_set_oc_value(TIM4, TIM_OC4, 1000);
#endif

  /* -- Enable timer -- */
  /*
   * ARR reload enable.
   * Note: In our case it does not matter much if we do preload or not. As it
   * is unlikely we will want to change the frequency of the timer during
   * runtime anyways.
   */
  timer_enable_preload(TIM4);

  /* Counter enable. */
  timer_enable_counter(TIM4);

#endif

#if REMAP_SERVOS_5AND6
#pragma message "Remapping servo outputs 5 and 6 to PA0,PA1 -> TIM5"
  /*---------------
   * Timer 5 setup
   *---------------*/
  timer_reset(TIM5);

  /* Timer global mode:
   * - No divider.
   * - Alignement edge.
   * - Direction up.
   */
  timer_set_mode(TIM5, TIM_CR1_CKD_CK_INT,
	  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

  timer_set_prescaler(TIM5, (PCLK / ONE_MHZ_CLK) - 1); // 1uS

  timer_disable_preload(TIM5);

  timer_continuous_mode(TIM5);

#ifdef SERVO_HZ_SECONDARY
  timer_set_period(TIM5, (ONE_MHZ_CLK / SERVO_HZ_SECONDARY) - 1);
#else
  timer_set_period(TIM5, (ONE_MHZ_CLK / SERVO_HZ) - 1);
#endif

  /* Disable outputs. */
  timer_disable_oc_output(TIM5, TIM_OC1);
  timer_disable_oc_output(TIM5, TIM_OC2);

  /* -- Channel configuration -- */
  actuators_pwm_arch_channel_init(TIM5, TIM_OC1);
  actuators_pwm_arch_channel_init(TIM5, TIM_OC2);

  /*
   * Set the capture compare value for OC1.
   * Note: Maybe we should preload the compare registers with some sensible
   * values before we enable the timer?
   */
  //timer_set_oc_value(TIM5, TIM_OC1, 1000);
  //timer_set_oc_value(TIM5, TIM_OC2, 1000);

  /* -- Enable timer -- */
  /*
   * ARR reload enable.
   * Note: In our case it does not matter much if we do preload or not. As it
   * is unlikely we will want to change the frequency of the timer during
   * runtime anyways.
   */
  timer_enable_preload(TIM5);

  /* Counter enable. */
  timer_enable_counter(TIM5);

#endif

}
/** Set Timer configuration
 * @param[in] timer Timer register address base
 * @param[in] period period in us
 * @param[in] channels_mask output compare channels to enable
 */
void set_servo_timer(uint32_t timer, uint32_t period, uint8_t channels_mask) {
  // WARNING, this reset is only implemented for TIM1-8 in libopencm3!!
  timer_reset(timer);

  /* Timer global mode:
   * - No divider.
   * - Alignement edge.
   * - Direction up.
   */
  if ((timer == TIM9) || (timer == TIM12))
    //There are no EDGE and DIR settings in TIM9 and TIM12
    timer_set_mode(timer, TIM_CR1_CKD_CK_INT, 0, 0);
  else
    timer_set_mode(timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);


  // By default the PWM_BASE_FREQ is set to 1MHz thus the timer tick period is 1uS
  uint32_t timer_clk = timer_get_frequency(timer);
  timer_set_prescaler(timer, (timer_clk / PWM_BASE_FREQ) -1);

  timer_disable_preload(timer);

  timer_continuous_mode(timer);

  timer_set_period(timer, (PWM_BASE_FREQ / period) - 1);

  /* Disable outputs and configure channel if needed. */
  if (bit_is_set(channels_mask, 0)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC1);
  }
  if (bit_is_set(channels_mask, 1)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC2);
  }
  if (bit_is_set(channels_mask, 2)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC3);
  }
  if (bit_is_set(channels_mask, 3)) {
    actuators_pwm_arch_channel_init(timer, TIM_OC4);
  }

  /*
   * Set initial output compare values.
   * Note: Maybe we should preload the compare registers with some sensible
   * values before we enable the timer?
   */
  //timer_set_oc_value(timer, TIM_OC1, 1000);
  //timer_set_oc_value(timer, TIM_OC2, 1000);
  //timer_set_oc_value(timer, TIM_OC3, 1000);
  //timer_set_oc_value(timer, TIM_OC4, 1000);

  /* -- Enable timer -- */
  /*
   * ARR reload enable.
   * Note: In our case it does not matter much if we do preload or not. As it
   * is unlikely we will want to change the frequency of the timer during
   * runtime anyways.
   */
  timer_enable_preload(timer);

  /* Counter enable. */
  timer_enable_counter(timer);

}
示例#13
0
void hardware_setup(void)
{
/* Set the clock to 72MHz from the 8MHz external crystal */

	rcc_clock_setup_in_hse_8mhz_out_72mhz();

/* Enable GPIOA, GPIOB and GPIOC clocks.
   APB2 (High Speed Advanced Peripheral Bus) peripheral clock enable register (RCC_APB2ENR)
   Set RCC_APB2ENR_IOPBEN for port B, RCC_APB2ENR_IOPAEN for port A and RCC_APB2ENR_IOPAEN
   for Alternate Function clock */
    rcc_periph_clock_enable(RCC_GPIOA);
	rcc_periph_clock_enable(RCC_GPIOB);
	rcc_periph_clock_enable(RCC_GPIOC);
	rcc_periph_clock_enable(RCC_AFIO);

/* Set ports PA8 (TIM1_CH1), PA9 (TIM1_CH2), PB13 (TIM1_CH1N), PB14 (TIM1_CH2N)
for PWM, to 'alternate function output push-pull'. */
	gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
		      GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8 | GPIO9);
	gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
		      GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO13 | GPIO14);

/* ------------------ Timer 1 PWM */
/* Enable TIM1 clock. */
	rcc_periph_clock_enable(RCC_TIM1);

/* Reset TIM1 peripheral. */
	timer_reset(TIM1);

/* Set Timer global mode:
 * - No division
 * - Alignment centre mode 1 (up/down counting, interrupt on downcount only)
 * - Direction up (when centre mode is set it is read only, changes by hardware)
 */
	timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_CENTER_1, TIM_CR1_DIR_UP);

/* Set Timer output compare mode:
 * - Channel 1
 * - PWM mode 2 (output low when CNT < CCR1, high otherwise)
 */
	timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM2);
	timer_enable_oc_output(TIM1, TIM_OC1);
	timer_enable_oc_output(TIM1, TIM_OC1N);
	timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM2);
	timer_enable_oc_output(TIM1, TIM_OC2);
	timer_enable_oc_output(TIM1, TIM_OC2N);
	timer_enable_break_main_output(TIM1);
/* Set the polarity of OCN to be high to match that of the OC, for switching
the low MOSFET through an inverting level shifter */
    timer_set_oc_polarity_high(TIM1, TIM_OC2N);

/* The ARR (auto-preload register) sets the PWM period to 62.5kHz from the
72 MHz clock.*/
	timer_enable_preload(TIM1);
	timer_set_period(TIM1, PERIOD);

/* The CCR1 (capture/compare register 1) sets the PWM duty cycle to default 50% */
	timer_enable_oc_preload(TIM1, TIM_OC1);
	timer_set_oc_value(TIM1, TIM_OC1, (PERIOD*20)/100);
	timer_enable_oc_preload(TIM1, TIM_OC2);
	timer_set_oc_value(TIM1, TIM_OC2, (PERIOD*50)/100);

/* Force an update to load the shadow registers */
	timer_generate_event(TIM1, TIM_EGR_UG);

/* Start the Counter. */
	timer_enable_counter(TIM1);
}