|
|
View previous topic :: View next topic |
Author |
Message |
kufre
Joined: 19 Oct 2013 Posts: 7 Location: Nigeria
|
MPL3115A2 not working with PIC16F877A |
Posted: Thu Dec 12, 2013 7:37 pm |
|
|
Hi Guys!
I have a new MPL3115A2 Temperature/Pressure/Altitude breakout board from Sparkfun as part of my school project. The sensor is a two wire serial (I2C) device. Am interested in reading only the Pressure.
I've connected the SDA and SCL on the breakout board to the SDA and SCL pins of the PIC16F877A respectively. The sensor is powered with +3.3vcc and the PIC is +5vcc both of them has common Gnd.
I have run the diagnostic test @ http://www.ccsinfo.com/forum/viewtopic.php?t=49713 and receive 0xC0 as the slave address.
The issue is when all of them are powered on, I'll get MSB:FF CSB: FF LSB: FF which shouldn't be so. The combination of the MSB, CSB, LSB should give me the pressure reading.
Also, from the datasheet, when reading the "WHO_AM_I" register (0x0C), the device should response with 0xC4, but what am getting is still 0xFF.
Here is the code, am using CCS C v4.068
Code: |
#include <16F877A.h>
#FUSES NOWDT
#FUSES HS
#FUSES BROWNOUT
#FUSES NOLVP, PUT
#use delay(clock=20000000)
// i2c preprocessor directives
#use i2c(Master, sda=PIN_C4,scl=PIN_C3, FORCE_HW, SMBUS)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=UART, ERRORS,BRGH1OK)
#define OUT_P_MSB 0x01
#define WHO_AM_I 0x0C
#define PT_DATA_CFG 0x13
#define CTRL_REG1 0x26
#define F_SETUP 0x0F
#define MPL3115A2_ADDRESS 0xC0 //0x60 7-bit I2C address 0xC0 8-bit I2C address
BYTE IIC_Read(BYTE regAddr);
void IIC_Write(byte regAddr, byte value);
void MPL3115A2_request(void);
void toggleOneShot(void);
void readPressure(void);
void setModeBarometer(void);
void enableEventFlags(void);
BYTE IIC_Read(BYTE regAddr)
{
BYTE re;
// This function reads one byte over IIC
i2c_start();
i2c_write(MPL3115A2_ADDRESS);
i2c_write(regAddr); // Address of CTRL_REG1
re=i2c_read(0);
i2c_stop();
return re;
}
void IIC_Write(BYTE regAddr, BYTE value)
{
// This function writes one byto over IIC
i2c_start();
i2c_write(MPL3115A2_ADDRESS);
i2c_write(regAddr);
i2c_write(value);
i2c_stop();
}
/* send a measurement request. in ~40ms issue a data request */
void MPL3115A2_request(void)
{
BYTE re;
fprintf(UART, "Request..\r\n");
re = IIC_Read(WHO_AM_I);
fprintf(UART, "WHO_AM_I: %X\r\n",re);
}
//Clears then sets the OST bit which causes the sensor to immediately take another reading
//Needed to sample faster than 1Hz
void toggleOneShot(void)
{
BYTE tempSetting;
tempSetting = IIC_Read(CTRL_REG1); //Read current settings
tempSetting &= ~(1<<1); //Clear OST bit
IIC_Write(CTRL_REG1, tempSetting);
tempSetting = IIC_Read(CTRL_REG1); //Read current settings to be safe
tempSetting |= (1<<1); //Set OST bit
IIC_Write(CTRL_REG1, tempSetting);
}
//Reads the current pressure in Pa
//Unit must be set in barometric pressure mode
void readPressure(void)
{
BYTE msb, csb, lsb;
toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading
delay_ms(10);
// start i2c communication
i2c_start();
// Read pressure registers
i2c_write(MPL3115A2_ADDRESS);
i2c_write(OUT_P_MSB); // Address of data to get
msb = i2c_read(1);
csb = i2c_read(1);
lsb = i2c_read(0);
fprintf(UART, "msb :%X csb: %X lsb: %X\r\n", msb, csb, lsb);
}
//Sets the mode to Barometer
//CTRL_REG1, ALT bit
void setModeBarometer(void)
{
BYTE tempSetting;
tempSetting = IIC_Read(CTRL_REG1); //Read current settings
tempSetting &= ~(1<<7); //Clear ALT bit
IIC_Write(CTRL_REG1, tempSetting);
}
//Call with a rate from 0 to 7.
//Sets the over sample rate. Datasheet calls for 128 but you can set it
//from 1 to 128 samples. The higher the oversample rate the greater
//the time between data samples.
void setOversampleRate(BYTE sampleRate)
{
BYTE tempSetting;
if(sampleRate > 7) sampleRate = 7; //OS cannot be larger than 0b.0111
sampleRate <<= 3; //Align it for the CTRL_REG1 register
tempSetting = IIC_Read(CTRL_REG1); //Read current settings
tempSetting &= 0b11000111; //Clear out old OS bits
tempSetting |= sampleRate; //Mask in new OS bits
IIC_Write(CTRL_REG1, tempSetting);
}
//Enables the pressure and temp measurement event flags so that we can
//test against them. This is recommended in datasheet during setup.
void enableEventFlags(void)
{
IIC_Write(PT_DATA_CFG, 0x07); // Enable all three pressure and temp event flags
}
void main(void)
{
delay_ms(1000);
fprintf(UART, "Reading Start....\r\n");
MPL3115A2_request();
// Configure the sensor
setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa
setOversampleRate(7); // Set Oversample to the recommended 128
enableEventFlags(); // Enable all three pressure and temp event flags
delay_ms(20);
while(1) {
readPressure();
delay_ms(3000);
}
}
|
Result:
Quote: |
Reading Start....
Request..
WHO_AM_I: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
msb :FF csb: FF lsb: FF
|
Is anything wrong with the code or is there anything am missing out? Pls I need your help.
Thanks |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Dec 12, 2013 8:18 pm |
|
|
comment: you need correct hardware before debugging software..
comment: It is never a good idea to mix 5V PICs with 3V peripherals. Best solution is to use 3V PICS with 3V peripherals. Next is to use a 5V to 3V logic level translation chips in between. Next would be to use I/O pins that WILL allow the PIC to see proper logic levels.Check the datasheet to see which pins would see a '1' when input is 3.3volts( homework for you).
comment: the 16F877 is 'obsolete' or at least 'at end of production life',if possible, choose a current PIC of the LF series( good for 3V) that is pin compatible.Newer PICs will have more features at a lower price.
comment: check the comments at the sparkfun website about the device,seems there's a lot of talk about it...maybe Google for PIC related info.
comment:in the I2C setup options you have SMBUS enabled, is this correct? what speed is the I2C bus(device max is 400KHz)?
hth
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 12, 2013 10:04 pm |
|
|
He's using the SMBUS option for #use i2c. With that parameter, a 5v
PIC will work with a 3.3v i2c slave (with 3.3v pull-ups).
One of the problems is in the IIC_Read() function. It should be replaced by this:
Code: |
BYTE IIC_Read(BYTE regAddr)
{
BYTE re;
i2c_start();
i2c_write(MPL3115A2_ADDRESS);
i2c_write(regAddr);
i2c_start();
i2c_write(MPL3115A2_ADDRESS +1);
re=i2c_read(0);
i2c_stop();
return re;
} |
|
|
|
kufre
Joined: 19 Oct 2013 Posts: 7 Location: Nigeria
|
MPL3115A2 not working with PIC16F877A |
Posted: Sat Dec 14, 2013 6:47 am |
|
|
Thanks PCM Programmer for your help!
I did exactly as your code and its working now. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|