This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SAADC configuration

Hello,

I am using nrf52840 and I have successfully uploaded the SAADC example. I do not understand why is V(p) = VDD? How can I configure Vp to be equal to voltage that I input to pin AIN0 (P0.02)? The simple example code is in the description. I am looking forward to someone answering me. Best regards.

#include "ADC.h"

#define ANALOGNI_PIN 0  //P0.02

int main(void)
{
  volatile int16_t rezultat = 0; 				//vrednost napona u vidu celog broja
  volatile float precizni_rezultat = 0; //vrednost napona na ulazu prikazano sa odredjenim brojem decimala
	
	uint32_t err_code = NRF_LOG_INIT(NULL);
  APP_ERROR_CHECK(err_code);
  NRF_LOG_DEFAULT_BACKENDS_INIT();
	
  // Start HFCLK from crystal oscillator, this will give the SAADC higher accuracy
	// naredne tri linje koda nisam proucio, vec sam samo usvojio jer nisam jos procitao CLOCK odeljak datasheeta
  NRF_CLOCK->TASKS_HFCLKSTART = 1;
  while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
  NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

	/*
	GAIN predstavlja diferencijalni pojacavac ciji su ulazi RESN i RESP (pogledaj blok dijagram na vrhu strane 419 datasheeta nrf52840 mikrochipa)
	sluzi da ni se dovoljno pojacao signal tako da se moze primeniti za potrebnu aplikaciju. Posto se koristi interna referenca, umesto 
	VDD, usvojen je gain 1/6 kao u primeru u datasheetu (pogledati stranu 424 datasheeta nrf52840 mikrochipa). Opseg vrednosti na ulazu je od GND do 3.6V
	(pogledati stranu 424 datasheeta nrf52840 mikrochipa).
	*/
  NRF_SAADC->CH[ANALOGNI_PIN].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6    << SAADC_CH_CONFIG_GAIN_Pos) |   //GAIN (pojacanje) je podeseno da ima vrednost 1/6
																				 (SAADC_CH_CONFIG_MODE_SE         << SAADC_CH_CONFIG_MODE_Pos) |   //ADC radi u single ended modu, sto i treba posto je potrebno ocitati samo jedan analogni ulaz
																				 (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) | //pogledati stranu 420 datahseeta. Na pocetku se nalazi objasnjenje. Nije Vdd referenca vec se koristi interna referenca sto zanci da je moguci opseg ulaza do 3.6 V koje moze da registruje kontroler, tj. ADC
																				 (SAADC_CH_CONFIG_RESN_Bypass     << SAADC_CH_CONFIG_RESN_Pos) |   //posto je single ended mode, RESN je povezan na masu. Pogledaj blok dijagram i pasus odmah ispod njega na strani 419 datasheeta
																				 (SAADC_CH_CONFIG_RESP_Bypass     << SAADC_CH_CONFIG_RESP_Pos) |	 //RESP je setovan i time si podesio da je pozitivan naponski ulaz u ADC. U RESP se smesta vrednost ulaznog napona koji ide na GAIN blok.
																				 (SAADC_CH_CONFIG_TACQ_3us        << SAADC_CH_CONFIG_TACQ_Pos);    //akviziciono vreme odbirka je 3 us, usvojio sam najmanje moguce. To vreme treba odabrati u skladu sa Rsource (strana 424). 

	// Single ended rezim se koristi posto ocitavas sa jednog ulaza samo vrednost. Nije moguce ocitati negativan napon. Posto si samo setovao PSELP, a PSELN nisi, usao si u one shot mode sto znaci da samplujes samo jedan kanal.
  NRF_SAADC->CH[ANALOGNI_PIN].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos; //ocitavas vrednost ulaza na analognom pinu
  NRF_SAADC->CH[ANALOGNI_PIN].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;

  //Za sad je podesena najveca rezolucija, ovo ces verovatno promeniti kad odredis stvarnu potrebnu rezoluciju.
  NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos; 

  NRF_SAADC->RESULT.MAXCNT = 1;                //zauzeli smo memorijski prostor u easyDMA medijumu                                                          
  NRF_SAADC->RESULT.PTR = (uint32_t)&rezultat; //u promenljivu rezultat se smesta vrednost adc konverzije                

  // No automatic sampling, will trigger with TASKS_SAMPLE.
  NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;  //kada se desi sample task, sampluje se signal na ulazu. Ti softverski dizes flag za pocinjanje sample taska

  // Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
  NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos; //enejblovao si adc konverziju na pinu 

  // Calibrate the SAADC (only needs to be done once in a while). Ovo znaci da kalibrises rad ADCa za svaki slucaj jer on menja svoj ofset na velikim temperaturama. Ne bitno ako radi na sobnoj temperaturi konstantno
  NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
  while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
  NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
  while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy <<SAADC_STATUS_STATUS_Pos));

  // Start the SAADC and wait for the started event. //u cemu je razlika u odnosu na enable?
  NRF_SAADC->TASKS_START = 1;
  while (NRF_SAADC->EVENTS_STARTED == 0);
  NRF_SAADC->EVENTS_STARTED = 0;

  // Do a SAADC sample, will put the result in the configured RAM buffer. //jasno je
  NRF_SAADC->TASKS_SAMPLE = 1;
  while (NRF_SAADC->EVENTS_END == 0);
  NRF_SAADC->EVENTS_END = 0;

  // Convert the result to voltage
  // Result = [V(p) - V(n)] * GAIN/REFERENCE * 2^(RESOLUTION)
  // Result = (VDD - 0) * ((1/6) / 0.6) * 2^14
  // VDD = Result / 4551.1
  precizni_rezultat = (float)rezultat / 4551.1f;
  precizni_rezultat; // to get rid of set but not used warning

  // Stop the SAADC, since it's not used anymore.
  NRF_SAADC->TASKS_STOP = 1;
  while (NRF_SAADC->EVENTS_STOPPED == 0);
  NRF_SAADC->EVENTS_STOPPED = 0;
	
	NRF_LOG_INFO("%d", rezultat);
	NRF_LOG_FLUSH();
	 
  while (1)
  {	
    __WFE(); //wait foe an event. 
  }
}

Related