Exemplo n.º 1
0
/**
 * \internal
 * \brief Configure the ADC Module.
 *
 * \param adc  Base address of the ADC
 * \param config   Configuration for the ADC
 */
static void adc_set_config(Adc *const adc, struct adc_config *config)
{
	uint32_t reg = 0;

	reg =  (config->useq ? ADC_MR_USEQ_REG_ORDER : 0) |
			ADC_MR_PRESCAL(config->mck /
			(2 * config->adc_clock) - 1) |
			ADC_MR_TRACKTIM(config->tracktim) |
			ADC_MR_TRANSFER(config->transfer) |
			(config->startup_time);

	adc->ADC_MR = reg;

	adc->ADC_EMR = (config->tag ? ADC_EMR_TAG : 0) |
			(config->aste ? ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE : 0);

	if (ADC_8_BITS == config->resolution ||
			ADC_10_BITS == config->resolution) {
		adc->ADC_MR |= config->resolution;
		adc->ADC_EMR &= ~ADC_EMR_OSR_Msk;
	} else {
		adc->ADC_MR &= ~ADC_MR_LOWRES;
		adc->ADC_EMR |= config->resolution;
	}
}
Exemplo n.º 2
0
void adc_init()
{
  PMC_EnablePeripheral(ID_ADC);
  ADC->ADC_CR = ADC_CR_SWRST;
  ADC->ADC_MR = ADC_MR_TRANSFER(1) | 
                ADC_MR_TRACKTIM(1) |
                ADC_MR_SETTLING(3) |
                ADC_MR_PRESCAL(4)  |   // adc clock = 64 MHz / ((4+1)*2) = 6.4
                ADC_MR_FREERUN     |
                ADC_MR_STARTUP_SUT512;
  ADC->ADC_CHER = (1 << ADC_CH_INPUT_VOLTAGE)    |
                  (1 << ADC_CH_TEMPERATURE)      |
                  (1 << ADC_CH_PHALANGE_CURRENT);
  ADC->ADC_IDR = 0xffffffff;
  ADC->ADC_ACR = ADC_ACR_TSON; // turn on temperature sensor
  ADC->ADC_CR = ADC_CR_START; // start a conversion
  while (!(ADC->ADC_ISR & ADC_ISR_DRDY)) { }
  ADC->ADC_LCDR;
  ADC->ADC_CR = ADC_CR_START; // start another conversion
  while (!(ADC->ADC_ISR & ADC_ISR_DRDY)) { }
  ADC->ADC_LCDR;
  ADC->ADC_IER = ADC_IER_DRDY; // fire ADC interrupt on any conversion complete
  for (int i = 0; i < 3; i++)
    g_adc_data[i] = 0x42 + i;
  NVIC_SetPriority(ADC_IRQn, 11); // really low priority...
  NVIC_EnableIRQ(ADC_IRQn);
}
Exemplo n.º 3
0
// Initialize ADC channels
void HAL::analogStart(void)
{

#if MOTHERBOARD == 500 || MOTHERBOARD == 501
  PIO_Configure(
    g_APinDescription[58].pPort,
    g_APinDescription[58].ulPinType,
    g_APinDescription[58].ulPin,
    g_APinDescription[58].ulPinConfiguration);
  PIO_Configure(
    g_APinDescription[59].pPort,
    g_APinDescription[59].ulPinType,
    g_APinDescription[59].ulPin,
    g_APinDescription[59].ulPinConfiguration);
#endif // (MOTHERBOARD==500) || (MOTHERBOARD==501)

  // ensure we can write to ADC registers
  ADC->ADC_WPMR = 0x41444300u; //ADC_WPMR_WPKEY(0);
  pmc_enable_periph_clk(ID_ADC);  // enable adc clock

  for (int i = 0; i < ANALOG_INPUTS; i++)
  {
    osAnalogInputValues[i] = 0;
    adcSamplesMin[i] = 100000;
    adcSamplesMax[i] = 0;
    adcEnable |= (0x1u << osAnalogInputChannels[i]);
    osAnalogSamplesSum[i] = 2048 * ANALOG_INPUT_MEDIAN;
    for (int j = 0; j < ANALOG_INPUT_MEDIAN; j++)
      osAnalogSamples[i][j] = 2048; // we want to prevent early error from bad starting values
  }
  // enable channels
  ADC->ADC_CHER = adcEnable;
  ADC->ADC_CHDR = !adcEnable;

  // Initialize ADC mode register (some of the following params are not used here)
  // HW trigger disabled, use external Trigger, 12 bit resolution
  // core and ref voltage stays on, normal sleep mode, normal not free-run mode
  // startup time 16 clocks, settling time 17 clocks, no changes on channel switch
  // convert channels in numeric order
  // set prescaler rate  MCK/((PRESCALE+1) * 2)
  // set tracking time  (TRACKTIM+1) * clock periods
  // set transfer period  (TRANSFER * 2 + 3)
  ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_TRGSEL_ADC_TRIG0 | ADC_MR_LOWRES_BITS_12 |
                ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF | ADC_MR_FREERUN_OFF |
                ADC_MR_STARTUP_SUT64 | ADC_MR_SETTLING_AST17 | ADC_MR_ANACH_NONE |
                ADC_MR_USEQ_NUM_ORDER |
                ADC_MR_PRESCAL(AD_PRESCALE_FACTOR) |
                ADC_MR_TRACKTIM(AD_TRACKING_CYCLES) |
                ADC_MR_TRANSFER(AD_TRANSFER_CYCLES);

  ADC->ADC_IER = 0;             // no ADC interrupts
  ADC->ADC_CGR = 0;             // Gain = 1
  ADC->ADC_COR = 0;             // Single-ended, no offset

  // start first conversion
  ADC->ADC_CR = ADC_CR_START;
}
Exemplo n.º 4
0
struct gpio_adc
gpio_adc_setup(uint8_t pin)
{
    // Find pin in adc_pins table
    int chan;
    for (chan=0; ; chan++) {
        if (chan >= ARRAY_SIZE(adc_pins))
            shutdown("Not a valid ADC pin");
        if (adc_pins[chan] == pin)
            break;
    }

    if (!(PMC->PMC_PCSR1 & (1 << (ID_ADC-32)))) {
        // Setup ADC
        PMC->PMC_PCER1 = 1 << (ID_ADC-32);
        uint32_t prescal = SystemCoreClock / (2 * ADC_FREQ_MAX) - 1;
        ADC->ADC_MR = (ADC_MR_PRESCAL(prescal)
                       | ADC_MR_STARTUP_SUT768
                       | ADC_MR_TRANSFER(1));
    }
    return (struct gpio_adc){ .bit = 1 << chan };
}

// Try to sample a value. Returns zero if sample ready, otherwise
// returns the number of clock ticks the caller should wait before
// retrying this function.
uint32_t
gpio_adc_sample(struct gpio_adc g)
{
    uint32_t chsr = ADC->ADC_CHSR & 0xffff;
    if (!chsr) {
        // Start sample
        ADC->ADC_CHER = g.bit;
        ADC->ADC_CR = ADC_CR_START;
        goto need_delay;
    }
    if (chsr != g.bit)
        // Sampling in progress on another channel
        goto need_delay;
    if (!(ADC->ADC_ISR & ADC_ISR_DRDY))
        // Conversion still in progress
        goto need_delay;
    // Conversion ready
    return 0;
need_delay:
    return ADC_FREQ_MAX * 1000ULL / CONFIG_CLOCK_FREQ;
}
Exemplo n.º 5
0
// Initialize ADC channels
void HAL::analogStart(void)
{
  uint32_t  adcEnable = 0;

  // ensure we can write to ADC registers
  ADC->ADC_WPMR = ADC_WPMR_WPKEY(0);
  pmc_enable_periph_clk(ID_ADC);  // enable adc clock

  for(int i=0; i<ANALOG_INPUTS; i++)
  {
      osAnalogInputCounter[i] = 0;
      osAnalogInputValues[i] = 0;

  // osAnalogInputChannels
      //adcEnable |= (0x1u << adcChannel[i]);
      adcEnable |= (0x1u << osAnalogInputChannels[i]);
  }

  // enable channels
  ADC->ADC_CHER = adcEnable;
  ADC->ADC_CHDR = !adcEnable;

  // Initialize ADC mode register (some of the following params are not used here)
  // HW trigger disabled, use external Trigger, 12 bit resolution
  // core and ref voltage stays on, normal sleep mode, normal not free-run mode
  // startup time 16 clocks, settling time 17 clocks, no changes on channel switch
  // convert channels in numeric order
  // set prescaler rate  MCK/((PRESCALE+1) * 2)
  // set tracking time  (TRACKTIM+1) * clock periods
  // set transfer period  (TRANSFER * 2 + 3) 
  ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_TRGSEL_ADC_TRIG0 | ADC_MR_LOWRES_BITS_10 |
            ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF | ADC_MR_FREERUN_OFF |
            ADC_MR_STARTUP_SUT64 | ADC_MR_SETTLING_AST17 | ADC_MR_ANACH_NONE |
            ADC_MR_USEQ_NUM_ORDER |
            ADC_MR_PRESCAL(AD_PRESCALE_FACTOR) |
            ADC_MR_TRACKTIM(AD_TRACKING_CYCLES) |
            ADC_MR_TRANSFER(AD_TRANSFER_CYCLES);

  ADC->ADC_IER = 0;             // no ADC interrupts
  ADC->ADC_CGR = 0;             // Gain = 1
  ADC->ADC_COR = 0;             // Single-ended, no offset
  
  // start first conversion
  ADC->ADC_CR = ADC_CR_START;
}
Exemplo n.º 6
0
/**
 * \internal
 * \brief Configure the ADC Module.
 *
 * \param adc  Base address of the ADC
 * \param config   Configuration for the ADC
 */
static void adc_set_config(Adc *const adc, struct adc_config *config)
{
	uint32_t reg = 0;

	reg =  (config->useq ? ADC_MR_USEQ_REG_ORDER : 0) |
			ADC_MR_PRESCAL(config->mck /
			(2 * config->adc_clock) - 1) |
			ADC_MR_TRACKTIM(config->tracktim) |
			ADC_MR_TRANSFER(config->transfer) |
			(config->startup_time);

	adc->ADC_MR = reg;

	adc->ADC_EMR = (config->tag ? ADC_EMR_TAG : 0) |
			(config->aste ? ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE : 0);

	adc_set_resolution(adc, config->resolution);
}
Exemplo n.º 7
0
// Initializes de ADC.  To be used only once.
static void ADC_Init() {

    // Power up ADC
    PMC->PMC_PCER0 |= ADC_POWER_BITMASK;

    // Reset the controller
    ADC->ADC_CR = ADC_CR_SWRST;

    // Reset the Control Register
    // This sets:
    // * Hardware triggers are disabled. Only software triggers.
    // * No trigger selected.
    // * High resolution selected.
    // * No sleep mode, no fast wake up, no free run.
    // * The clock divider to 4 (12 MHz).
    // * No analog change
    // * No sequence
    ADC->ADC_MR = ADC_MR_PRESCAL(1) | ADC_MR_STARTUP(8) |
                  ADC_MR_TRANSFER(1) | ADC_MR_TRACKTIM(0) | ADC_MR_SETTLING(3);
}
Exemplo n.º 8
0
ADC_DRIVER_DATA_STRU adc_driver_data;

const ADC_DRIVER_INFO adc_driver =
{
	{
		DRIVER_INFO_STUB,
		(DRV_ISR)ADC_ISR,
		(DRV_DCR)ADC_DCR,
		(DRV_DSR)ADC_DSR,
		ADC_IRQn,
		DRV_PRIORITY_KERNEL,
		ID_ADC
	},
	ADC,
	&adc_driver_data,
	ADC_MR_TRANSFER(1) | ADC_MR_TRACKTIM(7) | ADC_MR_SETTLING(3) | ADC_MR_STARTUP_SUT96//CFG_ADC_MR
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 		(30) DACC DRIVER
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DACC_DRIVER_DATA_STRU dacc_driver_data;

const DACC_DRIVER_INFO dacc_driver =
{
	{
		DRIVER_INFO_STUB,
		(DRV_ISR)DACC_ISR,
		(DRV_DCR)DACC_DCR,
		(DRV_DSR)DACC_DSR,
		DACC_IRQn,
Exemplo n.º 9
0
void ADCSampler::begin(unsigned int samplingRate)
{
  this->sampleingRate = sampleingRate;
  // Turning devices Timer on.
  pmc_enable_periph_clk(ID_TC0); 


  // Configure timer
  TC_Configure(TC0, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET | TC_CMR_ASWTRG_CLEAR | TC_CMR_TCCLKS_TIMER_CLOCK1);

  // It is good to have the timer 0 on PIN2, good for Debugging 
  //int result = PIO_Configure( PIOB, PIO_PERIPH_B, PIO_PB25B_TIOA0, PIO_DEFAULT);

  // Configure ADC pin A7
  //  the below code is taken from adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);

  ADC->ADC_CR = ADC_CR_SWRST;                            // Reset the controller.
  ADC->ADC_MR = 0;                                       // Reset Mode Register.
  ADC->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);   // Reset PDC transfer.
  ADC->ADC_MR |= ADC_MR_PRESCAL(3);                      // ADC clock = MSCK/((PRESCAL+1)*2), 13 -> 750000 Sps
  ADC->ADC_MR |= ADC_MR_STARTUP_SUT0;                    // What is this by the way?
  ADC->ADC_MR |= ADC_MR_TRACKTIM(15);
  ADC->ADC_MR |= ADC_MR_TRANSFER(1);
  ADC->ADC_MR |= ADC_MR_TRGEN_EN;                         // Hardware trigger selected by TRGSEL field is enabled. Включен аппаратный триггер, выбранный по полю TRGSEL.
  ADC->ADC_MR |= ADC_MR_TRGSEL_ADC_TRIG1;                 // selecting TIOA0 as trigger.
  ADC->ADC_MR |= ADC_MR_LOWRES_BITS_12;                   // brief (ADC_MR) 12-bit resolution 
  //ADC->ADC_ACR |= ADC_ACR_TSON;                         // Включить датчик температуры    
 
  ADC->ADC_CHER = ADC_CHANNELS;                           // Записать контролируемые входа
  ADC->ADC_CHDR = ADC_CHANNELS_DIS;                       // Отключить не используемые входа
  ADC->ADC_EMR = ADC_EMR_CMPMODE_IN                       // Генерирует событие, когда преобразованные данные пересекают окно сравнения.
	//  | ADC_EMR_CMPSEL(4)                               // Compare channel 4 = A3
	  | ADC_EMR_CMPALL                                    // Compare ALL channel
	  | ADC_EMR_CMPFILTER(0);                             // Количество последовательных событий сравнения, необходимых для повышения флага = CMPFILTER + 1
														  // При запрограммированном значении 0 флаг увеличивается, как только происходит событие.

  ADC->ADC_CWR = ADC_CWR_LOWTHRES(_compare_Low) | ADC_CWR_HIGHTHRES(_compare_High); // Установить высокий и низкий порог компаратора АЦП

  //ADC->ADC_SEQR1 = 0x01234567;                            // использовать A0 до A7 в порядке в массив
  //ADC->ADC_SEQR2 = 0x00dcba00;                            // использовать для А8 А11 следующие действия по порядку в массив  

  /* Interupts */
  ADC->ADC_IDR = ~ADC_IDR_ENDRX;                        // сбросить регистры прерывания по готовности данных.
  ADC->ADC_IDR = ~ADC_IDR_COMPE;                        // сбросить регистры копаратора.
  ADC->ADC_IER =  ADC_IER_ENDRX;                        // Включить прерывание по готовности данных.
 // ADC->ADC_IER =  ADC_IER_COMPE;                        // Прерывание по совпадению сравнения компаратором
  ADC->ADC_ISR = ~ADC_ISR_COMPE;                        // ADC Interrupt Status Register Обнулить ошибку сравнения с момента последнего чтения ADC_ISR.
  /* Waiting for ENDRX as end of the transfer is set
    when the current DMA transfer is done (RCR = 0), i.e. it doesn't include the
    next DMA transfer.

    If we trigger on RXBUFF This flag is set if there is no more DMA transfer in
    progress (RCR = RNCR = 0). Hence we may miss samples.

	Ожидание окончания ENDRX в конце передачи
	когда выполняется текущая передача DMA (RCR = 0), то есть она не включает следующая передача DMA.
    Если мы запускаем RXBUFF, этот флаг устанавливается, если больше нет передачи DMA в прогресс (RCR = RNCR = 0). 
	Следовательно, мы можем пропустить образцы.
  */

  
  unsigned int cycles = 42000000 / samplingRate;

  /*  timing of ADC */
  TC_SetRC(TC0, 0, cycles);                             // TIOA0 goes HIGH on RC.
  TC_SetRA(TC0, 0, cycles / 2);                         // TIOA0 goes LOW  on RA.

  // We have to reinitalise just in case the Sampler is stopped and restarted...
  // Мы должны приступить к реинициализировать на случай, если Sampler остановлен и перезапущен ...
  dataReady = false;
  dataHigh = false;                       // Признак срабатывания компаратора
  adcDMAIndex = 0;
  adcTransferIndex = 0;
  for (int i = 0; i < NUMBER_OF_BUFFERS; i++)
  {
    memset((void *)adcBuffer[i], 0, BUFFER_SIZE);
  }

  ADC->ADC_RPR  = (unsigned long) adcBuffer[adcDMAIndex];         // DMA buffer
  ADC->ADC_RCR  = (unsigned int)  BUFFER_SIZE;                    // ADC works in half-word mode.
  ADC->ADC_RNPR = (unsigned long) adcBuffer[(adcDMAIndex + 1)];   // next DMA buffer
  ADC->ADC_RNCR = (unsigned int)  BUFFER_SIZE;

  // Enable interrupts
  NVIC_SetPriorityGrouping(NVIC_PriorityGroup_1);
  NVIC_DisableIRQ(ADC_IRQn);
  NVIC_ClearPendingIRQ(ADC_IRQn);  
  NVIC_SetPriority(ADC_IRQn, 6);  
  NVIC_EnableIRQ(ADC_IRQn);
  ADC->ADC_PTCR  =  ADC_PTCR_RXTEN;                               // Enable receiving data.
  ADC->ADC_CR   |=  ADC_CR_START;                                 // start waiting for trigger.

  // Start timer
  TC0->TC_CHANNEL[0].TC_SR;
  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN;
  TC_Start(TC0, 0);
}