Trying to get my head around the Atmel Microchip XMEGA ADC.
Useful References
[1] http://ww1.microchip.com/downloads/en/Appnotes/00002535A.pdf
This picture seems to imply that all 16 inputs ADC0-ADC15 can be switched
Reference [1] "In devices with two ADCs, the inputs can only be connected to the corresponding port. Meaning that ADCA can be connected only to PORT A, and ADC B can be connected only to PORT B."
The XMEGA 128A1 has two ADCs
PROBLEM SOME ADC PINS READ WRONG
The ATXMEGA128 has 16 analogue inputs. These are on Port A and Port B.
The first indication of the problem was that ADC12 which monitored the 5V rail was reading high. I lifted the top resistor of the divider and so there was now a 5K2 resistor to GND. Using a multimeter, it read 1.0V when I was expecting 0V.
I put a post on the BASCOM forum.
https://www.mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&p=81048#81048
and someone asked had i considered JTAG.
DOES JTAG INFLUENCE THIS?
A response to the MCSELEC forum post mentions JTAG Fuses. I wonder.
What Pins?
JTAG Fuses?
Page 58 of the datasheet shows that indeed the JTAG uses pins on port B.
Now I read the fuses
I note FUSEBYTE0 mentions JTAG But what does it mean?
XMEGA A1U Datasheet
7.4 Fuses and Lock bits
The fuses are used to configure important system functions, and can only be written from an external programmer. The application software can read the fuses. The fuses are used to configure reset sources such as brownout detector and watchdog, startup configuration, JTAG enable, and JTAG user ID.
The lock bits are used to set protection levels for the different flash sections (that is, if read and/or write access should be blocked). Lock bits can be written by external programmers and application software, but only to stricter protection levels.
Chip erase is the only way to erase the lock bits. To ensure that flash contents are protected even during chip erase, the lock bits are erased after the rest of the flash memory has been erased.
An unprogrammed fuse or lock bit will have the value one, while a programmed fuse or lock bit will have the value zero.
Both fuses and lock bits are reprogrammable like the flash program memory
7.13 JTAG Disable
It is possible to disable the JTAG interface from the application software. This will prevent all external JTAG access to the device until the next device reset or until JTAG is enabled again from the application software. As long as JTAG is disabled, the I/O pins required for JTAG can be used as normal I/O pins.
So I add a line "DISABLE JTAG"And that my friends fixed the problem!
This is my test program
'*******************************************************************************
' FILENAME:
ATXMEGA128A1 ADC Test x.bas
'
' PROCESSOR:
ATXMEGA128A1
' CLOCK:
16Mhz XTAL
' TITLE:
' BOARD:
0420-04 and 0420-01
' MODIFIED:
29-NOV-2021
' AUTHOR:
Frank Thomson
'*******************************************************************************
$regfile = "xm128A1Udef.dat" '"xm128A1Udef.dat" ' "C:\MCS\BASCAVR2082\DAT\xm128A1Udef.dat"
$framesize = 200 ' After global
variables then after unused SRAM, grows bottom up, string conversion routines
(PRINT, LCD, INPUT) require a buffer in SRAM
$swstack = 200 ' ISR routine
parameters and grow top down
$hwstack = 200 ' Return address
after routine call (SUB, FUNCTION, GOSUB) and grow top down
$crystal = 16000000
'Config Osc = Enabled , 32mhzosc = Enabled ' enable 2 MHz and 32 MHz internal
oscillators
'Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc =
1_1
Config osc = disabled , EXTOSC = enabled , 32KHZOSC=DISABLED, pllosc = enabled , range = 12MHZ_16MHZ , startup = XTAL_16KCLK , pllsource = extclock , pllmul = 1
Config Sysclock = PLL , Prescalea = 1 , Prescalebc = 1_1
Disable Jtag <-- This is the fix
'$sim
' Comment this out for real program
' INITIALIZE HARDWARE
'PORT A has the first 8 Analogue inputs.
' Can only be read with ADCA
'
TypRead
'PORT A.0 - 0 ADC0
- 1 Connects to GND 0R
' A.1 - 0
ADC1 13 16k to GND
' A.2 - 0
ADC2 22 16k to GND
' A.3 - 0
ADC3 19 16k to GND
' A.4 - 0
ADC4 17 16k to GND
' A.5 - 0
ADC5 14 16k to GND
' A.6 - 0
ADC6 34 24k to GND
' A.7 - 1
ADC7 34 24k to GND
Config Porta = &B00000000 ' All IN
Porta = &B00000000
' PORT B Has another 8 ADCs They can only be read with ADCB
' DDR TypRead
'PORT B.0 - 0 ADC8
7 Test Point TP126 (Open Circuit)
' B.1 - 0
ADC9 1189 RF
Power Detector via divider 2k4 x 750R to GND
' B.2 - 1 ADC10
- 437 DAC1 output Not normally used for
ADC
' B.3 - 0
ADC11 324 Test Point TP127 (Open Circuit)
' B.4 - 0
ADC12 1613 8K2 to GND
' B.5 - 0
ADC13 841 Adjustable regulator via 12k x 3k0
to GND
' B.6 - 0
ADC14 1482 12V input mon via divider 18k x 1k5 to GND
' B.7 - 0
ADC15 1652 3V3 rail mon via divider 12k x 3k0
to GND
'
76543210
Config Portb = &B00000100
Portb = &B00000000
' PORTS C, D, E, F, H, J, K, Q Default to ALL INPUTS
' Except Port D which has a LED
'PORT D.0 - 0
0 LED SPARE 2
' D.1 - 0 0 LED
SPARE 1
' D.2 - 0 0 LED
FAIL
' D.3 - 0 0 LED
STATUS
' D.4 - 0 0 LED
TESTING
' D.5 - 0 0 LED
DEVICE
' D.6 - 0 0
Reserved for USB N
' D.7 - 0 0
Reserved for USB N
'
76543210
Config PortD = &B00000011
PortD = &B00000000
'---- INITIALISE COMMS
---------------------------------------------------------------------
Config Com5 = 9600 , mode = ASYNCHRONEOUS, Parity = None , Stopbits = 1 , Databits = 8
Open "COM5:" For Binary As #6
Config Serialin6 = Buffered , Size = 10
'----- INITIALISE ADC
----------------------------------------------------------------------
' The XMEGA128A1 has two Analogue to Digital Converters.
' Inputs ADC0 to 7
can only be routed by the MUX register to ADCA and 8-15 to ADCB.
' There are 4 channels - For these tests we will only use
Channel 0
' Prescaler= 4, 8, 16, 32, 64, 128, 256 and 512
' DIFFERENTIAL MODE
'Config Adca = Single , Convmode = signed , Resolution =
12bit , Dma = Off , Reference = Int1v , Event_mode = None , Prescaler = 512 ,
Ch0_gain = 1 , Ch0_inp = diff , Mux0 = &B0000000, Ch1_gain = 1 , Ch1_inp =
INTERNAL , Mux1 = &B1_000 , Ch2_gain = 1 , Ch2_inp = Single_ended , Mux2 =
&B10000000 , Ch3_gain = 1 , Ch3_inp = DIFF , Mux3 = &B1100000
'Config AdcB = Single , Convmode = signed , Resolution =
12bit , Dma = Off , Reference = Int1v , Event_mode = None , Prescaler = 512 ,
Ch0_gain = 1 , Ch0_inp = diff , Mux0 = &B0000000, Ch1_gain = 1 , Ch1_inp =
INTERNAL , Mux1 = &B1_000 , Ch2_gain = 1 , Ch2_inp = Single_ended , Mux2 =
&B10000000 , Ch3_gain = 1 , Ch3_inp = DIFF , Mux3 = &B1100000
' SINGLE ENDED
Config Adca = Single , Convmode = signed , Resolution = 12bit , Dma = Off , Reference = Int1v , Event_mode = None , Prescaler = 512 , Ch0_gain = 1 , Ch0_inp = SINGLE_ENDED , Mux0 = &B0000000, Ch1_gain = 1 , Ch1_inp = INTERNAL , Mux1 = &B1_000 , Ch2_gain = 1 , Ch2_inp = Single_ended , Mux2 = &B10000000 , Ch3_gain = 1 , Ch3_inp = DIFF , Mux3 = &B1100000
Config AdcB = Single , Convmode = signed , Resolution = 12bit , Dma = Off , Reference = Int1v , Event_mode = None , Prescaler = 512 , Ch0_gain = 1 , Ch0_inp = SINGLE_ENDED , Mux0 = &B0000000, Ch1_gain = 1 , Ch1_inp = INTERNAL , Mux1 = &B1_000 , Ch2_gain = 1 , Ch2_inp = Single_ended , Mux2 = &B10000000 , Ch3_gain = 1 , Ch3_inp = DIFF , Mux3 = &B1100000
' MUX is
' See Table 28-16 page 362 of XMEGA Manual
"Differential without gain"
' 7 6 5 4 3 2 1
0
' / | | | | \ \ \
MUXNEG DIFFERENTIAL
SINGLE_ENDED
' Not Positive \
\ \Negative Side MUXNEG is
IGNORED
' Used Side
of Of the ADC
' ADC 0 0 0 = ADC0Pin
' = Channel
' Number 1 0 1 = PAD Ground
'
1 1 0 = Reserved
'
1 1 1 = Internal Ground
'
'-----DIMENSION VARIABLES-------------------------------------------------------------------
dim k_b as byte ' Used to hold input
Dim LEDcounter as word
dim i as byte
dim mux as byte
Dim myADCX as integer
dim MUXNEG as byte : MUXNEG = &b00000101 ' See table
above.
'-----MAIN PROGRAM
START---------------------------------------------------------------------
portd.0 = 1 ' LED
SPARE 2 ON
Print #6 ,
print #6, "AT X Mega 128A1U ADC
Program";
loopforever:
k_b = Inkey(#6) ' Get a byte from the uart.
Loop keeps running
if k_b > 0 Then ' we have a character
print #6, chr(k_b) 'echo it
' ----READ ALL 16
ADCs------------------------------------------
For i = 0 to 15
mux = i * 8
mux = mux and &b01111000 ' Make sure LS 3 bits are zero
mux = mux OR MUXNEG ' Add in the LS 3
bits
if i <= 7 then
myADCX = getadc(ADCA, 0 , mux)
' ADC inputs 0-7 can be routed to ADCA only
else
myADCX = getadc(ADCB, 0 , mux)
' ADC inputs 8-15 can be routed to ADCB only
end if
'Print #6,
i ; " , "; myADCX
Print #6, myADCX
Next i
end if
' Heartbeat LED
LEDcounter =
LEDcounter + 1
if LEDcounter >= 60000 then
toggle portd.1 'FAIL LED ON OFF
LEDcounter = 0
end if
goto loopforever
|
U
|
No U
|
[AU] SINGLE_ENDED UNSIGNED
|
Read A from A & Subtract PA0
Read B from A & subtract PA0
|
Read A from A & Subtract PA0
Read B from B & subtract PA0
|
ADC0-7b Port A
|
PA0=0V reads 166
PA1=0 PA1=1V =
|
PA0 0V reads 138
PA1=0 reads 157
=1V=4095
|
ADC8-15 Port B
|
11 PB3=0V Reads 182
=1V 4095
All show up on ADC
A. ADCB is crap
|
8 PB0 0V = 1V = 4095
11 PB3=0V = 1 @1V=2047
These show up on ADCB
as both 0-7 and 8-15
|
|
|
|
[AS] SINGLE ENDED SIGNED
|
Read A from A
Read B from A
|
Read A from A
Read B from B
|
ADC0-7b Port A
|
PA0=0V reads -10
PA1=0V= @1=2047
|
ON ADCA
PA0=0V Reads -3
PA1=0V = -3 @1=2047
|
ADC8-15 Port B
|
Show up on ADCA
08 PB0=0V = 5 @1V= 2047
11 PB3=0V =0 @1V = 2047
|
ON ADCB
8 PB0=0V = 0 @1V=2047
11PB3=0V = 1 @1V=2047
|
|
|
|
Signed DIFFERENTIAL
muxNeg = 000 as PortA.0
|
|
Read A from A.
Read B from B but unsure how to correct
|
ADC0-7b Port A
|
ADC A Works. -? To 2047
0V in read about -6
|
PA0=0V reads -1
PA1=0V = 0 @1V=2047
|
ADC8-15 Port B
|
ADC A 8-15 seems to
work.
0V in read about -6
ADCB never seems to have anything sensible.
All read 600-900
|
8 PB0=0V= -530 @1V=+1850
11PB3=1V= @1V=-2048
Note negatives
This is weird.
|
Signed DIFFERENTIAL
muxNeg = 111 Internal Ground
|
|
|
ADC0-7b Port A
|
ADC A -? To +2047. With 0V in, Read about -28
|
PA0 reads -1
|
ADC8-15 Port B
|
ADC A 8-15 seems to
work.
ADCB never seems to have anything sensible
|
Results show up on ADCB
08 PB0 0V = -522 1V = 1737
Note 1737 + 522 = 2259 ???
|
|
|
Note with MuxNex
set to 111, the registers read back 011 = ADC3 pin
|
|
|
|
PROBLEM: EEPROM IS NOT BEING RETAINED
XMEGA128A1U
Is it a Fuse issue?
Fuse Byte 0 OxFF JTAG UID So we assume no
Fuse Byte 1 0x00 Watchdog stuff - We assume no
Fuse Byte 2 0xFF 6 BOOTRST 5 TOSCSEL - We assume no
Fuse Byte 3
Fuse Byte 4 - no
Fuse Byte 5 Bit 3 EESAVE
Bit 3 – EESAVE: EEPROM is Preserved through the Chip Erase
A chip erase command will normally erase the flash, EEPROM, and internal SRAM. If this fuse is programmed, the
EEPROM is not erased during chip erase. This is useful if EEPROM is used to store data independently of the
software revision.
Table 4-8. EEPROM preserved through chip erase.
Changes to the EESAVE fuse bit take effect immediately after the write timeout elapses. Hence, it is possible to
update EESAVE and perform a chip erase according to the new setting of EESAVE without leaving and reentering
programming mode
7654 3210
37 = 0011 0111
1 1= EEPROM Erased during chip erase
0 0= Preserved