Hello,
I have now examined the datasheet for the MCP3204 device, and am of the opinion that you are not using the correct data format. Fig. 6.1 and Fig. 6.2 provide the information for the SPI interface.
- The first byte sent will need the start bit and the single/diff bit correctly positioned, and the return data would be ignored.
- The second byte sent will need the two channel select bits positioned at the two most significant positions. The lower four bits of the return byte will contain the MS four bits of the 12-bit reading.
- The third byte sent will be a dummy byte of non-specific value, and the return byte will contain the remaining bits of the 12-bit reading.
With a bus clock of 7.3728 MHz, and a timer interrupt period of 200 microseconds, this will correspond to 1474 bus cycles between interrupts. The ISR processing should take considerably less than this number of cycles, to allow for other activities to occur. In fact all other ISRs should also take considerably less than that number of cycles, so that the critical timer interrupt may occur with minimal latency.
With the current ISR code, the code enters a tight (5-cycle) loop, waiting for the SPRF flag to become set. The period within the loop will therefore be a 5-cycle multiple. The SPI clock should be as fast as possible. However, the minimum available division ratio is 2, and the next ratio is 8. A division ratio of 2 would put the SPI clock at 3.69 MHz, which is too high for the ADC device, so a division ration of 8 must be used. This will give a SPI clock of 0.92 MHz, which is one half the maximum rate of the ADC. So each byte transfer will take 64 bus cycles, and the wait loop will occupy 65 cycles.
I notice that you are storing the data in a two-dimensional array of structures. Handling this would seem to require an excessive number of cycles. By extending the structure, it is possible to have a single dimension array of structures that will be considerably more efficient to handle.
The following code addresses some of these issues, and requires about 656 cycles to execute, occupying about 45 percent of the available time.
#define clrReg8Bits(reg,bit) __asm bclr (bit),(reg)
#define setReg8Bits(reg,bit) __asm bset (bit),(reg)
#define CS_3204 7
#define START 0x06 /* Single mode */
typedef union {
word value;
byte val[2];
} two_byte;
typedef struct {
two_byte dat0;
two_byte dat1;
} two_val;
byte ind;
byte chan;
two_val Datos[10];
byte SPI_trans( byte val); /* Function prototype */
/****************************************************************************/
/* TIM Ch0 interrupt (output compare) */
interrupt 5 void Muestreo_C_fase_OnInterrupt(void)
{ // [13] ISR entry
T1SC0_CH0F = 0; // [4] Clear flag
T1CH0 += INCRVAL; // [21] Set next interval
if (ind < 10) { // [9]
clrReg8Bits(PTA, CS_3204); // [4]
(void)SPI_trans( START); // [37 or 82<-]
Datos[ind].dat0.val[0] =
SPI_trans( chan << 6) & 0x0F; // [63 or 108<-]
Datos[ind].dat0.val[1] =
SPI_trans( 0); // [50 or 95<-]
setReg8Bits(PTA, CS_3204); // [4]
__asm nop; __asm nop; // [2]
setReg8Bits(PTA, CS_3204); // [4]
(void)SPI_trans( START); // [37 or 82<-]
Datos[ind].dat1.val[0] =
SPI_trans(( chan + 1) << 6) & 0x0F; // [63 or 108<-]
Datos[ind].dat1.val[1] =
SPI_trans( 0); // [50 or 95<-]
setReg8Bits(PTA, CS_3204); // [4]
ind++; // [10]
}
} // [11] ISR exit
/****************************************************************************/
/* SPI transfer */
byte SPI_trans( byte val)
{
SPDR = val;
while (!SPSCR_SPRF); /* Wait for transfer complete */
return SPDR;
} // Total cycles: 15+(5*n)
// SPI_clk divisor = 2: n = 4
// SPI_clk divisor = 8: n = 13 /*
For each 200 microsecond interrupt, you are processing two ADC readings. The ISR execution time would be more managable if only a single reading were processed for each interrupt.
It is possible to utilize the SPI interrupt to avoid waiting for each SPI transfer to complete. However, the coding would be more complex. With minimum ISR entry/exit overhead of 28 cycles, and the more complex code, any savings would probably be quite minimal.
Regards,
Mac