Pages: [1]   Go Down
Author Topic: PWM trigger ADC interrupts  (Read 1169 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For my project, I'm emulating a quadrature encoder signal (A+B+index and 3 inverse). I use pwm signals for this with 50% dutycycle and a varying frequency dependent on the voltage read by pin A9 (analog channel 11). The phase shifts of the B signal I made with the deadtime generator. The Index signal is not yet implemented.
During the PWM period I want to trigger the ADC to read the voltage. This works, but when the voltage gets zero, the PWM doesnt trigger an event line and doesn't read anymore. Is there a way to manually trigger the ADC? Or other solutions to this problem? Thanks!

Code:
void pwmWrite(uint32_t ulFreq) {

  static uint8_t PWMEnabled = 0;
  static uint8_t ADCEnabled = 0;
  static uint8_t pin6Enabled = 0;
  static uint8_t pin7Enabled = 0;
  static uint8_t pin8Enabled = 0;
  static uint8_t pin9Enabled = 0;

  int duty_100 = 255;
  int duty_75 = (((duty_100+1)/4)*3)-1;
  int duty_50 = ((duty_100+1)/2)-1;
  int duty_25 = ((duty_100+1)/4)-1;
 
  if (!ADCEnabled) {
    pmc_enable_periph_clk(ID_ADC);
    adc_init(ADC, VARIANT_MCK, ADC_FREQ_MAX, 0);
    adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_0, 0);
    adc_stop_sequencer(ADC);
    adc_enable_channel(ADC, (adc_channel_num_t)11);
    adc_enable_interrupt(ADC, ADC_IER_DRDY);
    NVIC_EnableIRQ(ADC_IRQn);
    ADCEnabled = 1;
  }   
 
  if (!PWMEnabled) {
    pmc_enable_periph_clk(ID_PWM);
    PWMC_ConfigureClocks(0, 0, VARIANT_MCK );
    PWMEnabled = 1;
  }
   
  // SETUP PINS 6 T/M 9
  uint32_t chan6 = g_APinDescription[6].ulPWMChannel;
  uint32_t chan7 = g_APinDescription[7].ulPWMChannel;
  uint32_t chan8 = g_APinDescription[8].ulPWMChannel;
  uint32_t chan9 = g_APinDescription[9].ulPWMChannel;
 
  if (!pin6Enabled || !pin7Enabled || !pin8Enabled || !pin9Enabled) {
    PIO_Configure(g_APinDescription[6].pPort, g_APinDescription[6].ulPinType, g_APinDescription[6].ulPin, g_APinDescription[6].ulPinConfiguration);
    PIO_Configure(g_APinDescription[7].pPort, g_APinDescription[7].ulPinType, g_APinDescription[7].ulPin, g_APinDescription[7].ulPinConfiguration);
    PIO_Configure(g_APinDescription[8].pPort, g_APinDescription[8].ulPinType, g_APinDescription[8].ulPin, g_APinDescription[8].ulPinConfiguration); 
    PIO_Configure(g_APinDescription[9].pPort, g_APinDescription[9].ulPinType, g_APinDescription[9].ulPin, g_APinDescription[9].ulPinConfiguration);
             
    // CONFIGURE CHANNELS
    PWMC_ConfigureChannel(PWM, chan6, PWM_CMR_CPRE_CLKA, 0, 0);
    PWMC_ConfigureChannel(PWM, chan7, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
    PWMC_ConfigureChannel(PWM, chan8, PWM_CMR_CPRE_CLKA, 0, 0);           
    PWMC_ConfigureChannel(PWM, chan9, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
       
    // SET PERIODS
    PWMC_SetPeriod(PWM, chan6, duty_100);
    PWMC_SetPeriod(PWM, chan7, duty_100);
    PWMC_SetPeriod(PWM, chan8, duty_100);
    PWMC_SetPeriod(PWM, chan9, duty_100);  // PWM_MAX_DUTY_CYCLE (100%)
       
    // SET DUTY CYCLES   
    PWMC_SetDutyCycle(PWM, chan6, duty_50);   
    PWMC_SetDutyCycle(PWM, chan7, duty_50); 
    PWMC_SetDutyCycle(PWM, chan8, duty_75);   
    PWMC_SetDutyCycle(PWM, chan9, duty_75); 
       
    //SET DEAD TIME
    PWM->PWM_CH_NUM[chan8].PWM_CMR |= PWM_CMR_DTE;  // added, enable channel dead time DTE=1
    PWM->PWM_CH_NUM[chan9].PWM_CMR |= PWM_CMR_DTE;
    PWMC_SetDeadTime(PWM, chan8, 0, duty_25);
    PWMC_SetDeadTime(PWM, chan9, 0, duty_25);
       
    //SYNC CHANNELS
    PWMC_ConfigureSyncChannel(PWM, ( PWM_SCM_SYNC4 |  PWM_SCM_SYNC5 | PWM_SCM_SYNC6 | PWM_SCM_SYNC7), PWM_SCM_UPDM_MODE2, 0, 0); 
    PWMC_SetSyncChannelUpdateUnlock(PWM);              // PWM_SCUC set UPDULOCK to 1, update next period
    PWMC_SetSyncChannelUpdatePeriod(PWM, duty_100);    //  update period of the synchronous channels PWM_SCUP
       
    // EVENT LINES FOR ADC
    PWMC_ConfigureEventLineMode( PWM, 0, 1 ) ;
    PWMC_ConfigureComparisonUnit(PWM, 0, (duty_100/2), 1);
         
    // SET CHANNEL 0 FOR SYNC
    PWMC_ConfigureChannel(PWM, 0, PWM_CMR_CPRE_CLKA, 0, 0);
    PWMC_SetPeriod(PWM, 0, duty_100);
    PWMC_SetDutyCycle(PWM, 0, duty_50);
    PWMC_EnableChannel(PWM, 0);
   
    // CONFIGURE TRIGGER ON EVENT LINE
    adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0, 0);
       
    pin6Enabled = 1;
    pin7Enabled = 1;
    pin8Enabled = 1;
    pin9Enabled = 1;
  }
   
  if (lastState == 0 && CW == 1) {
    PWM->PWM_CH_NUM[chan8].PWM_CMR |= PWM_CMR_CPOL;  // set CPOL 0
    PWM->PWM_CH_NUM[chan9].PWM_CMR &= 0xFFFFFDFF;
    lastState = 1;
  }
 
  if (lastState == 1 && CW == 0) {
    PWM->PWM_CH_NUM[chan8].PWM_CMR &= 0xFFFFFDFF;  // set CPOL 0
    PWM->PWM_CH_NUM[chan9].PWM_CMR |= PWM_CMR_CPOL;
    lastState = 0;
  }
   
  PWMC_ConfigureClocks(ulFreq * duty_100, 0, VARIANT_MCK );
   
  return;
}

Code:
// ADC Interrupt handler.
void ADC_Handler(){
  uint32_t ul_Value;
  if ((adc_get_status(ADC) & ADC_ISR_DRDY) == ADC_ISR_DRDY)  {
    ul_Value = adc_get_latest_value(ADC);
    //Serial.println(ul_Value);
  }
  PWMC_ConfigureClocks(ul_Value*255, 0, VARIANT_MCK );

}
Logged

Pages: [1]   Go Up
Jump to: