From: Bill on 8 Sep 2009 09:53 Hi, I'm trying to pull out data from the ADS8320 (a 16-bit ADC by Analog Devices. See bottom of page 10 in http://focus.ti.com/lit/ds/symlink/ads8320.pdf ) using the SPI in an AT91SAM7S256. The problem is that the ADC needs 6 extra clock cycles to sample the analog signal, before the 16 cycles that will output each of the conversion result bits. So, a complete ADC cycle involves a minimum of 22 clock cycles. Now, the SPI in the AT91SAM7 (and, as far as I've seen, in all other MCUs), cannot generate more than 16 clock cycles within one CS activation. How am I supposed to do this, in an elegant way? Of course I could bit bang those lines, but I hate doing that, because it adds load to the CPU, and doesn't take advantage of the SPI and DMA. The AT91SAM7S256 allows holding the CS low until a new device is addressed, so I could initiate two 11-bit readings in a row (in such a way that the ADC would think it is a single CS assertion with 22 clock cycles inside), and discard the bits with no information, but that's still ugly to me. It would use the SPI, but not the DMA, and the two readings would be different (the first one should hold CS low. The second one should leave it high), which is kind of non-homogeneous. Any more elegant ideas? Thank you.
From: Vladimir Vassilevsky on 8 Sep 2009 10:11 Bill wrote: > Hi, > > I'm trying to pull out data from the ADS8320 (a 16-bit ADC by Analog > Devices. ^^^^^^^^^^^^^^^^^^^^^^ > See bottom of page 10 in > http://focus.ti.com/lit/ds/symlink/ads8320.pdf ) ^^^^^^^^^^^^^^^^^^^^^ LOL > using the SPI in an > AT91SAM7S256. The problem is that the ADC needs 6 extra clock cycles > to sample the analog signal, before the 16 cycles that will output > each of the conversion result bits. So, a complete ADC cycle involves > a minimum of 22 clock cycles. Now, the SPI in the AT91SAM7 (and, as > far as I've seen, in all other MCUs), cannot generate more than 16 > clock cycles within one CS activation. > > How am I supposed to do this, in an elegant way? Generate transactions by SPI, but control the CS signal as GPIO. I.e. assert the CS, read the required number of bits by SPI, deassert the CS. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
From: MK on 8 Sep 2009 11:04 "Bill" <a(a)a.a> wrote in message news:5gnca5d000ql2jlabkd42od9tv1mcgr9b0(a)4ax.com... > Hi, > > I'm trying to pull out data from the ADS8320 (a 16-bit ADC by Analog > Devices. See bottom of page 10 in > http://focus.ti.com/lit/ds/symlink/ads8320.pdf ) using the SPI in an > AT91SAM7S256. The problem is that the ADC needs 6 extra clock cycles > to sample the analog signal, before the 16 cycles that will output > each of the conversion result bits. So, a complete ADC cycle involves > a minimum of 22 clock cycles. Now, the SPI in the AT91SAM7 (and, as > far as I've seen, in all other MCUs), cannot generate more than 16 > clock cycles within one CS activation. > > How am I supposed to do this, in an elegant way? Of course I could bit > bang those lines, but I hate doing that, because it adds load to the > CPU, and doesn't take advantage of the SPI and DMA. > > The AT91SAM7S256 allows holding the CS low until a new device is > addressed, so I could initiate two 11-bit readings in a row (in such a > way that the ADC would think it is a single CS assertion with 22 clock > cycles inside), and discard the bits with no information, but that's > still ugly to me. It would use the SPI, but not the DMA, and the two > readings would be different (the first one should hold CS low. The > second one should leave it high), which is kind of non-homogeneous. > > Any more elegant ideas? > > Thank you. Hello Bill, On my web site you can find a VHDL model of the ADS8320 - which won't help you much with using the SAM. In the end I didn't use an FPGA on that project but I bit banged the ADS8320 from a micro. (It was so long ago that have forgotten which one !) Can you get anywhere by doing what TI hint at and do 3 times 8 bit SPI transfers for each sample ? Michael Kellett www.mkesc.co.uk
From: Bill on 8 Sep 2009 11:23 On Tue, 08 Sep 2009 09:11:13 -0500, Vladimir Vassilevsky <nospam(a)nowhere.com> wrote: >> I'm trying to pull out data from the ADS8320 (a 16-bit ADC by Analog >> Devices. >^^^^^^^^^^^^^^^^^^^^^^ > >> See bottom of page 10 in >> http://focus.ti.com/lit/ds/symlink/ads8320.pdf ) >^^^^^^^^^^^^^^^^^^^^^ > >LOL :-) Sorry. TI. I'm using other Analog Devices ICs. >Generate transactions by SPI, but control the CS signal as GPIO. >I.e. assert the CS, read the required number of bits by SPI, deassert >the CS. But still, bye bye DMA. I'm very curious... what were the guys at TI (and at some other companies) thinking when they designed this ADC with SPI interface? Which SPI hardware were they thinking would be able to pull out data in one transaction? Does anyone know of an MCU with SPI hardware able to do this? Amazing. Best,
From: Mel on 8 Sep 2009 11:23
Bill wrote: > I'm trying to pull out data from the ADS8320 (a 16-bit ADC by Analog > Devices. See bottom of page 10 in > http://focus.ti.com/lit/ds/symlink/ads8320.pdf ) using the SPI in an > AT91SAM7S256. [ ... ] > How am I supposed to do this, in an elegant way? Of course I could bit > bang those lines, but I hate doing that, because it adds load to the > CPU, and doesn't take advantage of the SPI and DMA. You have Peripheral DMA Controller, use it. This is for a Microchip ADC, but the three-byte transfer might resemble your problem. The method on the ADC side was written up in the MCP3008 datasheet. Code fragment: inline void poll_mcp3008 (int pad) { // Mode-register bits to select each of the MCP3008s, with MSTR bit set ... static const int modecsbits[4] = {0x000F0001 ^ (1 << (16+0)) , 0x000F0001 ^ (1 << (16+1)) , 0x000F0001 ^ (1 << (16+2)) , 0x000F0001 ^ (1 << (16+3)) }; // set SPI_MR(PCS) to select the pad AT91C_BASE_SPI->SPI_MR = modecsbits[(pad >> 3) & 3]; // prime buffer with a start bit, 'single' bit, and channel number pan_buf[0] = 1; // start bit pan_buf[1] = 0x80 | ((pad & 7) << 4); // 'single' bit, channel number, 2 pad bits and space for high 2 bits of value pan_buf[2] = 0; // pad space where low 8 bits of value will appear // start a conversion SPI_RwBuffer (AT91C_BASE_SPI, pan_buf, sizeof pan_buf); } And the SPI-RwBuffer added to the spi library routines (based on the other SPI routines): unsigned char SPI_RwBuffer(AT91S_SPI *spi, void *buffer, unsigned int length) { // Check if the first bank is free if (spi->SPI_RCR == 0) { // set up to overlay the write buffer with incoming data .. spi->SPI_RPR = (unsigned int) buffer; spi->SPI_RCR = length; spi->SPI_TPR = (unsigned int) buffer; spi->SPI_TCR = length; spi->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN; return 1; } // Check if second bank is free else if (spi->SPI_RNCR == 0) { spi->SPI_RNPR = (unsigned int) buffer; spi->SPI_RNCR = length; spi->SPI_TNPR = (unsigned int) buffer; spi->SPI_TNCR = length; return 1; } // No free bank return 0; } In this case the data from the MCP3008 overlays the buffer that contained the tranmitted request. It doesn't have to be this way, but it was easy to implement. SPI device interrupts when the full 3 bytes have been transferred both ways. Mel. |