This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1248 ADC chip

Other Parts Discussed in Thread: ADS1248, ADS1246, MSP430F4783

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.

     

     

  • Hi  Mr. Downs,

    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 tosc
    ADC24sstartloop   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,R5
    ADC24sbusy1        bit.b   #UCBUSY,&UCB0STAT
                                    jnz     ADC24sbusy1
                                    mov.b   #000h,&UCB0TXBUF                                                                        ; Write bytes = 0+1 = 1 byte
                                    mov.b   &UCB0RXBUF,R5
    ADC24sbusy2        bit.b   #UCBUSY,&UCB0STAT
                                    jnz     ADC24sbusy2
                                    mov.b   #ADC24_PGA32+ADC24_DOR2K,&UCB0TXBUF                        ; SYS0=ADC24_PGA32+ADC24_DOR2K
                                    mov.b   &UCB0RXBUF,R5
    ADC24sbusy3        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