Author Topic: [SAM] [ADC] register conundrums  (Read 3463 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[SAM] [ADC] register conundrums
« on: February 02, 2022, 08:35:29 am »
I attach 3 sections of the ADC description for the SAMC, So this offset and gain calculation. I assume from the lack of mention that this something that has to be manually added ? It's not that the ADC automatically works out it's gain and offset error?

There seem to be 2 offset features the other is definitely automatic, I assume the input is shorted to ground and a reading taken to subtract from the value automatically. As they tell you all about this I assume the other is not automatic and I would have to devise a self calibration routine.

So the gain register. that text is incomprehensible to me. I understood it as there is an 11 bit value that, actually i don't know, I give up.

½ <= GAINCORR < 2

Are they trying to say that the gain can be set from 0.5-2?

values range from 0.10000000000 to 1.11111111111

But 0.1 is less than 0.5

2^11 = 2048, did they mean that this is in 2's complement like the offset register? in which case a 10 bit fractional value could be added to "1" to produce a +/- amount around "1" which is the neutral value for gain calculations.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #1 on: February 02, 2022, 08:57:40 am »
Buffer compensation and offset correction are completely different independent features. The first one is analog and affects conversion results. The second one is purely digital applied after the conversion is done.

Gain correction is a fixed point fractional number. 0.10..000 and 1.111..1111 are binary numbers.  0.10..000 in binary is a 0.5 fractional value. Binary 1.00..00 is 1.0 decimal. To divide 1.0 by 2 you shift 1.00..00 to the right, and you get 0.10..000. Same with multiplication by 2 - if you shift 1.00..00 to the left, you get 10.00..00, but this is not representable in this fixed point format, so they use 1.111...111 (shifted number minus one), so the actual multiplication is done by 1.999...999, and not 2. That's why it says "0.5 <=", but "< 2".

Look up how fixed point fractional numbers work if you want to understand this in detail.

Alternatively you can read uncorrected numbers and apply any correction you like in the firmware.  You will not lose in analog accuracy, since this correction is digital anyway. It is nothing you can't do on the MCU itself.

This format of the fixed point number would be called "UQ1.11". See https://en.wikipedia.org/wiki/Q_(number_format) for details.
« Last Edit: February 02, 2022, 09:07:54 am by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #2 on: February 02, 2022, 09:24:24 am »
Right so 3rd attempt at this. Are they saying (but not saying) that you cannot put less than 10000000000 in the register? so it will be, no that still does not work, none of these bits can be a fraction whilst also determining the whole number not be 0 or 1. The only way this could work is that the number is in 2's complement as a fraction added to 1, if you add a negative fraction to 1 you will make it 0.something. But they do not say that the number is in 2's complement.

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #3 on: February 02, 2022, 09:33:33 am »
I guess, technically you should be able to put numbers less than 0.10000000000, which would represent gain < 0.5, but the result depends on how their multiplier is implemented. So yes, you should not configure gain < 0.5. I'm not sure why you would ever want to do that anyway.

And yes, it works. Read how fixed points numbers work. Integer part is 1 bit (most significant one). It can be either 0 or 1, so full range represented by the fixed point number is 0.0 to 1.99(9). And in this case lower end is limited to 0.5 for some reason, but that's a separate story.
« Last Edit: February 02, 2022, 09:36:07 am by ataradov »
Alex
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8193
  • Country: fi
Re: [SAM] [ADC] register conundrums
« Reply #4 on: February 02, 2022, 09:38:07 am »
Also don't fall into the trap of premature optimization. Gain and offset corrections are nice features, but the whole idea is they just save a few CPU cycles.

Just start by using the values as-is. If you need calibration, do it in software, less need to read and understand manuals, more control about what happens.

Only if you actually have a performance issue, then think about utilizing in-peripheral processing features.

Regarding the fixed-point value, it might be easier if you just think about it as a number, where 1024 corresponds to exactly 1.0, and 2048 would correspond to exactly 2.0. 0 would correspond 0. It's a simple linear system. If you need 1.1, that would be approximately 1024+102.
« Last Edit: February 02, 2022, 09:41:18 am by Siwastaja »
 
The following users thanked this post: hans, thm_w

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #5 on: February 02, 2022, 09:43:32 am »
my problem is not fixed point numbers of which there are various ways of representing them.

So the 11th digit is the whole part, the lower 10 are a 10 bit fraction (not 11!) and the minimum value is 01000000000 which is 0.1000000000 not 0.10000000000 as shown.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #6 on: February 02, 2022, 09:44:57 am »
Also don't fall into the trap of premature optimization. Gain and offset corrections are nice features, but the whole idea is they just save a few CPU cycles.

Just start by using the values as-is. If you need calibration, do it in software, less need to read and understand manuals, more control about what happens.

Only if you actually have a performance issue, then think about utilizing in-peripheral processing features.

Regarding the fixed-point value, it might be easier if you just think about it as a number, where 1024 corresponds to exactly 1.0, and 2048 would correspond to exactly 2.0. 0 would correspond 0. It's a simple linear system. If you need 1.1, that would be approximately 1024+102.

i don't intend using this feature yet. I'm just trying to get into the head oaf the person writing this.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #7 on: February 02, 2022, 09:46:18 am »
It is a 12 bit number with bits going from 0 to 11. Most significant bit is integer part, 11 least significant bits are fractional part. The datasheet is correct.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #8 on: February 02, 2022, 10:19:26 am »
Sorry yes I was fooled by bit position 11, yes it is 12 bits, so minimum value is 010000000000 with a decimal place added after the first digit.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #9 on: February 02, 2022, 10:21:09 am »
Right, next. Rail to rail operation setting, you what? so what does it go to without this? I don't understand, I read that as normally you can take a frigging guess at what you will get, enable this handy feature for it to work as you would expect - but you will have to disable a load of other features and just to test your skills we use a double negative in the explanation.
« Last Edit: February 02, 2022, 10:55:11 am by Simon »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #10 on: February 02, 2022, 03:02:42 pm »
Please stop complaining.  I'm not going to respond to all that negativity. I get it, you don't like the datasheet, no need to point this out in every single post, especially given that most of the time you can't read.

Also, your question itself is not exactly the most clear either.

Effects of R2R setting are shown in the Table 45-19. It affects input common mode voltage. With R2R = 1 you get common mode input in the range 0.2V - VREF-0.2V. With R2R = 0 you get VCM = VREF/2-0.2V - VREF/2+0.2V.

Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #11 on: February 02, 2022, 03:33:49 pm »
I showed the text of the datasheet that describes this, that is the sum total in the ADC section about it. It makes it sound like I won't get to read the full input voltage range of 0-Vref unless I used it, which I am sure is not the case.

I take it as we are talking about differential input voltage differences/references? as even in the electrical characteristics it sounds pretty hairy. As far as I am aware any voltage on the micro is "common mode", all voltages have a common reference to ground right?

Or are they trying to say that when used in differential mode the minimum voltage of the two voltages measured must be in a certain voltage range?
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #12 on: February 02, 2022, 04:44:12 pm »
The ADC itself is fully differential. You can route both V+ and V- on the external pins. The common voltage on those pins is the parameter in question.Single-ended mode is achieved by grounding the V- input internally.

ADC will always convert the full scale range, but the accuracy (offset/linearity) would be worse at the ends of the range. Using R2R setting allows you  to get better results.

For most practical applications you won't see a difference, but there is no hard in just enabling R2R all the time.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #13 on: February 02, 2022, 05:23:31 pm »
Well if I enable R2R I cannot use other things like result accumulation so I guess it is a trade off in the complexity of getting single accurate result and doing your own filtering or using the hardware filtering. I'm trying to read the VDDANA/4 voltage which presumably is available for things like calibrations I may want to make but the results are drifting around quite a bit. I am going to setup a voltage source for it to read tomorrow so that I know what I am putting in and can read the converted value to check my setup.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #14 on: February 02, 2022, 05:39:28 pm »
What are your ADC settings? What is your reference?  Make sure you don't overclock the ADC.

And how much thing are drifting? Can you provide the ranges or values?
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #15 on: February 02, 2022, 07:32:04 pm »
Well I get a figure of around 2000 in 12 bit mode but it can jump by about 100 each way. I need to do a lot of averaging of the result anyway. The setup is pretty much the basic. I can report on those tomorrow when I am back at work.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #16 on: February 03, 2022, 08:22:00 am »
So I have a 12MHz clock (48/4) i's in 12 bit mode and everything is off in terms of additional functionality. The reference is the analogue supply at 3.3V and I have set SCALEDVDDCORE as the input which is the core voltage divided by 2. I believe the core is at 1.2V? I take a reading once a second, I get numbers between 1814 and 2118. so let's say 2000 on average:

2000 / 4095 x 3.3 = ~1.6V or around SCALEDVDDCORE /2, maybe that is what it is meant to be and not SCALEDVDDCORE /4 ? but setting SCALEDVDDANA gets the same numbers and should be about 3 times.

I'll put an actual voltage in today.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #17 on: February 03, 2022, 08:25:53 am »
Changing some of my code around gives a different result, around 730 with fluctuations in the lows 10's so I've obviously got a problem somewhere.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #18 on: February 03, 2022, 08:28:50 am »
Scaled VDDCORE is scaled by 1/4 for sure. It is better to provide your initialization code.
Alex
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8193
  • Country: fi
Re: [SAM] [ADC] register conundrums
« Reply #19 on: February 03, 2022, 09:50:02 am »
What is the source signal? Is it properly low impedance, either by opamp buffering, or if DC enough, just filtered with a capacitor of at very least 100nF?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #20 on: February 03, 2022, 10:32:54 am »
OK I have got it down to the minimum and now have 1004/5 as a result measureng VDDANA/4 which is pretty much 1/4 4095 which is the refence voltage VDDANA. It's still quite a few counts out but I assume that there is no massive promise on accuracy of the VDDANA/4 ? Or there is some source impedance there.

Code: [Select]
void ADC0_init()
{
REG_MCLK_APBCMASK |= 0x1 << 17 ;
REG_GCLK_PCHCTRL33 = ADC0_GCLK_GEN | 0x1 << 6 ; // Connect ADC0 to GCLK GEN and enable clock - see clock_config.h
REG_ADC0_CTRLB = 0x2 ;

// CTRLB ADC CLK pre-scaler

REG_ADC0_REFCTRL = 0x5 ;

// INPUTCTRL input control

REG_ADC0_INPUTCTRL = 0x1B ;


// CTRLA

REG_ADC0_CTRLA = 0x1 << 1 ; // enable ADC0
}



The mess this came from was:

adc.h

Code: [Select]

// channel selection bits
#define SCALEDVDDANA  0x1B // 1/4 of VDDANA
#define SCALEDVDDCORE 0x1A // 1/4 Vcore

// ADC 0 setup
void ADC0_init1() ;
void ADC0_init() ; // initialize and enable the ADC with the below settings (not complete)

#define ADC0_CLK_DIV 4 // may be any power of 2 from 2-256 resulting frequency must be between 160kHz and 16MHz

#define ADC0_Reference_Buffer_Offset_Compensation_Enable 0 // Reference Buffer Offset Compensation Enable CTRLB

#define ADC0_rail_to_rail_operation_enable 0 // enable rail to rail operation.

#define ADC0_Sampling_Time_Length 0 // extend sampling time beyond 1 clock cycle from 0 - 64 (cannot be used with above two options)

#define ADC0_Reference_Selection VDDANA // Reference Selection REFCTRL

#define ADC0_Init_POS_channel SCALEDVDDANA // use 0-11 or above def's

#define ADC0_Init_NEG_channel 0 // use 0-5

#define ADC0_Conversion_Result_Resolution 12 // 8, 10, 12 or 16 for averaging and oversampling

#define ADC0_Free_Running_Mode_Enable 0 // enable (1) disable free running mode

#define ADC0_Differential_Mode_Enable 0 // enable differential mode

#define ADC0_Digital_Correction_Logic_Enabled 0 // enable manual offset and gain corrections with values in register.

#define ADC0_samples_to_accumulate 1 // samples will be accumulated, number must always be a power of 2 from 1 - 1024

#define ADC0_Result_division 0 // right shifting of result use 0-7

#define ADD_REG_ADC0_CTRLA             (0x42004400UL) /**< \brief (ADC0) Control A */
#define ADD_REG_ADC0_CTRLB             (0x42004401UL) /**< \brief (ADC0) Control B */
#define ADD_REG_ADC0_REFCTRL           (0x42004402UL) /**< \brief (ADC0) Reference Control */
#define ADD_REG_ADC0_EVCTRL            (0x42004403UL) /**< \brief (ADC0) Event Control */
#define ADD_REG_ADC0_INTENCLR          (0x42004404UL) /**< \brief (ADC0) Interrupt Enable Clear */
#define ADD_REG_ADC0_INTENSET          (0x42004405UL) /**< \brief (ADC0) Interrupt Enable Set */
#define ADD_REG_ADC0_INTFLAG           (0x42004406UL) /**< \brief (ADC0) Interrupt Flag Status and Clear */
#define ADD_REG_ADC0_SEQSTATUS         (0x42004407UL) /**< \brief (ADC0) Sequence Status */
#define ADD_REG_ADC0_INPUTCTRL         (0x42004408UL) /**< \brief (ADC0) Input Control */
#define ADD_REG_ADC0_CTRLC             (0x4200440AUL) /**< \brief (ADC0) Control C */
#define ADD_REG_ADC0_AVGCTRL           (0x4200440CUL) /**< \brief (ADC0) Average Control */
#define ADD_REG_ADC0_SAMPCTRL          (0x4200440DUL) /**< \brief (ADC0) Sample Time Control */
#define ADD_REG_ADC0_WINLT             (0x4200440EUL) /**< \brief (ADC0) Window Monitor Lower Threshold */
#define ADD_REG_ADC0_WINUT             (0x42004410UL) /**< \brief (ADC0) Window Monitor Upper Threshold */
#define ADD_REG_ADC0_GAINCORR          (0x42004412UL) /**< \brief (ADC0) Gain Correction */
#define ADD_REG_ADC0_OFFSETCORR        (0x42004414UL) /**< \brief (ADC0) Offset Correction */
#define ADD_REG_ADC0_SWTRIG            (0x42004418UL) /**< \brief (ADC0) Software Trigger */
#define ADD_REG_ADC0_DBGCTRL           (0x4200441CUL) /**< \brief (ADC0) Debug Control */
#define ADD_REG_ADC0_SYNCBUSY          (0x42004420UL) /**< \brief (ADC0) Synchronization Busy */
#define ADD_REG_ADC0_RESULT            (0x42004424UL) /**< \brief (ADC0) Result */
#define ADD_REG_ADC0_SEQCTRL           (0x42004428UL) /**< \brief (ADC0) Sequence Control */
#define ADD_REG_ADC0_CALIB             (0x4200442CUL) /**< \brief (ADC0) Calibration */

#define ADD_REG_ADC_OFFSET 0X400




static inline void ADC_start_conversion(uint8_t channel)
{
register8( ADD_REG_ADC0_SWTRIG + channel * ADD_REG_ADC_OFFSET ) = 0x1 << 1 ;
}

static inline void ADC_POS_channel_select( uint8_t adc_ch,  uint8_t adc_pin)
{
register16( ADD_REG_ADC0_INPUTCTRL + adc_ch * ADD_REG_ADC_OFFSET ) &= 0xFFFF0000 | adc_pin ;
}


static inline void ADC_POS_NEG_channel_select( uint8_t adc_ch,  uint8_t pos_pin,  uint8_t neg_pin )
{
register16( ADD_REG_ADC0_INPUTCTRL + adc_ch * ADD_REG_ADC_OFFSET ) = pos_pin | neg_pin << 8 ;
}

static inline uint16_t ADC_result_ret( uint8_t adc_ch)
{
return register16( ADD_REG_ADC0_RESULT + adc_ch * ADD_REG_ADC_OFFSET )  ;
}

static inline uint16_t ADC0_result_ret()
{
return REG_ADC0_RESULT   ;
}



adc.c

Code: [Select]
void ADC0_init()
{
REG_MCLK_APBCMASK |= 0x1 << 17 ;
REG_GCLK_PCHCTRL33 = ADC0_GCLK_GEN | 0x1 << 6 ; // Connect ADC0 to GCLK GEN and enable clock - see clock_config.h

// CTRLB ADC CLK pre-scaler

#if (ADC0_CLK_DIV == 2)
REG_ADC0_CTRLB = 0x0 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 4)
REG_ADC0_CTRLB = 0x1 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 8)
REG_ADC0_CTRLB = 0x2 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 16)
REG_ADC0_CTRLB = 0x3 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 32)
REG_ADC0_CTRLB = 0x4 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 64)
REG_ADC0_CTRLB = 0x5 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 128)
REG_ADC0_CTRLB = 0x6 ;
#define ADC0_CLK_OK
#endif
#if (ADC0_CLK_DIV == 256)
REG_ADC0_CTRLB = 0x7 ;
#define ADC0_CLK_OK
#endif
#ifndef ADC0_CLK_OK
#warning ADC0 clock precaler incorrectly defined see adc_config.h
#endif

// ADC0 REFCTRL

#if (ADC0_Reference_Selection == VDDANA)
#define ADC0_REFCTRL_REFSEL 0x5
#endif

REG_ADC0_REFCTRL = ADC0_REFCTRL_REFSEL | ADC0_Reference_Buffer_Offset_Compensation_Enable << 7 ;

// INPUTCTRL input control

REG_ADC0_INPUTCTRL = ADC0_Init_POS_channel | ADC0_Init_NEG_channel << 8 ;

// CTRLC

#if (ADC0_Conversion_Result_Resolution == 12)
#define ADC0_RESSEL_s 0x0
#endif
#if (ADC0_Conversion_Result_Resolution == 16)
#define ADC0_RESSEL_s 0x1
#endif
#if (ADC0_Conversion_Result_Resolution == 10)
#define ADC0_RESSEL_s 0x2
#endif
#if (ADC0_Conversion_Result_Resolution == 8)
#define ADC0_RESSEL_s 0x3
#endif
#ifndef ADC0_RESSEL_s
#warning incorrect  resolution setting
#endif

REG_ADC0_CTRLC = ADC0_rail_to_rail_operation_enable << 7 | ADC0_RESSEL_s << 4 | ADC0_Free_Running_Mode_Enable << 2 | ADC0_Differential_Mode_Enable <<  0 ;

#if ( ( ADC0_rail_to_rail_operation_enable == 1 ) && ( ADC0_Reference_Buffer_Offset_Compensation_Enable == 0 ) )
#warning ADC0_Reference_Buffer_Offset_Compensation_Enable must be turned on to use ADC0_rail_to_rail_operation_enable
#endif

// AVGCTRL averaging control

#if ( ADC0_samples_to_accumulate == 1 )
#define ADC0_samples 0
#endif
#if ( ADC0_samples_to_accumulate == 2 )
#define ADC0_samples 1
#endif
#if ( ADC0_samples_to_accumulate == 4 )
#define ADC0_samples 2
#endif
#if ( ADC0_samples_to_accumulate == 8 )
#define ADC0_samples 3
#endif
#if ( ADC0_samples_to_accumulate == 16 )
#define ADC0_samples 4
#endif
#if ( ADC0_samples_to_accumulate == 32 )
#define ADC0_samples 5
#endif
#if ( ADC0_samples_to_accumulate == 64 )
#define ADC0_samples 6
#endif
#if ( ADC0_samples_to_accumulate == 128 )
#define ADC0_samples 7
#endif
#if ( ADC0_samples_to_accumulate == 256 )
#define ADC0_samples 8
#endif
#if ( ADC0_samples_to_accumulate == 512 )
#define ADC0_samples 9
#endif
#if ( ADC0_samples_to_accumulate == 1024 )
#define ADC0_samples 10
#endif
#ifndef ADC0_samples
#warning ADC0 samples accumulator incorrectly defined see adc_config.h
#endif

#if (ADC0_Conversion_Result_Resolution == 16)
REG_ADC0_AVGCTRL = ADC0_samples | ADC0_Result_division << 4 ;
#endif



// SAMPCTRL sampling control

REG_ADC0_SAMPCTRL =  ADC0_Sampling_Time_Length | ADC0_Reference_Buffer_Offset_Compensation_Enable << 7 ;

#if ( ADC0_Sampling_Time_Length && ADC0_Reference_Buffer_Offset_Compensation_Enable )
#warning sampling time length cannot be used with reference buffer offset compensation (therefore rail to rail operation must also be disabled )
#endif

// CTRLA

REG_ADC0_CTRLA = 0x1 << 1 ; // enable ADC0
}

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #21 on: February 03, 2022, 10:49:30 am »
looks like I didn't understand how the pre-processor works and it fails on the ctrlb register macros to set the correct clock setting
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: [SAM] [ADC] register conundrums
« Reply #22 on: February 03, 2022, 11:24:35 pm »
1/4 divider is not the most accurate, and it is not characterized.

You need to select MUXNEG=GND (not sure if it is really needed for a single-ended mode, but will not hurt) and you are not writing anything into CALIB register.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #23 on: February 04, 2022, 07:58:42 am »
I didn't think it would be. Connecting the negative input to GND does not make any difference in non diff mode, but no I've not loaded any calibration and I guess there is a reason why that calibration is available.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17832
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [SAM] [ADC] register conundrums
« Reply #24 on: February 04, 2022, 08:27:47 am »
Well my VDDANA/4 has now moved from 1004 to 1006, slight improvement towards the expected 1023 :)

Code: [Select]

#define register8(x)  ( *(volatile uint8_t * )( x ) )

#define REG_ADC0_CAL register8(0x806020)

REG_ADC0_CALIB = (uint16_t) ( ( REG_ADC0_CAL & 0x7 ) << 8 | ( REG_ADC0_CAL & 0b00111000 ) >> 3 ) ;


I take it I am OK to treat the section of the 64 bit calibration data that I want as an 8 bit register.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf