|
|
|
Getting ADC result
|
|
Date: 2007/04/27 14:27
|
By: rwillis
|
Status: User
|
|
|
Karma: 0  
|
|
| Posts: 2 |   | |
|
Hi All
First off, I've not much experience with PIC's etc, so any code posted will probably be a bit frightening to most of you. My main problem is I have a circuit, all tested and working, its an MCP3421 18bit ADC. I only need 14bits for my application, but I digress. I have a dsPIC33FJ256GP506, I am using the C30 compiler and the peripheral libraries, in my app. I want to just read one value from the ADC, to start with. I am reading temps using PT100 sensors.
I have emailled Microchip, who cannot provide me with any C examples, only asm for the 16F series, so I have a lot of reading to do.
Well I have tried to follow, and convert many asm examples, and the tech specs, etc. but I only get the same three sets of answers, either all 0's, F's or a 0x7F7F pattern. I feel it may be a setup problem, but If someone could look at the code for any glaring errors it would a great help. I'm just providing the relevant code here that does the ADC work,
Thanks for getting this far.
Russ
| Code: |
#include <p33fj256gp506.h>
#include <i2c.h>
//----------------------------------------------------------------------------------------
void Analog_Init()
{
unsigned int config2,config1;
config2 = 0x11; // Set baud rate to 100KHz
config1 = ( I2C1_ON & I2C1_IDLE_CON & I2C1_CLK_HLD &
I2C1_IPMI_DIS & I2C1_7BIT_ADD & I2C1_SLW_DIS &
I2C1_SM_DIS & I2C1_GCALL_DIS & I2C1_STR_DIS &
I2C1_NACK & I2C1_ACK_DIS & I2C1_RCV_DIS &
I2C1_STOP_DIS & I2C1_RESTART_DIS &
I2C1_START_DIS );
OpenI2C1(config1,config2);
}
//----------------------------------------------------------------------------------------
// Globals used for debugging
unsigned char sensor_result1_1; // H/L Results from sensor reading
unsigned char sensor_result1_2;
//----------------------------------------------------------------------------------------
void Analog_Task()
{
unsigned char setup_1_shot; // Setup ADC config and initiate 1 shot conversion
unsigned char setup_only; // Setup ADC config only
unsigned char setup_continuous; // Setup ADC config and continuous conversion
setup_1_shot = 0x87; // 10001111 (8V/V - 14bit 60SPS - 1Shot - Do Conversion)
sensor_result1_1 = 0;
sensor_result1_2 = 0;
IdleI2C1(); // Set I2C as idle
StartI2C1(); // Request start up sequence
IdleI2C1();
MasterWriteI2C1(0x8B ); // RW/1 ADDR/000 DEV/1011 (8b)
IdleI2C1();
AckI2C1();
IdleI2C1();
//----------------------------------------------------------------
// Setup the ADC, then send the ONE SHOT CONVERSION code
//----------------------------------------------------------------
MasterWriteI2C1(setup_1_shot); // Setup ADC
IdleI2C1();
AckI2C1();
IdleI2C1();
//----------------------------------------------------------------
// Read in sensor data, as it is 14bits long need to read in
// two byte values from the ADC.
//----------------------------------------------------------------
// SENSOR 1
I2C1RCV = 0x00; // Make sure rx buffer is 0
MasterReadI2C1(); // Read value from I2C bus
IdleI2C1();
AckI2C1();
sensor_result1_1 = I2C1RCV; // Result of the 1 shot conversion
I2C1RCV = 0x00; // 0 again, for testing
//IdleI2C1();
MasterReadI2C1(); // Read value from I2C bus
IdleI2C1();
AckI2C1();
//IdleI2C1();
sensor_result1_2 = I2C1RCV; // Result of the 1 shot conversion
//----------------------------------------------------------------
StopI2C1(); // Initiate stop sequence
IdleI2C1();
CloseI2C1();
}
|
|
|
|
|
|
Re:Getting ADC result
|
|
Date: 2007/05/01 15:32
|
By: dariog
|
Status: User
|
|
|
Karma: 6  
|
|
| Posts: 107 |   | |
|
I may be wrong, but I always see your code Writing bytes which end with "1", which in I2C terms usually means "Read". So, IMO, you're never Writing nor configuring the ADC.
I don't have datasheet for that part, but you should look again into it, to see the proper sequence to get it working.
|
|
|
|
|
|
Re:Getting ADC result
|
|
Date: 2007/05/03 13:05
|
By: rwillis
|
Status: User
|
|
|
Karma: 0  
|
|
| Posts: 2 |   | |
|
Hi
Thanks for your reply. I revised what I had done, and tried a differnet way, this works for me now, it may be of use to some one in the future.
Excuse the code, I'm new to this C stuff!
| Code: |
// Configure I2C module
unsigned int config2,config1;
config2 = 0x11; // Set baud rate to 100KHz
// Configure I2C for 7 bit address mode
config1 = ( I2C1_ON & I2C1_IDLE_CON & I2C1_CLK_HLD
& I2C1_IPMI_DIS & I2C1_7BIT_ADD
& I2C1_SLW_DIS & I2C1_SM_DIS &
I2C1_GCALL_DIS & I2C1_STR_DIS &
I2C1_NACK & I2C1_ACK_DIS & I2C1_RCV_DIS &
I2C1_STOP_DIS & I2C1_RESTART_DIS
& I2C1_START_DIS );
OpenI2C1(config1,config2);
StopI2C1(); // Initiate Stop
IdleI2C1(); // Stopped
StartI2C1(); // Initiate Start
while(I2C1CONbits.SEN); // Wait till Start sequence is completed
MasterWriteI2C1(0xD1); // Write Slave address and set master for transmission
while(I2C1STATbits.TBF); // wait for 8 clock cycs
while(I2C1STATbits.ACKSTAT);
MasterWriteI2C1(_1shot); // Configure MCP3421 for 1 SHOT - 14Bit 60SPS - 8VV
while(I2C1STATbits.TBF); // wait for 8 clock cycs
while(I2C1STATbits.ACKSTAT);
if(I2C1STATbits.ACKSTAT)
{
Nop(); Nop(); Nop(); // NACK
I2C1CONbits.RCEN = 1;
Nop(); Nop(); Nop(); Nop(); Nop();
}
else
{
Nop(); Nop(); Nop(); // ACK
// High Data byte 1
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN); // RCEN cleared in HW
while(I2C1STATbits.ACKSTAT);
sensor_high_byte = I2C1RCV; // read RX buffer
I2C1CONbits.ACKDT = 0; // select ACK
I2C1CONbits.ACKEN = 1; // send ACK/NACK
while(I2C1CONbits.ACKEN); // cleared in HW
while(I2C1STATbits.ACKSTAT);
// Low Data byte 2
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN); // RCEN cleared in HW
while(I2C1STATbits.ACKSTAT);
sensor_low_byte = I2C1RCV; // read RX buffer
I2C1CONbits.ACKDT = 0; // select ACK
I2C1CONbits.ACKEN = 1; // send ACK/NACK
while(I2C1CONbits.ACKEN); // cleared in HW
while(I2C1STATbits.ACKSTAT);
// Configuration byte 3
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN); // RCEN cleared in HW
while(I2C1STATbits.ACKSTAT);
sensor_config_byte = I2C1RCV; // read RX buffer
I2C1CONbits.ACKDT = 0; // select ACK
I2C1CONbits.ACKEN = 1; // send ACK/NACK
while(I2C1CONbits.ACKEN); // cleared in HW
while(I2C1STATbits.ACKSTAT);
StopI2C1();
Nop(); Nop(); Nop(); Nop(); Nop();
}//end if
CloseI2C1();
|
Thanks again
Russ
|
|
|
|
|
Re:Getting ADC result
|
|
Date: 2007/05/15 11:51
|
By: dariog
|
Status: User
|
|
|
Karma: 6  
|
|
| Posts: 107 |   | |
|
Ok, not sure how it went, but good anyway
|
|
|
|
|
|
Re:Getting ADC result
|
|
Date: 2008/06/16 11:22
|
By: RWillis
|
Status: Visitor
|
|
|
|
|
|
|
Hi
Sorry for delay in updating this code, but finally I have something that works and is tested, extensively. The code snippet below is just that a snippet, its what allows you to configure the MPC3421 and read a value from it into the ADCReading variable.
You can use this as a basis to setup your own routines, etc. It hasn't actually taken me all this time to figure this out its just I'm very busy and completely forget to post it here until now.
Anyway hope it will help someone somewhere.
Russ
| Code: |
// set up the I2C and MCP3421 using the peripheral library
// 400kHz using 40MHz clock
OpenI2C1(0x8000, 92);
StopI2C1();
while(I2C1CONbits.PEN);
// set the 3421 into 16bit mode
StartI2C1();
while(I2C1CONbits.SEN);
if (MasterWriteI2C1(0xD0) == 0) {
// wait for data to end transmission
while(I2C1STATbits.TRSTAT);
// wait for ack
while(I2C1STATbits.ACKSTAT);
// set into continuous mode 16bit - 8V/V
MasterWriteI2C1(0x18);
while(I2C1STATbits.TRSTAT);
while(I2C1STATbits.ACKSTAT);
StopI2C1();
while(I2C1CONbits.PEN);
}
StartI2C1();
while(I2C1CONbits.SEN);
// write Slave address
if (MasterWriteI2C1(0xD1) == 0) {
// wait for the data to be written
while(I2C1STATbits.TRSTAT);
// wait for ACK
while(I2C1STATbits.ACKSTAT);
// now read 3 bytes of data
if (MastergetsI2C1(3, i2c_data, 1000) == 0) {
// successful read so convert the result
// i2c_data[0:1] form the 16 bit result
// i2c_data[2] = config byte
if ((i2c_data[2] & 0x80) == 0) {
// new data available
ADCReading = (i2c_data[0] << 8) | i2c_data[1];
}
}
StopI2C1();
while(I2C1CONbits.PEN);
}
|
|
|
|
|