View previous topic :: View next topic |
Author |
Message |
kaos
Joined: 03 May 2007 Posts: 4 Location: Spain
|
Problem width MCP3302(A/D Converter) |
Posted: Thu May 03, 2007 5:15 am |
|
|
Halo, my english is very poor so I ask for pardon.
hardware:
MCP3301 -> 13-Bit Differential Input, Low Power A/D Converter with SPI™ Serial Interface (microchip)
PIC18F2550
code:
Code: |
// Added SPI Mode define because CCS and Microchip made a very confusing mess of it.
// MOTOROLA MICROCHIP CCS
//---------------------------------------------------------------------------------
// SPI Mode 0,0 == CKP = 0, CKE = 1 == SPI_L_TO_H | SPI_XMIT_L_TO_H
// SPI Mode 0,1 == CKP = 0, CKE = 0 == SPI_L_TO_H
// SPI Mode 1,0 == CKP = 1, CKE = 1 == SPI_H_TO_L
// SPI Mode 1,1 == CKP = 1, CKE = 0 == SPI_H_TO_L | SPI_XMIT_L_TO_H
#define MCP3301_CS PIN_B2
#define MCP3301_CLK PIN_B1
#define MCP3301_SDI PIN_B0
void init_mcp3301()
{
output_low(MCP3301_CS);
output_low(MCP3301_SDI);
output_low(MCP3301_CLK);
setup_spi( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16 );
//setup_spi( SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 );
}
int16 read_mcp3301()
{
BYTE byte_low=0,byte_high=0;
output_high(MCP3301_CS);
while( !spi_data_is_in() )
{
byte_high = spi_read();
byte_low = spi_read();
}
output_low(MCP3301_CS);
byte_high <<3>>= 3;
return (make16(byte_high,byte_low));
}
void main(void)
{
int16 dato;
printf("Init mcp3301...\r\n");
delay_ms(100);
init_mcp3301();
delay_ms(100);
while(1)
{
dato = read_mcp3301();
printf("Dato: %Ld \r\n",dato);
delay_ms(100);
}
}
|
Problem:
spi_data_is_in() always is false. |
|
|
RolandAldridge
Joined: 26 Mar 2007 Posts: 7 Location: Southern California
|
|
Posted: Thu May 03, 2007 10:08 am |
|
|
I think you have the chip select lines the wrong way up - bring it low while you write to or read from it, high when you are not doing so.
Here is my code for a 3204, using a 16C67:
byte first_data_out, second_data_out;
struct adc_data_type{ byte hi; byte lo;} adc_data;
long data_in = 0;
first_data_out = 0x06; // See MP3204 data sheet
// Set up the data_out byte to tell the ADC what channel to look at.
If (ADC_Channel > 3) ADC_Channel = 0; // We'll look at the reading, what the hell
second_data_out = ADC_Channel << 6; // 0 is oxygen, 1 is Alarm 1, 2 is Alarm 2, 3 is span value
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16|SPI_SS_DISABLED);
//Set up the SPI for 0,0 operation
CKE = TRUE; // data out transmitted on clock rising edge
SMP = FALSE; // input data sampled in middle of data output time
// set the /cs pin high then low to initiate communication
// Output_HIGH(ADC_CS);
Output_LOW(ADC_CS);
//Now tell it what we want
//Dump any data in the buffer
If ( SPI_DATA_IS_IN() )data_in = spi_read();
// Write the command data into the chip
SPI_write(first_data_out);
adc_data.lo = SPI_read(); // garbage
SPI_write(second_data_out);
adc_data.hi = spi_read(); // of which the first four bits are garbage
SPI_write(second_data_out); // so as to clock in the lower byte
adc_data.lo = spi_read();
adc_data.hi &= 0x0F; // Dump the top four bits
data_in = adc_data.hi;
data_in <<= 8;
data_in += adc_data.lo;
Output_HIGH(ADC_CS); // set the /cs high again
return( data_in);
Roland _________________ Roland Aldridge
www.amio2.com |
|
|
nina
Joined: 20 Apr 2007 Posts: 111
|
mcp |
Posted: Sat May 05, 2007 4:23 am |
|
|
what means these lines?
byte_high <<3>>= 3;
return (make16(byte_high,byte_low));
tks |
|
|
kaos
Joined: 03 May 2007 Posts: 4 Location: Spain
|
|
Posted: Sat May 05, 2007 4:35 am |
|
|
In the picture you can to see that 3 bytes don't use so first, <<3, move 3 bytes to left an them, >>3, move 3 bytes to right. Now there is 0. |
|
|
nina
Joined: 20 Apr 2007 Posts: 111
|
high_byte |
Posted: Sat May 05, 2007 7:53 am |
|
|
kaos...
why do I need use this line?
tks |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Sat May 05, 2007 10:38 am |
|
|
Quote: |
byte_high <<3>>= 3; |
The statement is wrong.
you wanted to do this:
byte_high << 3;
byte_high >> 3;
in one statement.
If you want to discard the 3 MSB:
byte_high = (0x1F & byte_high);
Anyway you need something like this:
Code: |
signed long read_mcp3301()
{
int byte_low=0,byte_high=0;
signed long out_value;
output_low(MCP3301_CS);
byte_high = spi_read(); // clock out the MSByte
byte_low = spi_read(); // clock out the LSByte
output_high(MCP3301_CS); // disable the converter
out_value = make16(byte_high,byte_low);
if(bit_test(out_value,12)) // get the sign
{bit_set(out_value,15);} // format propperly a signed long
else
{bit_clear(out_value,15);}
return(out_value);
}
void main(void)
{
signed long dato;
delay_ms(100);
printf("Init mcp3301...\r\n");
init_mcp3301();
delay_ms(100);
while(1)
{
dato = read_mcp3301();
dato = dato & 0x9FFF; // discard bit 14 and 13
printf("Dato: %Ld \r\n",dato); // Signed output
delay_ms(1000);
}
}
|
I don´t have the MCP3301 to test it, i would like to know your results.
Humberto |
|
|
kaos
Joined: 03 May 2007 Posts: 4 Location: Spain
|
|
Posted: Sun May 06, 2007 5:04 am |
|
|
It does not work. I dont't understand, because the A/d is very simple but only send 514 and dont change.
Thank you anyhow.
pd:
I writed
byte_high <<= 3;
byte_high >>= 3;
but the foro changed it ;). |
|
|
|