ADC with internal 2.56v reference on -24x

Discussion specific to the 24-pin ZX microcontrollers, e.g. ZX-24r, ZX-24s and ZX-24t.
GTBecker
Posts: 616
Joined: 17 January 2006, 19:59 PM
Location: Cape Coral

Post by GTBecker »

Don, an oddity of PortBit has arisen:

Code: Select all

Option TargetDevice ZX24x

	const p1 as byte = 13
	const p2 as byte = A.7
	dim p3 as byte = 13		' PortBit error from this var
	dim p4 as byte = A.7

Sub Main()
	const p5 as byte = 13
	const p6 as byte = A.7
	dim p7 as byte = 13
	dim p8 as byte = A.7

	debug.print cstr(PortBit(13))
	debug.print
	debug.print cstr(PortBit(p1))
	debug.print cstr(PortBit(p2))
	debug.print cstr(PortBit(p3))	' ***
	debug.print cstr(PortBit(p4))
	debug.print cstr(PortBit(p5))
	debug.print cstr(PortBit(p6))
	debug.print cstr(PortBit(p7))
	debug.print cstr(PortBit(p8))
End Sub
Result:

Code: Select all

Verification complete.
135

135
135
13
135
135
135
135
135
When the PortBit argument is a module level dim'd pin number, no composite conversion occurs.

Edit: Another instance shows that it can happen with Const, too.
Tom
GTBecker
Posts: 616
Joined: 17 January 2006, 19:59 PM
Location: Cape Coral

Post by GTBecker »

Further:

Code: Select all

Option TargetDevice ZX24x
   const p1 as byte = 13
   const p2 as byte = A.7
   dim p3 as byte = 13      ' PortBit error from this var
   dim p4 as byte = A.7

Sub Main()
   const p5 as byte = 13
   const p6 as byte = A.7
   dim p7 as byte = 13
   dim p8 as byte = A.7 
   
   debug.print cstr(doPortPin(13))
   debug.print
   debug.print cstr(doPortPin(p1))
   debug.print cstr(doPortPin(p2))
   debug.print cstr(doPortPin(p3))   ' ***
   debug.print cstr(doPortPin(p4))
   debug.print cstr(doPortPin(p5))
   debug.print cstr(doPortPin(p6))
   debug.print cstr(doPortPin(p7))
   debug.print cstr(doPortPin(p8))
End Sub

Function doPortPin(byval pin as byte) as byte
    doPortPin = PortBit(pin)
End Function
Result:

Code: Select all

Verification complete.
13

13
135
13
135
13
135
13
135
Tom
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

GTBecker wrote:When the PortBit argument is a module level dim'd pin number, no composite conversion occurs.
Thanks. I am able to reproduce the problem here. You can work around the problem if you include at least one instance of calling GetPin() or PutPin() using a physical pin number or a variable whose value is not known at compile time. For example:

Code: Select all

dim p3 as byte = 13
Dim b as Byte

Sub Main()
   b = GetPin(p3)
   debug.print cstr(PortBit(p3))
End Sub
- Don Kinzer
GTBecker
Posts: 616
Joined: 17 January 2006, 19:59 PM
Location: Cape Coral

Post by GTBecker »

I believe I've settled on a high-rate ADC solution - actually two.

Since the input in the project can include zero volts, this code corrects the zero-volt input (often offset by several tens of mV) via one of two methods. One method converts a pin connected to the ground plane and subtracts that value from the input conversion; the other uses differential ADC mode to effectively achieve the same result, but at half the resolution - but also at a faster rate since no time is required to convert the grounded pin.

I've placed the ADC setup code in InitADC(), run once; function readADC(pin) can then be called as required. Differential mode can select A.0 through A.3 as the negative input or, with a different CONVMODE setting in Register.ADCA_CTRLB, A.4 through A.7. I chose and grounded A.1 since A.0 can be used as an external vRef - although I continue to have some difficulty with that mode when trying to use Vcc as vRef (see edit below). I've reverted to Vcc/1.6 vRef.

The single-ended method converts at ~57kHz; the differential method converts at ~83kHz.

Code: Select all

'	ZX-24x

#define Differential

const pinInput as Byte = A.7	' ZX-24x pin 14
const pinVcc as byte = A.0		' 20	' Vcc reference
const pinZero as Byte = A.1		' 19	' 0v reference
const Vcc as single = 3.25
const vref as Single = Vcc / 1.6

	#ifdef Differential
		const fs as single = 4096.0 / 2.0	' +/-2048
	#else
		const fs as single = 4096.0
	#endif

dim SpinCount as long, ivalp1 as integer
dim ReadSpinTaskStack(1 to 100) as byte

Sub Main()
	dim StartCount as long, StopCount as long, ivalp2 as integer
	CallTask ReadSpinTask, ReadSpinTaskStack
	do
		Atomic
			Startcount = SpinCount
		End Atomic
		Call Sleep(1.0)
		Atomic
			ivalp2 = ivalp1		' copy ival from module level
			StopCount = SpinCount
		End Atomic
		Debug.Print "Loops/Sec= "; CStr(StopCount - StartCount); " ival= "; cstr(ivalp2); " volts= "; fmt(vref * csng(ivalp2) / fs, 2)
	loop
End Sub

Sub ReadSpinTask()
    Dim ival as Integer
	Call InitADC()
	Do 
	#ifdef Differential
		ival = readADC(pinInput)
	#else
		ival = readADC(pinInput) - readADC(pinZero)	' 0v offset correction
	#endif
		Atomic
			ivalp1 = ival		' copy ival to module level 
			SpinCount = SpinCount + 1
		End Atomic
		Call Sleep(0)
    Loop
End Sub

Sub InitADC()
    Register.ADCA_PRESCALER = 2		' divide-by-16 
	#ifdef Differential
		Register.ADCA_CTRLB = &H10		' differential signed
		Register.ADCA_CH0_CTRL = &H02
	#else
		Register.ADCA_CTRLB = &H00		' single-ended unsigned
		Register.ADCA_CH0_CTRL = &H01
	#endif
    Register.ADCA_REFCTRL = &H10	' vref= Vcc/1.6 = 2.06v
    Register.ADCA_CH0_INTFLAGS = &H01    ' clear flag
    Register.ADCA_CTRLA = &H01		' enable ADC
    'Call Sleep(1)	' settle
End Sub

Function readADC(byval pin as byte) as integer
    ' select pin(s)
	#ifdef Differential
		Register.ADCA_CH0_MUXCTRL = (Shl(PortBit(pin), 3) And &H38) Or (PortBit(pinZero) And &H03)
	#else
		Register.ADCA_CH0_MUXCTRL = Shl(PortBit(pin), 3) And &H38
	#endif
	Register.ADCA_CTRLA = &H05	' start channel 0
	Do While Not CBool(Register.ADCA_CH0_INTFLAGS And &H01)	' wait for conversion
	Loop
	readADC = cint(Register.ADCA_CH0_RES)	' result
	Register.ADCA_CH0_INTFLAGS = &H01	' clear flag
End Function
Result:

Code: Select all

Differential:
Loops/Sec= 83305 ival= 1685 volts= 1.67

Single-ended:
Loops/Sec= 57241 ival= 3335 volts= 1.65
Later edit:
Vcc as vRef via AREFA (-24x,u pin 20) won't work; the maximum AREFA voltage is Vcc-0.6v on these parts.
Tom
Post Reply