bgdev
Newbie level 1
- Joined
- Feb 2, 2015
- Messages
- 1
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1
- Activity points
- 9
Hi I'm trying to read the temperature data from a sensor MCP9808 with a PIC12F683 through the i2c bus and then store it into the pic internal eeprom, working with mplab and XC8 C compiler.
From the MCP9808 datasheet, these are the steps:
I have found a PIC12F675 bit banging library that should be fine for my purpose.
This is my code:
msb and lsb are always 0x00, I really can not find the problem, hope someone can help.
thanks
From the MCP9808 datasheet, these are the steps:
Code:
i2c_start(); // send START command
i2c_write (AddressByte & 0xFE); //WRITE Command (see Section 4.1.4 “Address Byte”) also, make sure bit 0 is cleared ‘0’
i2c_write(0x05); // Write TA Register Address
i2c_start(); //Repeat START
i2c_write(AddressByte | 0x01); // READ Command (see Section 4.1.4 “Address Byte”) also, make sure bit 0 is Set ‘1’
UpperByte = i2c_read(ACK); // READ 8 bits and Send ACK bit
LowerByte = i2c_read(NAK); // READ 8 bits and Send NAK bit
i2c_stop(); // send STOP command
I have found a PIC12F675 bit banging library that should be fine for my purpose.
This is my code:
Code:
[B]Includes.h[/B]
#ifndef __INCLUDES_H
#define __INCLUDES_H
// Define CPU Frequency
// This must be defined, if __delay_ms()
// or __delay_us() functions are used in the code
#define _XTAL_FREQ 4000000 // Hz
// Include files
#include <xc.h> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> /* For true/false definition */
#include <htc.h>
#include "I2C.h"
#endif
[B]I2C.h[/B]
#ifndef __I2C_H
#define __I2C_H
// Define i2c pins
#define SDA GP4 // Data pin for i2c
#define SCK GP5 // Clock pin for i2c
#define SDA_DIR TRISIO4 // Data pin direction
#define SCK_DIR TRISIO5 // Clock pin direction
#define DataPinADCMask ANS3 // It is attached on GP4(AN3) pin
#define ClockPinADCMask ANS3 // It is not attached on any ADC pin
// Define i2c speed
#define I2C_SPEED 1 // kbps
#define HalfBitDelay 500/I2C_SPEED // usec
// Define macros
#define Set_SDA_Low SDA_DIR = 0
#define Set_SDA_High SDA_DIR = 1
#define Set_SCK_Low SCK_DIR = 0
#define Set_SCK_High SCK_DIR = 1
//Function Declarations
void InitI2C(void);
void I2C_Start(void);
void I2C_ReStart(void);
void I2C_Stop(void);
void I2C_Send_ACK(void);
void I2C_Send_NACK(void);
bit I2C_Write_Byte(unsigned char);
unsigned char I2C_Read_Byte(void);
#endif
[B]I2C.c[/B]
#include "Includes.h"
// Function Purpose: Set initial values of SCK and SDA pins
void InitI2C(void)
{
DataPinADCMask = 1; // Make analog output
ClockPinADCMask = 1; // Make analog output
// Make SDA and SCK pins input initially
SDA_DIR = 1;
SCK_DIR = 1;
// Write zero in output register of SDA and SCK pin
SDA = 0;
SCK = 0;
}
// Function Purpose: I2C_Start sends start bit sequence
void I2C_Start(void)
{
SDA = 0; // Write zero in output register
SCK = 0; // of SDA and SCK pin
Set_SCK_High; // Make SCK pin high
Set_SDA_High; // Make SDA pin High
__delay_us(HalfBitDelay); // Half bit delay
Set_SDA_Low; // Make SDA Low
__delay_us(HalfBitDelay); // Half bit delay
}
// Function Purpose: I2C_ReStart sends start bit sequence
void I2C_ReStart(void)
{
Set_SCK_Low; // Make SCK pin low
__delay_us(HalfBitDelay/2); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_High; // Make SDA pin High
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SDA_Low; // Make SDA Low
__delay_us(HalfBitDelay/2); // 1/4 bit delay
}
//Function : I2C_Stop sends stop bit sequence
void I2C_Stop(void)
{
Set_SCK_Low; // Make SCK pin low
__delay_us(HalfBitDelay/2); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_Low; // Make SDA pin low
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SDA_High; // Make SDA high
__delay_us(HalfBitDelay/2); // 1/4 bit delay
}
//Function : I2C_Send_ACK sends ACK bit sequence
void I2C_Send_ACK(void)
{
Set_SCK_Low; // Make SCK pin low
__delay_us(HalfBitDelay/2); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_Low; // Make SDA Low
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
__delay_us(HalfBitDelay); // Half bit delay
}
//Function : I2C_Send_NACK sends NACK bit sequence
void I2C_Send_NACK(void)
{
Set_SCK_Low; // Make SCK pin low
__delay_us(HalfBitDelay/2); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_High; // Make SDA high
__delay_us(HalfBitDelay/2); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
__delay_us(HalfBitDelay); // Half bit delay
}
// Function Purpose: I2C_Write_Byte transfers one byte
bit I2C_Write_Byte(unsigned char Byte)
{
static bit ACK = 0;
unsigned char i; // Variable to be used in for loop
for(i=0;i<8;i++) // Repeat for every bit
{
Set_SCK_Low; // Make SCK pin low
__delay_us(HalfBitDelay/2); // Data pin should change it's value,
// when it is confirm that SCK is low
if((Byte<<i)&0x80) // Place data bit value on SDA pin
Set_SDA_High; // If bit is high, make SDA high
else // Data is transferred MSB first
Set_SDA_Low; // If bit is low, make SDA low
__delay_us(HalfBitDelay/2); // Toggle SCK pin
Set_SCK_High; // So that slave can
__delay_us(HalfBitDelay); // latch data bit
}
// Get ACK from slave
Set_SCK_Low;
Set_SDA_High;
__delay_us(HalfBitDelay);
Set_SCK_High;
__delay_us(HalfBitDelay);
DataPinADCMask = 0; // Make digital input
ACK = SDA; // Read data pin status
DataPinADCMask = 1; // Make analog output
return ACK;
}
// Function Purpose: I2C_Read_Byte reads one byte
unsigned char I2C_Read_Byte(void)
{
unsigned char i, RxData = 0;
for(i=0;i<8;i++)
{
Set_SCK_Low; // Make SCK pin low
Set_SDA_High; // Don't drive SDA
__delay_us(HalfBitDelay); // Half bit delay
Set_SCK_High; // Make SCK pin high
__delay_us(HalfBitDelay/2); // 1/4 bit delay
DataPinADCMask = 0; // Make digital input
RxData = RxData|(SDA<<(7-i)); // Captured received bit
DataPinADCMask = 1; // Make analog output
__delay_us(HalfBitDelay/2); // 1/4 bit delay
}
return RxData; // Return received byte
}
[B]main.c[/B]
#include "Includes.h"
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown Out Detect (BOR enabled)
#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
void InitCCT(void)
{
ANSEL = 0x00; // Set ports as digital I/O, not analog input
ADCON0 = 0x00; // Shut off the A/D Converter
CMCON0 = 0x07; // Shut off the Comparator
VRCON = 0x00; // Shut off the Voltage Reference
TRISIO = 0x00; // GP3 input, rest all output
GPIO = 0x00; // Make all pins 0
}
int main(int argc, char** argv) {
unsigned char msb;
unsigned char lsb;
InitCCT(); // Turn off ADC and comparator to make pins digital IOs
InitI2C(); // Initialize i2c pins
__delay_ms(100);
// Send stop bit on i2c
I2C_Start(); // Send start bit on i2c
I2C_Write_Byte((unsigned char)0x18 & 0xFE);
I2C_Write_Byte((unsigned char)0x05);
I2C_Start();
I2C_Write_Byte((unsigned char)0x18 | 0x01); // Send 0xA0 on i2c
msb = I2C_Read_Byte(); // Read value from i2c
I2C_Send_ACK(); // Send ACK bit on i2c
lsb = I2C_Read_Byte(); // Read value from i2c
I2C_Send_NACK(); // Send ACK bit on i2c
I2C_Stop();
eeprom_write(0x00, msb);
eeprom_write(0x01, lsb);
while(1){
}
}
msb and lsb are always 0x00, I really can not find the problem, hope someone can help.
thanks