Hi,
I was wondering if anybody here has any experience using the ADS1248 ADC? I am able to write to the chip's registers, but when i try to read back from them, all i get is zeros. I am unclear about what exactly i should do with the START pin (when to take high or low) when setting up the ADS1248 when I am trying to read from it. The ADC is connected to a thermistor and I am trying to get a temperature measurement.
Any help on setting up the START pin or other initialization procedures when reading data back from the ADS1248 registers would be greatly appreciated.
The START pin can be used to start a conversion by pulling it HIGH. If you'd rather have the device continuously convert, simply tie START high all the time, and the ADS1248 will send out /DRDY pulses as it finishes each conversion.
Since it sounds like you're having a little trouble getting started (no pun intended), I'd advise just tying START high. Set your code up so that you watch the /DRDY line for a HIGH-to-LOW transition (we do this by tying it to an interrupt pin of a micro - the HIGH-to-LOW transition then fires off an interrupt), then when you see that transition or interrupt you send an RDATA or RDATAC command and clock out the data. Note that you have to set the DRDY MODE bit up correctly.
You say you can write to registers, but can't read them back - how do you know you've written to them? For example, if you set the DRDY MODE bit to different values, does the function of the DRDY pin change?
Sorry I can't give you much more detail now - would need to know how you're attempting to communicate to know where you might be going wrong. Can you post some code that might help us figure out what you're doing? What micro are you talking to?
Hi Mr. Downs,
Thanks very much for the reply - but I think we are already doing what you suggested. To give a little background, I am a University student trying to get the ADS1248 to work - I am using a Motorola M68HC11 micro-controller (I know, its kind of old!). I think that I am doing something wrong with the taking high/low of the start pin, or perhaps the initialization commands to the registers of the ADS1248 when I try to read back the conversion results. I made some progress since my last post - i can now read back the contents of the ADC's registers which i couldn't do before. Taking the start pin high before reading made that possible. however, I still can't get any coherent conversion data from
the data registers - its still all 0s. My code which successfully reads the register contents (it writes to all the registers first and then reads back what it has written for all of them) is given below. Asterisks are comments, data equates are at the end, # denotes immediate addressing, PORTA (8 bit) is subdivided into both input and output functions:
*********************************************************************************************
ldaa #%00010000 Make Start pin go high (Change which enabled regsiter reading - it came out as 14 0s before when we tried to read from all the registers) staa PORTA
ldx #RDREGS
bsr SEND L1 ldab #14 Count the number of registers to be read ldy #V1 Point to data area where register contents will be stored * L3 ldx #NOOPR bsr SEND Send the NOP command * ldaa SPDR Then read one byte ... staa 0,Y ... and store it iny Increment pointer decb Decrement register counter bne L3 Go back for more till done * clr PORTA Take Start pin low again swi
Subroutines * SEND ldaa 0,X Get byte from string cmpa #EOT Is this the end? (End of Transmission? ) beq DONE staa SPDR If not, send it (SPDR is the micro - data register) WAIT ldaa SPSR bpl WAIT Wait for completion * inx Point to next byte bra SEND * DONE rts Return after all are sent DELAY ldy #0 This routine produces a delay DLY1 brn DLY1 of 426 milliseconds. brn DLY1 dey bne DLY1 * rts
ORG DATA * READ FCB $12,EOT Conversion results are read once by sending the RDATA command RDCONT FCB $14,EOT Conversions are made continuously RDREGS FCB $20,$0D,EOT NOOPR FCB $FF,EOT * ONSTR FCB $4E,$00,$01,EOT OFFSTR FCB $4E,$00,$00,EOT * ALREGS FCB $40,$0D,$01,$00,$20,$00,$00,$00,$00,$00,$00,$00,$03,$0F,$01,$00,EOT (write to all the registers at once) * END
***************************************************************************************************************************************
This code works currently and lets me read back the register contents. I mentioned in my previous post that I could write to the ADS1248 - this was done by making an LED flash on and off with the chip by using one of the I/O pins on the ADS1248. I will post my conversion reading code (which doesn't work properly) next. Any help would be very greatly appreciated.
This is the code which is faulty - as i mentioned, i get 0s when i try to read back converison results. We have a thermistor connected as the temperature sensing element. The idea was that when the /drdy pin goes low, we send nop commands to read back 3 bytes which would be the converison results. however, upon checking memory in the micro-c, all 3 bytes are 0s which can't be right.The pasting in from notepad is kind of messy; anyway, a brief command syntax guide if necessary is below before the code starts :
ldaa - means load accumulator A (8 bit) ; staa - store A to; ldx - load accumulator X (16 bit); bsr/jsr - branch/jump to subroutine; clr - clear; bne - branch on not equal to 0; bpl - branch on plus (if the lead bit in the register is a 0);
decb - decrement accumulator B; inx - increment X; cmpa - compare A to; beq - branch on equal to 0; swi is software interrupt; bra - branch always, brn - branch never; dey - decrement accumulator Y; rts - return from subroutine;
$20 - means hex 20; % prefix indicates a binary number. L1, L2, L3 in the code below are just loop labels .
*****************************************************************************************************************************************
* Configure ADS1248 registers first (CODE STARTS HERE)
ldaa #%00010000 Make Start pin go high (Start pin connected to bit 4 of PORTA) staa PORTA
ldx #ALREGS bsr SEND clr PORTA This takes START low again. jsr DELAY
CYCLE ldaa #%00010000 Pulse START high, then low. staa PORTA nop (micro-c nop command; not for ADS1248 nop) clr PORTA * WHEN2 ldaa PORTA The WHEN2 is just a loop label bita #%00000001 Check PA0 pin for DRDY\ low; this is a bitwise and; /drdy connected to bit 0 of PORTA bne WHEN2 * ldx #READ bsr SEND * L1 ldab #3 Count 3 bytes ldx #V1 Point to data area L2 ldaa SPSR bpl L2 Wait until SPI is ready * L3 ldaa #$FF staa SPDR Send the NOP command (this NOP is for the ADS1248)
L4 ldaa SPSR bpl L4 Wait until exchange is complete * ldaa SPDR Then read one byte ... staa 0,X ... and store it inx Increment pointer decb bne L3 Go back for more * dec COUNT COUNT variable is = 4; not quite sure if this is necessary bne CYCLE * swi
* Subroutines * SEND ldaa 0,X Get byte from string cmpa #EOT Is this the end? beq DONE staa SPDR If not, send it WAIT ldaa SPSR bpl WAIT Wait for completion * inx Point to next byte bra SEND * DONE rts Return after all are sent * * DELAY ldy #0 This routine produces a delay DLY1 brn DLY1 of 426 milliseconds. brn DLY1 dey bne DLY1 * rts
ORG DATA Data equates are below * READ FCB $12,EOT Conversion results are read once by sending the RDATA command* ONSTR FCB $4E,$00,$01,EOT OFFSTR FCB $4E,$00,$00,EOT MUX0 FCB $40,$00,$01,EOT Selects AIN0 as + input, AIN1 as - input. MUX01 FCB $40,$00,$13,EOT (Set MUX0 to use AIN2 as positive and AIN3 as negative for 2nd diff. measurement) ; we are using only 1 thermistor right now though * ALREGS FCB $40,$0D,$01,$00,$20,$00,$00,$00,$00,$00,$00,$00,$03,$20,$00,$00,EOT * END
************************************************************************************************************************************
I think the byte in the MUX1 register which is hex 20 right now could be wrong; might need to be hex 38; the start pin again is something i am not sure about. Again, any help on this would be greatly appreciated.
Thanks.
Syed,
Well, I'll admit my assembly skills are pretty rusty, but from what I can see here I can't spot any glaring errors (but I may have missed something obvious because I never used the 68HC11 - I learned assembly on 68000 and 8051 cores). I guess the better way to approach this is to look at the actual serial port pins with a scope and see if your code is making them work like what is shown below:
Do you serial ports lines look like this? And what data is actually coming back from the converter - is DOUT zero all the time? We need to narrow down if the problem is the chip isn't sending you data or if you are somehow "losing" what comes back in your code. Take a look at that and let me know what you find.
Thanks for replying. I have been looking with a scope but that was at the Din pin during the write process. I will try what you suggested, probably tomorrow and let you know.
I was wondering if you had any opinion on the initialization commands that I have been using for the ADS1248? whether they seem right to you and would set up the ADS chip the right way if I was trying to get conversion data off it? I write to all the registers (14 of them ) in order, filling them up like so ($ is hex):
$01,$00,$20,$00,$00,$00,$00,$00,$00,$00,$03,$0F,$01,$00
$20 goes into the MUX1 register and i think it might need to be $38. Anyway, do you think the setting up is right? I could provide more info. if needed.
MUX0 = 0x01 = No BCS, AINP = AIN0, AINN = AIN1
VBIAS = 0x00 = No Bias Voltage enabled
MUX1 = 0x20 = Internal osc, internal ref on, REF0 selected, use MUX values for input (no system monitor)
-> did you mean to use the internal reference as the ADC ref? Then you would want this to be 0x30, so you use the internal ref for the ADC
SYS0 = 0x00 = PGA = 1, Data Rate = 5SPS
OFC0 = 0x00
OFC1 = 0x00
OFC2 = 0x00 = these are the defaults, you probably don't actually need to write them.
FSC0 = 0x00
FSC1 = 0x00
FSC2 = 0x00 = you don't want to write this! You've set the full scale of the device to zero, so it's no wonder you get nothing but zeros out. You should not write to these or the OFC registers.
IDAC0 = 0x00 = DOUT/DRDY acts on as Data Out, current source DACs turned off
IDAC1 = 0x03 = I1DIR off, I2DIR to AIN3... ok, so you want the internal ref on, but you may not be using it for the ADC. But why then do you have the DACs turned off?
GPIOCFG = 0x0F = IOCFG3-0 used as GPIO, others are analog input. So REFP0, REFN0, AIN2 and AIN3 are GPIOs. Probably don't want REF0 used as your ADC ref then.
GPIODIR = 0x01 = all GPIOs outputs except REFP0, which is an input.
GPIODAT = 0x00 = all GPIOs are set low.
Hope that helps. One big problem is writing to the offset and gain registers - don't do that.
Thanks very much for the post. I hope that solves the problem I have been having. i was wondering what the bits in the offset and gain registers should be if i don't write to them? What should i leave the contents of the FSC0,1,2 registers as?
Is there a default value for those registers that would take away the all 0s problem I 've been having?
And about the DACs that you mentioned, should i be leaving one of them on to make the thermistor work properly? In that case, what would you suggest that i put into the IDAC0 and IDAC1 register for it to be correct?
(I suppose I am really not the best interpreter of data sheets!)
thanks for all your help regarding this.
You should probably read the OFC and FSC registers before writing to them, then when you write all registers simply restore (write back) the same values you read. The OFC register should be something close to 0 - on a part I have, after calibration, it's 0xFFFFF5, but you could just write 0x000000 to this register (as you have been) and be close.
The FSC register is different - on my part, again after calibration, it's 0x400840. The data sheet says the default for this register is a full-scale calibration at a gain of 32, but doesn't tell you what's actually loaded by default. I say load 0x400840 and you'll be close.
If you want to excite the thermistor with a current, typically you would connect the thermistor between two inputs (say, AIN1 and AIN0) and then connect a resistor between the bottom of the thermistor and ground, and use the voltage dropped across that resistor as the reference. Here's a diagram for doing this with a two-wire RTD, but you could do it with a thermistor as well:
You size the Rbias resistor to give you a decent voltage for the reference with the current from the IDAC flowing through it. The voltage across the thermistor changes with temperature. Is this how you have your circuit set up? I suggest you try it this way - so you're using the REF0 pins as GPIO, if you put Rbias between the REF1 pins, you'd set up the MUX1 register as 0x28. You'd set IDAC0 to use whatever current is appropriate, and route it using IDAC1 = 0x11 - so you have both IDACs driving the AIN1 pin.
That should get you started. Good luck!
Well, I am glad to say that everything works now with the ADS1248 and I am able to get coherent data out of it; the fixing up of the FSC registers did the trick.
Thanks very very much for all your help on this - it wouldn't have worked otherwise.
I met a problem like this tip in my project about ads1246.
MCU--MSP430F4783, VCC = 2.7V, MCLK = 8MHZ, SPI interface, Baud rate 500,000
My object is to set PGA = 32 and DOR = 2000 SPS.
=====================================
begin
{
Pull START pin HIGH;
delay 3.5 tosc; // Minimum START pulse width = 3tosc, 750ns
Pull START pin LOW;
waite for /DRAY HIGH-to-LOW transition; // Conversion finished, 500ms after 'Pull START pin LOW', DOR= 5 SPS, the default value
send WREG; // 043h, 4xh -- Write register, 03h -- register SYS0
send 00h; // 00h, Number of registers to be write = 00h + 1
send 5fh; // 5fh, PGA = 32 and DOR = 2000 SPS
}
end
Then, tie START HIGH.
The figure on scope displays that the periods of /DRDY is still 200ms, that is DOR = 5 SPS.
Why, may be something is wrong?
Give me you hand, please!
ADC24set push R5 bis.b #BIT4,&P3OUT ; Set 'START'; ADC24 START pulse width = 3.5 ADC24 tosc mov.w #2,R5 ; 1 MCLK = 1/2 ADC24 toscADC24sstartloop dec.w R5 ; 1 MCLK = 1/2 ADC24 tosc jnz ADC24sstartloop ; 2 MCLK = 1 ADC24 tosc bic.b #BIT4,&P3OUT ; Reset 'START' mov.b #ADC24_WREG+ADC24_REGSYS0,&UCB0TXBUF ; Write SYS0 mov.b &UCB0RXBUF,R5ADC24sbusy1 bit.b #UCBUSY,&UCB0STAT jnz ADC24sbusy1 mov.b #000h,&UCB0TXBUF ; Write bytes = 0+1 = 1 byte mov.b &UCB0RXBUF,R5ADC24sbusy2 bit.b #UCBUSY,&UCB0STAT jnz ADC24sbusy2 mov.b #ADC24_PGA32+ADC24_DOR2K,&UCB0TXBUF ; SYS0=ADC24_PGA32+ADC24_DOR2K mov.b &UCB0RXBUF,R5ADC24sbusy3 bit.b #UCBUSY,&UCB0STAT jnz ADC24sbusy3 pop R5 ret
From a register and command standpoint, it appears you are doing everything correctly.
The only thing I'm not sure about is if your /CS signal is staying low during the entire WREG/00/5F sequence - it needs to in order for the command to take properly. Put a scope on your SPI bus and look to see if this is happening correctly.
Another test might be to just trying writing to and reading from registers, to make sure the communication is working properly.
Thank you for your reply.
I had corrected the bug in my software, it's ok!
I lost a important setting bit for interfacing MSP430F4783 to ADS1246 via SPI, the UCMSB -- MSB first