Skip to content

Commit df01520

Browse files
Torgeir Bjoernvoldcmaglie
authored andcommitted
Various fix to ADC and DAC.
1 parent 3c996b2 commit df01520

File tree

4 files changed

+125
-53
lines changed

4 files changed

+125
-53
lines changed

cores/arduino/wiring.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -93,46 +93,42 @@ void init( void )
9393

9494
// Initialize Analog Controller
9595
// Setting clock
96+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
97+
9698
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
97-
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
99+
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
98100
GCLK_CLKCTRL_CLKEN ;
99101

100-
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV128 | // Divide Clock by 512.
101-
ADC_CTRLB_RESSEL_10BIT; // Result on 10 bits
102+
while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
103+
104+
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 | // Divide Clock by 512.
105+
ADC_CTRLB_RESSEL_10BIT; // 10 bits resolution as default
106+
107+
ADC->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length
108+
109+
while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
102110

103111
ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground)
104112

105113
// Averaging (see table 31-2 p.816 datasheet)
106-
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_2 | // 2 samples
107-
ADC_AVGCTRL_ADJRES(0x01ul); // Adjusting result by 1
114+
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_64 | // 64 samples
115+
ADC_AVGCTRL_ADJRES(0x04ul); // Adjusting result by 4
108116

109-
ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_AREFA; // RReference AREFA (pin AREF) [default]
117+
while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
110118

111-
ADC->CTRLA.bit.ENABLE = 1; // Enable ADC
112-
while( ADC->STATUS.bit.SYNCBUSY == 1 )
113-
{
114-
// Waiting for synchroinization
115-
}
119+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
120+
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
116121

117122
// Initialize DAC
118123
// Setting clock
124+
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY );
119125
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC
120-
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
126+
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
121127
GCLK_CLKCTRL_CLKEN ;
122128

123-
129+
while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
124130
DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
125-
DAC_CTRLB_EOEN; // External Output Enable (Vout)
126-
DAC->DATA.reg = 0x3FFul;
127-
128-
// Enable DAC
129-
DAC->CTRLA.bit.ENABLE = 1;
130-
131-
while(DAC->STATUS.bit.SYNCBUSY != 0)
132-
{
133-
// Waiting for synchronization
134-
}
135-
131+
DAC_CTRLB_EOEN ; // External Output Enable (Vout)
136132
}
137133

138134
#ifdef __cplusplus

cores/arduino/wiring_analog.c

Lines changed: 100 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,77 +28,144 @@ static int _writeResolution = 8;
2828

2929
void analogReadResolution( int res )
3030
{
31-
_readResolution = res ;
31+
switch ( res )
32+
{
33+
case 12:
34+
while( ADC->STATUS.bit.SYNCBUSY == 1 );
35+
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
36+
break;
37+
case 8:
38+
while( ADC->STATUS.bit.SYNCBUSY == 1 );
39+
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
40+
break;
41+
default:
42+
while( ADC->STATUS.bit.SYNCBUSY == 1 );
43+
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
44+
break;
45+
}
46+
_readResolution = res ;
3247
}
3348

3449
void analogWriteResolution( int res )
3550
{
36-
_writeResolution = res ;
51+
_writeResolution = res ;
3752
}
3853

3954
static inline uint32_t mapResolution( uint32_t value, uint32_t from, uint32_t to )
4055
{
41-
if ( from == to )
56+
if ( from == to )
4257
{
43-
return value ;
58+
return value ;
4459
}
4560

46-
if ( from > to )
61+
if ( from > to )
4762
{
48-
return value >> (from-to) ;
63+
return value >> (from-to) ;
4964
}
50-
else
65+
else
5166
{
52-
return value << (to-from) ;
67+
return value << (to-from) ;
5368
}
5469
}
5570

5671
void analogReference( eAnalogReference ulMode )
5772
{
58-
// ATTENTION : On this board the default is not 5volts or 3.3volts BUT 1volt
59-
73+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
6074
switch ( ulMode )
6175
{
62-
case AR_DEFAULT:
6376
case AR_INTERNAL:
64-
default:
65-
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
77+
case AR_INTERNAL2V23:
78+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
79+
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/1.48 VDDANA = 1/1.48* 3V3 = 2.2297
6680
break;
6781

6882
case AR_EXTERNAL:
83+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
6984
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
7085
break;
86+
87+
case AR_INTERNAL1V0:
88+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
89+
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; // 1.0V voltage reference
90+
break;
91+
92+
case AR_INTERNAL1V65:
93+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
94+
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
95+
break;
96+
97+
case AR_DEFAULT:
98+
default:
99+
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
100+
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
101+
break;
71102
}
72103
}
73104

74105
uint32_t analogRead( uint32_t ulPin )
75106
{
76107
uint32_t valueRead = 0;
77-
pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType);
78108

79-
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;
109+
if (ulPin < A0) ulPin += A0;
80110

81-
// Start conversion
82-
ADC->SWTRIG.bit.START = 1;
111+
if (ulPin == A0) // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
112+
{
113+
while ( DAC->STATUS.bit.SYNCBUSY == 1 );
114+
DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
115+
//DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
116+
while ( DAC->STATUS.bit.SYNCBUSY == 1 );
117+
}
83118

84-
while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 )
119+
if (ulPin != TEMP)
120+
{
121+
pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType);
122+
123+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
124+
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input
125+
}
126+
else
85127
{
86-
// Waiting for a complete conversion and complete synchronization
128+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
129+
ADC->INPUTCTRL.bit.MUXPOS = ulPin & 0x7F; // Selection for the positive ADC input
130+
//ADC->INPUTCTRL.bit.MUXPOS = 0x18; // Selection for the positive ADC input
131+
132+
SYSCTRL->VREF.bit.TSEN = 0x1; // Temperature sensor is enabled and routed to an ADC input channel.
87133
}
88134

89-
// Store the value
90-
valueRead = ADC->RESULT.reg;
135+
// Control A
136+
/*
137+
* Bit 1 – ENABLE: Enable
138+
* 0: The ADC is disabled.
139+
* 1: The ADC is enabled.
140+
* Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The
141+
* value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register
142+
* (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete.
143+
*
144+
* Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be
145+
* configured. The first conversion after the reference is changed must not be used.
146+
*/
147+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
148+
ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC
149+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
150+
151+
// Start conversion
152+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
153+
ADC->SWTRIG.bit.START = 1;
91154

92155
// Clear the Data Ready flag
93156
ADC->INTFLAG.bit.RESRDY = 1;
94157

95-
// Flush the ADC for further conversions
96-
//ADC->SWTRIG.bit.FLUSH = 1;
158+
// Start conversion again, since The first conversion after the reference is changed must not be used.
159+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
160+
ADC->SWTRIG.bit.START = 1;
97161

98-
while( ADC->STATUS.bit.SYNCBUSY == 1 || ADC->SWTRIG.bit.FLUSH == 1 )
99-
{
100-
// Waiting for synchronization
101-
}
162+
// Store the value
163+
while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete
164+
valueRead = ADC->RESULT.reg;
165+
166+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
167+
ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC
168+
while ( ADC->STATUS.bit.SYNCBUSY == 1 );
102169

103170
return valueRead;
104171
}
@@ -124,7 +191,12 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
124191
return;
125192
}
126193

127-
DAC->DATA.reg = ulValue & 0x3FF; // Dac on 10 bits.
194+
while ( DAC->STATUS.bit.SYNCBUSY == 1 );
195+
DAC->DATA.reg = ulValue & 0x3FF; // DAC on 10 bits.
196+
while ( DAC->STATUS.bit.SYNCBUSY == 1 );
197+
DAC->CTRLA.bit.ENABLE = 0x01; //Enable ADC
198+
while ( DAC->STATUS.bit.SYNCBUSY == 1 );
199+
return ;
128200
}
129201

130202
if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )

cores/arduino/wiring_analog.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ typedef enum _eAnalogReference
3232
{
3333
AR_DEFAULT,
3434
AR_INTERNAL,
35-
AR_EXTERNAL
35+
AR_EXTERNAL,
36+
AR_INTERNAL1V0,
37+
AR_INTERNAL1V65,
38+
AR_INTERNAL2V23
3639
} eAnalogReference ;
3740

3841

variants/arduino_zero/variant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static const uint8_t A2 = PIN_A2 ;
9292
static const uint8_t A3 = PIN_A3 ;
9393
static const uint8_t A4 = PIN_A4 ;
9494
static const uint8_t A5 = PIN_A5 ;
95+
static const uint8_t TEMP = 0x98 ;
9596
#define ADC_RESOLUTION 12
9697

9798
/*

0 commit comments

Comments
 (0)