I have a simple polling loop in assembly called by a C application.
100MHz system clock.
SysCtrlRegs.HISPCP.all = 4; // HSPCLK = SYSCLKOUT/ADC_MODCLK 12.5 MHz (from examples)
I set up trying both single sample (0,0,0) and continuous with override (0,1,1)
I have 15 for ACQ_PS
// Specific ADC setup for this example: AdcRegs.ADCTRL1.all = 0x0F60; // AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // 0 not Cascaded mode // AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run // AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1; // Enable Sequencer override feature // AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK; // Simultaneous single-shot mode: Sample rate = 1/[(2+2.5+ACQ_PS)*ADC clock in ns] // = 1/(23.5*80ns) = 1/1880ns = 532KHz (for 100 MHz devices) before ADCTRL3.ADCCLKPS AdcRegs.ADCTRL2.all = 0; // AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // start // AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // stop AdcRegs.ADCTRL3.all = 0x00E2; //0x00E4; //AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS; // 1.820 us * factor --> start with 4x (0x02) //AdcRegs.ADCTRL3.bit.SMODE_SEL= 0; // simultaneously take (but ignore) B4 so we can use SOCB out pin AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x0; // convert and store in 1 result register AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x02; // ADC channel A2
I have tried both AdcRegs and AdcMirror.
Assembler receives a pointer to array, starts ADC, waits for INT_SEQ1, clears the interrupt flag, stores the sample, and reloops for the next point. The numbers are reasonable, but they are identical for 8 loops then change only every 8 samples.
FP .set XAR2
.sect ".text"
.global _asmMeasSamp
.global _AdcRegs
.global _AdcMirror
_asmMeasSamp:
ADDB SP,#2 ;
;----------------------------------------------------------------------
; 39 | // start measurement
; 40 | AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // start
;----------------------------------------------------------------------
MOVW DP,#_AdcRegs+25 ;
OR @_AdcRegs+1,#0x2000 ;
;----------------------------------------------------------------------
; 27 | int i = 4096;
; 28 | loop:
;----------------------------------------------------------------------
SETC SXM ; [CPU_]
MOV *-SP[1],#2048 ; [CPU_] |27|
;----------------------------------------------------------------------
; 27 | while(!AdcRegs.ADCST.bit.INT_SEQ1)
;----------------------------------------------------------------------
WAITADC:
MOVW DP,#_AdcRegs+25 ;
TBIT @_AdcRegs+25,#0 ;
BF WAITADC,NTC ;
;----------------------------------------------------------------------
; 32 | AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
;----------------------------------------------------------------------
OR @_AdcRegs+25,#0x0010 ;
;----------------------------------------------------------------------
; 29 | Samples[4095-i] = AdcRegs.ADCRESULT2;
;----------------------------------------------------------------------
MOVW DP,#_AdcMirror ; first tried AdcRegs+10 ;
MOV AL,@_AdcMirror ; [CPU_] |29|
;LSL ACC,3 ; Value is in ACC as Q12, make Q15
MOV *+XAR4[0],AL ; [CPU_] |29|
ADDB XAR4,#1 ; XAR4[i]
;----------------------------------------------------------------------
; 39 | // restart measurement
; 40 | AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // start
;----------------------------------------------------------------------
;OR @_AdcRegs+1,#0x2000 ; comment if continuous mode;
;----------------------------------------------------------------------
; 30 | if (i--) goto loop;
;----------------------------------------------------------------------
DEC *-SP[1] ; [CPU_] |30|
BF WAITADC,NEQ ; [CPU_] |30|
;----------------------------------------------------------------------
; 31 | return;
;----------------------------------------------------------------------
SUBB SP,#2 ; [CPU_U]
LRETR ; [CPU_]
The code behaves the same regardless of continuous mode or single-shot.
Somehow I am getting 8 identical readings followed by a jump in value.
I could accept this if the jumps between sets were on the order of the real resolution (+/- 2) but there are significant jumps.
Assumptions:
1) HISPCP.all = 4; gives 12.5 MHz as per the examples I looked at. Just to be sure, I divided by 8 and still see the repetition.
2) INT_ENA_SEQ1 is zero unless I want to use an ISR. I do not. I just want flag set on data ready.
3) INT_MOD_SEQ1 is zero - I want a flag per sample.
4) ADCCLKPS = 1 or 2 should not affect anything except sampling rate.
5) In the debugger I see the flag set and clear as I step through. The flag is set at the end of the sequence. I *assume* this means the conversion is ready. Even if not, I'd assume I would get a different conversion every time, one sample late or get corrupted and nonsensical values.
6) I assume the zero wait state mirror is loaded and available at the same time as the base result, just reads faster. Do I need to delay between the INT flag and reading the register??
