Exemplo n.º 1
0
/* Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */
static inline void adc_init_rcc( void )
{
#if defined (USE_AD1) || defined (USE_AD2)
  uint32_t timer;
  volatile uint32_t *rcc_apbenr;
  uint32_t rcc_apb;
#if defined(USE_AD_TIM4)
  timer   = TIM4;
  rcc_apbenr = &RCC_APB1ENR;
  rcc_apb = RCC_APB1ENR_TIM4EN;
#elif defined(USE_AD_TIM1)
  timer   = TIM1;
  rcc_apbenr = &RCC_APB2ENR;
  rcc_apb = RCC_APB2ENR_TIM1EN;
#else
  timer   = TIM2;
  rcc_apbenr = &RCC_APB1ENR;
  rcc_apb = RCC_APB1ENR_TIM2EN;
#endif

  /*
   * Historic Note:
   * Previously in libstm32 we were setting the ADC clock here.
   * It was being set to PCLK2 DIV2 resulting in 36MHz clock on the ADC. I am
   * pretty sure that this is wrong as based on the datasheet the ADC clock
   * must not exceed 14MHz! Now the clock is being set by the clock init
   * routine in libopencm3 so we don't have to set up this clock ourselves any
   * more. This comment is here just as a reminder and may be removed in the
   * future when we know that everything is working properly.
   * (by Esden the historian :D)
   */

  /* Timer peripheral clock enable. */
  rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);
  /* GPIO peripheral clock enable. */
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN |
                              RCC_APB2ENR_IOPCEN);

  /* Enable ADC peripheral clocks. */
#ifdef USE_AD1
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
#endif
#ifdef USE_AD2
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC2EN);
#endif

  /* Time Base configuration */
  timer_reset(timer);
  timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
                 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
  timer_set_period(timer, 0xFF);
  timer_set_prescaler(timer, 0x8);
  timer_set_clock_division(timer, 0x0);
  /* Generate TRGO on every update. */
  timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
  timer_enable_counter(timer);

#endif // defined (USE_AD1) || defined (USE_AD2)
}
Exemplo n.º 2
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;
    }
}
static void timer_setup(void)
{
	/* Set up the timer TIM2 for injected sampling */
	uint32_t timer;

	timer   = TIM2;
	rcc_periph_clock_enable(RCC_TIM2);

	/* Time Base configuration */
    timer_reset(timer);
    timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
	    TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_period(timer, 0xFF);
    timer_set_prescaler(timer, 0x8);
    timer_set_clock_division(timer, 0x0);
    /* Generate TRGO on every update. */
    timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
    timer_enable_counter(timer);
}
static void timer_setup(void)
{
	/* Set up the timer TIM2 for injected sampling */
	uint32_t timer;
    volatile uint32_t *rcc_apbenr;
    uint32_t rcc_apb;

	timer   = TIM2;
    rcc_apbenr = &RCC_APB1ENR;
    rcc_apb = RCC_APB1ENR_TIM2EN;

	rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);

	/* Time Base configuration */
    timer_reset(timer);
    timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
	    TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_period(timer, 0xFF);
    timer_set_prescaler(timer, 0x8);
    timer_set_clock_division(timer, 0x0);
    /* Generate TRGO on every update. */
    timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
    timer_enable_counter(timer);
}
//------------Private Helper functions--------------------------------------------------------------------------
//Setup hardware to read temperature data (input as a freq on PC8)
void Temperature::initMotorTemperature(void) {

	//ENABLE TIM3 full remap (PC8 on chnl 3)
	AFIO_MAPR |= AFIO_MAPR_TIM3_REMAP_FULL_REMAP;

	//TIM3 clock source enable
	RCC_APB1ENR |= RCC_APB1ENR_TIM3EN;

	//Enable GPIOC clock
	RCC_APB2ENR |= RCC_APB2ENR_IOPCEN;

	//Set GPIOC Pin 8 as input floating (motor temperature - freq maps to temperature)
	gpio_set_mode(
	  GPIOC,
	  GPIO_MODE_INPUT,
	  GPIO_CNF_INPUT_FLOAT,
	  GPIO8);

	//TIM3 Prescaler = 0  i.e. No prescaling
	TIM3_PSC = 0x0;
	//TIM3 Counter Mode Up;
	timer_set_alignment(TIM3, TIM_CR1_CMS_EDGE);
	//TIM3 Period = 65535
	TIM3_ARR = 65535;
	//TIM3 clock division 1
	timer_set_clock_division(TIM3, TIM_CR1_CKD_CK_INT);

	//(CC1 input, IC1 mapped onto TI1) and OC1Ref is cleared when High detected on ETRF input
	TIM3_CCMR1 |= 0x04 | 0x01;
	TIM3_CR2 |= 0x0080;  //Set TI1S (CH1, CH2 and CH3 are connected to the TI1 input (XOR)
	TIM3_SMCR = 0x50 | 0x07; //TI1FR1 (b101) and SMS = external clock /mode 1
	TIM3_SR = ~((u16)0x0001); //Clear Update interupt flag (UIF)
	TIM3_DIER |= 0x0001; //IT update (UIE - update interupt enable)
	TIM3_CNT = 0;   //Clear counter
	TIM3_CR1 |= TIM_CR1_CEN;  //Finally, enable it!
}