// Set the frequency (in Hz) DueTimer DueTimer::setFrequency(long frequency){ Timer t = Timers[timer]; uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above TC_SetRA(t.tc, t.channel, rc/2); //50% high, 50% low TC_SetRC(t.tc, t.channel, rc); TC_Start(t.tc, t.channel); t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS; t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS; return *this; }
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) { pmc_enable_periph_clk(id); TC_Configure(tc, channel, TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32 TC_CMR_WAVE | // Waveform mode TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC /* 84MHz, MCK/32, for 1.5ms: 3937 */ TC_SetRA(tc, channel, 2625); // 1ms /* Configure and enable interrupt */ NVIC_EnableIRQ(irqn); // TC_IER_CPAS: RA Compare tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // Enables the timer clock and performs a software reset to start the counting TC_Start(tc, channel); }
/*------------------------------------------------------------------------------ Name: startTimer parameters: tc - timer counter channel - timer channel irq - isr request frequency - frequency of inetrrupts description: initializes timer for periodic interrupt generation ------------------------------------------------------------------------------*/ void BldcControl::configureTimerInterrupt(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) { pmc_set_writeprotect(false); pmc_enable_periph_clk((uint32_t)irq); TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4); uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected //TIMER_CLOCK4 above TC_SetRA(tc, channel, rc/2); //50% high, 50% low TC_SetRC(tc, channel, rc); TC_Start(tc, channel); tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS; tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS; NVIC_EnableIRQ(irq); }
void DACClass::begin(uint32_t period) { // Enable clock for DAC pmc_enable_periph_clk(dacId); dacc_reset(dac); // Set transfer mode to double word dacc_set_transfer_mode(dac, 1); // Power save: // sleep mode - 0 (disabled) // fast wakeup - 0 (disabled) dacc_set_power_save(dac, 0, 0); // DAC refresh/startup timings: // refresh - 0x08 (1024*8 dacc clocks) // max speed mode - 0 (disabled) // startup time - 0x10 (1024 dacc clocks) dacc_set_timing(dac, 0x08, 0, DACC_MR_STARTUP_1024); // Flexible channel selection with tags dacc_enable_flexible_selection(dac); // Set up analog current dacc_set_analog_control(dac, DACC_ACR_IBCTLCH0(0x02) | DACC_ACR_IBCTLCH1(0x02) | DACC_ACR_IBCTLDACCORE(0x01)); // Enable output channels dacc_enable_channel(dac, 0); dacc_enable_channel(dac, 1); // Configure Timer Counter to trigger DAC // -------------------------------------- pmc_enable_periph_clk(ID_TC1); TC_Configure(TC0, 1, TC_CMR_TCCLKS_TIMER_CLOCK2 | // Clock at MCR/8 TC_CMR_WAVE | // Waveform mode TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR); const uint32_t TC = period / 8; TC_SetRA(TC0, 1, TC / 2); TC_SetRC(TC0, 1, TC); TC_Start(TC0, 1); // Configure clock source for DAC (2 = TC0 Output Chan. 1) dacc_set_trigger(dac, 2); // Configure pins PIO_Configure(g_APinDescription[DAC0].pPort, g_APinDescription[DAC0].ulPinType, g_APinDescription[DAC0].ulPin, g_APinDescription[DAC0].ulPinConfiguration); PIO_Configure(g_APinDescription[DAC1].pPort, g_APinDescription[DAC1].ulPinType, g_APinDescription[DAC1].ulPin, g_APinDescription[DAC1].ulPinConfiguration); // Enable interrupt controller for DAC dacc_disable_interrupt(dac, 0xFFFFFFFF); NVIC_DisableIRQ(isrId); NVIC_ClearPendingIRQ(isrId); NVIC_SetPriority(isrId, 0); NVIC_EnableIRQ(isrId); }
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); }