SPI 13 bit ADC MCP3301

I've been able to get my MCP3301 ADC working using the method described in this post: Arduino Playground - MCP3208

However, in order to work properly the MCP3301 needs a minimum clock speed of 85KHz. I have a feeling that interfacing with the SPI ADC manually using the I/O pins described in the above link won't provide a clock speed fast enough. How would I read the output using the 'standard' way? I've tried to do it the way described in this post: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264346368/1
but my ADC doesn't have MOSI so I can't send it commands. How am I supposed to read the data?

I think you can just ignore the parts of the code involved in sending it commands. The MCP3301 looks like it'll just pump out data as soon as you ask for it. The "set continuous read mode" code in the code you referenced is unnecessary.

Then you can always write:

result = spi_transfer(0);

since the "0" is ignored (doesn't go anywhere).

--
Check out our new shield: http://www.ruggedcircuits.com/html/gadget_shield.html

I have been using the MCP3302 as a 4-channel ADC with a project I've been working on. If I use the Playground example, I can get numbers but there are weird issues with dropping the LSB of the upper word (the 256 place) when the lower word is mostly ones. I would expect to see around 1000 but get something like 768.

I changed my code to do direct port manipulation instead of using digital.Write and it seems to work perfectly. I am using the standard pins for SPI (10-13.) This code will probably not work on the Mega since I'm running the ports directly, YMMV. It's a lot faster than the Playground code, too.

It's probably easier to do this in 0019 using the new SPI library but I haven't tried it yet. I'm also not sure if you can use more than one SPI device with the 0019 library. I imagine you can but it seems to indicated that 10 is SS and can't be changed...

The commented lines are from the Playground code, and have been replaced by high-octane bit toggling. Code follows:

// ADC Reading function
// modified from http://www.arduino.cc/playground/Code/MCP3208
// changed reading routine to request 13 bits instead of 12
// Changed all (slow) digitalWrite and digitalRead to (much faster)
// direct port manipulation
    
int read_adc(int channel, int oversample){
  int adcvalue = 0;
  int oversampleAvg = 0;
  for (int i=oversample; i>0; i--){
    byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)
    
    //allow channel selection
    commandbits|=((channel-1)<<3);
    
    //Select adc
    bitWrite(PORTB, 2, LOW);  //pull CS low to enable 
  
    // setup bits to be written
    for (int i=7; i>=3; i--){
      bitWrite(PORTB, 3, (commandbits & 1 << i)); // shift command bits out PORTB 3, DATAOUT

      //cycle clock
      bitWrite(PORTB, 5, HIGH); 
      bitWrite(PORTB, 5, LOW);
    }
  
    //cycle clock twice, ignore two null bits

    bitWrite(PORTB, 5, HIGH);
    bitWrite(PORTB, 5, LOW);

    bitWrite(PORTB, 5, HIGH);
    bitWrite(PORTB, 5, LOW);

    //read bits from adc

    for (int i=12; i>=0; i--){
      oversampleAvg += (bitRead(PINB, 4) << i);
      
      //cycle clock
      bitWrite(PORTB, 5, HIGH);
      bitWrite(PORTB, 5, LOW);
    }

    bitWrite(PORTB, 2, HIGH);
    adcvalue += oversampleAvg;
  }

  adcvalue /= oversample;
  return adcvalue;
}

This defaults to single-ended mode, but if you want to use the ADC in differential you'd need to change the command word from B11000000 to B10000000. I think you can use this code as-is with the 3301, but it's only been tested with the 3302. I also added in the oversampling bits, this reads the ADC several times and returns the average. The 330X series should output 0-4095 in single-ended (12-bit) mode, just take care that oversampleAvg doesn't get too big for an int. With full-scale values, you could theoretically sample 8 times but that's it. I sample 4 times to reduce the jitter on the last couple of bits.

If you find a slick way to do this with the SPI library, post it here! This is just the best I could come up with.