• AVR Freaks

Hot!MCP3464 ADC output issues

Author
AndyH
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2014/06/09 07:41:11
  • Location: 0
  • Status: offline
2019/07/01 13:13:54 (permalink)
0

MCP3464 ADC output issues

I'm working on a product with an external MCP3464 ADC. I can communicate with the device via SPI, and am able to read and write registers with no problems. However, I just can't get the device to run correctly. 
 
I'm using the internal clock, one-shot conversion, mux mode.
 
On one of my prototype boards, MCLK is generated on the output pin for a very short period after setting CONFIG0, but then stops. On this board the Data Ready status interrupt never fires (probably not surprising if the clock isnt running). 
 
On the other prototype board, MCLK seems to be generated correctly and the Data Ready interrupt fires. However, there is no data generated in the ADCDATA Registers - it always reads 0. I have tried different mux register settings for Vin+ and Vin- to no effect. I have also tried setting it to 32-bit output with the channel ID as part of the output; it's still all 0. It is definitely reading the register, as doing an incremental read moves onto reading CONFIG0 afterwards as would be expected. 
 
I have no idea what could be causing either fault! Does anyone have any ideas, or any experience of working with this family of devices?
 
#1

5 Replies Related Threads

    thornwave
    New Member
    • Total Posts : 1
    • Reward points : 0
    • Joined: 2020/05/17 11:48:11
    • Location: 0
    • Status: offline
    Re: MCP3464 ADC output issues 2020/05/19 09:43:19 (permalink)
    0
    Hi Andy,
     
    I am having the exact same issue. Did you find a fix? Some hint or help would be immensely appreciated. 
     
    Thanks,
    Raz
    #2
    jasmeet singh
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2020/07/09 23:27:54
    • Location: 0
    • Status: offline
    Re: MCP3464 ADC output issues 2020/07/12 22:52:09 (permalink)
    0
    Hi Andyh,
     
    I am also working with ADC MCP3464 and i am also facing same problem with it. If you have any solution regarding this please help me out. thank you
     
     
    #3
    E2Paul
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2020/07/10 10:47:51
    • Location: 0
    • Status: offline
    Re: MCP3464 ADC output issues 2020/07/15 03:45:39 (permalink)
    0
    Hi Andy, Microchip users,
     
    I have the exact same problem on my board (the second one, ADCDAT staying at 0, even though I can read well my configuration registers well if i increment the pointer)
     
    Does anyone have a workaround or found an error on this?
     
    Thanks a lot
    Paul
    #4
    E2Paul
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2020/07/10 10:47:51
    • Location: 0
    • Status: offline
    Re: MCP3464 ADC output issues 2020/07/15 07:55:56 (permalink)
    0
    For anyone that could help, I found a fix in CCSinfo forum by geopro:
     
    Pin /IRQ needs to be configured as "The inactive state is logic High" or use a pull up even if you do not use it!
     
    http://www.ccsinfo.com/forum/viewtopic.php?t=58344
    #5
    AndyH
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2014/06/09 07:41:11
    • Location: 0
    • Status: offline
    Re: MCP3464 ADC output issues 2020/09/29 05:46:39 (permalink)
    0
    I've only just seen the responses to my original message. I got it working in the end, but can no longer remember what I needed to do.
     
    I've posted some code below in case it's any use. Working correctly for 4 differential input pairs, on a PIC24F16KL402
    Call spi1_Init then adc_Init in your startup
    Call adc_TimerTick on a 10ms timer
    Replace the debug_ functions with your own
     
     
    #include <p24fxxxx.h>
    #include <stdio.h>
    #include "main.h"
    #include "debug.h"

    #define ADC_NUM_CHANNELS 4

    // Global
    short adc_channelData[ADC_NUM_CHANNELS];
    long adc_value;
    bool adc_freeze = false;
    bool adc_updated = false;

    // Register definitions
    #define REG_ADCDATA 0x00
    #define REG_CONFIG0 0x01
    #define REG_CONFIG1 0x02
    #define REG_CONFIG2 0x03
    #define REG_CONFIG3 0x04
    #define REG_IRQ 0x05
    #define REG_MUX 0x06
    #define REG_SCAN 0x07
    #define REG_TIMER 0x08
    #define REG_OFFSETCAL 0x09
    #define REG_GAINCAL 0x0A
    #define REG_LOCK 0x0D


    static const uchar initialConfigData[7] =
    {
     0b01000110, // Control byte: Device address 1, incremental write starting at address 1 (Config0 register)

     0b11100010, // Config0: No total shutdown, internal clock and not on output pin, 0uA on ADC inputs, ADC standby mode
     0b00111000, // Config1: No clock prescaler, 81920 oversampling ratio
     0b10101111, // Config2: 1x Boost, 16x Gain, auto-zeroing enabled, reserved bits set to 1
     0b01000000, // Config3: One-shot conversion then standby mode, 16-bit data, CRC disabled, offset and gain disabled
     0b00000110, // IRQ Register: Fast commands enabled, IRQs enabled (although not used)
     0b00000001 // Mux register: Channel 0 on +, channel 1 on -};
    };

    static const uchar muxRegisters[ADC_NUM_CHANNELS][2] =
    {
     {
      0b01011010, // Control byte: Device address 1, incremental write starting at address 6 (Mux register)
      0b00000001 // Channel 0 on +, channel 1 on -
     },
     {
      0b01011010, // Control byte: Device address 1, incremental write starting at address 6 (Mux register)
      0b00100011, // Channel 2 on +, channel 3 on -
     },
     {
      0b01011010, // Control byte: Device address 1, incremental write starting at address 6 (Mux register)
      0b01000101, // Channel 4 on +, channel 5 on -
     },
     {
      0b01011010, // Control byte: Device address 1, incremental write starting at address 6 (Mux register)
      0b01100111 // Channel 6 on +, channel 7 on -
     }
    };

    static const uchar startConversionFastCmd = 0b01101000; // Fast command to start a conversion
    static const uchar fullResetFastCmd = 0b01111000; // Fast command to reset device
    static const uchar readConversionData = 0b01000011; // Device address 1, incremental read starting at register address 0 (ADC Data register)
    static const uchar readConfigBytes = 0b01000111; // Device address 1, incremental read starting at register address 1 (Config0)

    // Local variables
    static uchar currentChannel;
    static uchar notReady;


    static void writeData(const uchar *data, uchar len);
    static void readData(uchar cmd, uchar *data, uchar len);
    static uchar spi1_poll(uchar data);


    void adc_Init(void)
    {
     uchar data[5];
     uchar ch;
     
     // Configure the ADC chip select as output and high
     TRISBbits.TRISB12 = 0;
     LATBbits.LATB12 = 1;
     
     // Set variables
     for (ch = 0; ch < ADC_NUM_CHANNELS; ch++)
     {
      adc_channelData[ch] = 0;
     }

     currentChannel = 0;
     notReady = 0;
     
     // Reset the device
     writeData(&fullResetFastCmd, 1);
     
     // Write the initial config
     writeData(&initialConfigData[0], 7);
     
     //adc_dump();
     
     // Check we can talk to the device
     readData(readConfigBytes, &data[0], 5);
     if ((data[1] != initialConfigData[1]) || (data[2] != initialConfigData[2]) || (data[3] != initialConfigData[3]) || (data[4] != initialConfigData[4]))
     {
      debug_Puts("ADC init fail\r\n");
      return;
     }
     
     // Start the first encode
     writeData(&startConversionFastCmd, 1);
     
     debug_Puts("ADC init OK\r\n");
    }


    void spi1_Init(void)
    {
     // Disable module to start
     SSP1CON1 = 0;

     // Configure the relevant pins for SPI
     TRISBbits.TRISB11 = 0; // SCK1 output
     TRISBbits.TRISB10 = 1; // SDI1 input
     TRISBbits.TRISB13 = 0; // SD01 output

     // Ensure SCK and SDO are not disabled
     PADCFG1bits.SCK1DIS = 0;
     PADCFG1bits.SDO1DIS = 0;

     // General config
     SSP1STAT = 0;

     //SSP1CON1bits.SSPM = 0b0000; // SPI master mode, clock = Fosc/2 = 16MHz
     //SSP1CON1bits.SSPM = 0b0001; // SPI master mode, clock = Fosc/8 = 4MHz
     SSP1CON1bits.SSPM = 0b0010; // SPI master mode, clock = Fosc/32 = 1MHz
     SSP1CON1bits.CKP = 0; // Clock polarity, idle is low
     SSP1STATbits.CKE = 1; // Transmit occurs on transition from active to idle clock state
     SSP1CON1bits.SSPEN = 1; // SSP enabled
    }


    void adc_TimerTick(void)
    {
     static ulong ct = 0;
     uchar status;
     ushort tmp;
     short value;

     // Debug
     ct++;
     if (ct >= 100)
     {
      debug_Putn(adc_channelData[0]);
      debug_Puts(" ");
      debug_Putn(adc_channelData[1]);
      debug_Puts(" ");
      debug_Putn(adc_channelData[2]);
      debug_Puts(" ");
      debug_Putn(adc_channelData[3]);
      debug_Puts("\r\n");
      ct = 0;
     }
     
     
     // Pull chip select low
     LATBbits.LATB12 = 0;
     
     // Write command byte and get status in return
     status = spi1_poll(readConversionData);
     
     // Check the status byte for the POR bit. Low = POR has occurred
     if ((status & 0x01) == 0x00)
     {
      debug_Puts("ADC POR, reinit\r\n");
      adc_Init();
      return;
     }

     // Check the data ready bit
     if ((status & 0x04) == 0x04)
     {
      notReady++;
      if (notReady > 20)
      {
       debug_Puts("ADC not ready 200ms\r\n");
      }
      else
      {
       LATBbits.LATB12 = 1;
       return;
      }
     }
     notReady = 0;
     
     // Read remaining bytes
     tmp = spi1_poll(0);
     tmp <<= 8;
     tmp |= spi1_poll(0);

     // Set chip select high again
     LATBbits.LATB12 = 1;

     
     // Build value
     value = (short)tmp;
     

     // Store value
     adc_channelData[currentChannel] = value;
     
     // Move onto next channel and reading
     currentChannel++;
     if (currentChannel >= ADC_NUM_CHANNELS)
     {
      currentChannel = 0;
     }
     
     // Write the new ADC channel
     writeData(&muxRegisters[currentChannel][0], 2);
     
     // Start the next encode
     writeData(&startConversionFastCmd, 1);
     
    }



    #if 0
    void adc_dump(void)
    {
     uchar data[28] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     
     // Check we can talk to the device
     readData(readConfigBytes, &data[0], 28);

     debug_Puts("\r\nConfig0:");
     debug_Putx(data[1]);
     debug_Puts("\r\nConfig1:");
     debug_Putx(data[2]);
     debug_Puts("\r\nConfig2:");
     debug_Putx(data[3]);
     debug_Puts("\r\nConfig3:");
     debug_Putx(data[4]);
     debug_Puts("\r\nIRQ:");
     debug_Putx(data[5]);
     debug_Puts("\r\nMux:");
     debug_Putx(data[6]);
     debug_Puts("\r\nScan:");
     debug_Putx(data[7]);
     debug_Putx(data[8]);
     debug_Putx(data[9]);
     debug_Puts("\r\nTimer:");
     debug_Putx(data[10]);
     debug_Putx(data[11]);
     debug_Putx(data[12]);
     debug_Puts("\r\nOffsetcal:");
     debug_Putx(data[13]);
     debug_Putx(data[14]);
     debug_Putx(data[15]);
     debug_Puts("\r\nGaincal:");
     debug_Putx(data[16]);
     debug_Putx(data[17]);
     debug_Putx(data[18]);
     debug_Puts("\r\nRes:");
     debug_Putx(data[19]);
     debug_Putx(data[20]);
     debug_Putx(data[21]);
     debug_Puts("\r\nRes:");
     debug_Putx(data[22]);
     debug_Puts("\r\nLock:");
     debug_Putx(data[23]);
     debug_Puts("\r\nRes:");
     debug_Putx(data[24]);
     debug_Putx(data[25]);
     debug_Puts("\r\nCRC:");
     debug_Putx(data[26]);
     debug_Putx(data[27]);
     debug_Puts("\r\n");
    }
    #endif



    static void writeData(const uchar *data, uchar len)
    {
     // Pull chip select low
     LATBbits.LATB12 = 0;
     
     // Write bytes
     while (len > 0)
     {
      (void)spi1_poll(*data);
      data++;
      len--;
     }
     
     // Set chip select high again
     LATBbits.LATB12 = 1;
    }




    static void readData(uchar cmd, uchar *data, uchar len)
    {
     // Pull chip select low
     LATBbits.LATB12 = 0;
     
     // Write command byte
     *data = spi1_poll(cmd);
     data++;
     len--;
     
     // Read remaining bytes
     while (len > 0)
     {
      *data = spi1_poll(0);
      data++;
      len--;
     }

     // Set chip select high again
     LATBbits.LATB12 = 1;
    }



    static uchar spi1_poll(uchar data)
    {
     // Write data
     SPI1BUF = data;

     // Wait for data to arrive
     while (SSP1STATbits.BF == 0) { }

     // Dump data
     return (uchar)SPI1BUF;
    }

    #6
    Jump to:
    © 2020 APG vNext Commercial Version 4.5