2017-10-16 5 views
0

J'essaye de migrer de PIC16F886 à PIC18F24K40. NOw ici j'essaye de communiquer PIC18F24K40 avec DS1307 et l'afficher sur l'affichage de 4 segments. J'ai testé mon code sur PIC16F886 mais pas sur PIC18F24K40. SInce PIC18F24K40 utilise MPLAB X ide et crée un fichier c I2c c basé sur la configuration de code MCC et un fichier .h. Quelqu'un peut-il suggérer ce que j'ai fait de mal dans le code ci-dessous?I2c Données d'esclave PIC MPLAB X

Je ne pouvais pas mettre à jour l'heure une fois écrite.

/** 
    Generated Main Source File 

    Company: 
    Microchip Technology Inc. 

    File Name: 
    main.c 

    Summary: 
    This is the main file generated using MPLAB(c) Code Configurator 

    Description: 
    This header file provides implementations for driver APIs for all modules selected in the GUI. 
    Generation Information : 
     Product Revision : MPLAB(c) Code Configurator - 4.15 
     Device   : PIC18F24K40 
     Driver Version : 2.00 
    The generated drivers are tested against the following: 
     Compiler   : XC8 1.35 
     MPLAB    : MPLAB X 3.40 
*/ 

/* 
    (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this 
    software and any derivatives exclusively with Microchip products. 

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER 
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED 
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A 
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION 
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. 

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, 
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND 
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS 
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE 
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN 
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, 
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. 

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE 
    TERMS. 
*/ 

#include "mcc_generated_files/mcc.h" 

#include "mcc_generated_files/i2c1.h" 
uint8_t status; 


#define DS1307_RETRY_MAX 100 // define the retry count 
#define Ds1307_ADDRESS 0xD0 // slave device address 
#define RTC_addres 0x68 // RTC slave device address 

//static unsigned char readI2C[10], writeI2C[4]; 

#define buffersize 20 
static unsigned char writeBuffer[buffersize]; //Buffer for I2C writing. 
static unsigned char readbuffer[buffersize]; // Buffer for I2C reading. 

uint8_t second; 
uint8_t start_addres; 
uint8_t length; 
//I2C1_MESSAGE_STATUS w_status; 



    uint8_t   sourceData[] = {0x1A, 0x2A, 0x4A, 0x8A,0x1A, 0x2A, 0x4A, 0x8A,0x1A, 0x2A, 0x4A, 0x8A,0x1A, 0x2A, 0x4A, 0x8A}; 
    uint8_t   addressBuffer[] = {0xAB,0x10} ; //Put your address here 
    uint8_t   readBuffer[16]; 
    uint8_t readByte; 



# define LED RC7 

unsigned int i; 
unsigned int count; 
unsigned int x; 
unsigned short sec; 
unsigned short min; 
unsigned short hour; 
unsigned short date; 
unsigned short month; 
unsigned short year; 
unsigned short day; 
unsigned short int temp=0; 
unsigned short r_data; 
#define Seg1 0x01 
#define Seg2 0x02 
#define Seg3 0x04 
#define Seg4 0x08 
#define Seg5 0x10 
#define Seg6 0x20 



unsigned short int cnt, num,Dgt=0;; 
unsigned short int temp1,temp2,temp3; 


void Delay(int k) 
{ 
    for(i=0;i<=k;i++); 

} 

void Blink_LED() 
{ 
    LED=!LED; 
    Delay(10000); 

} 



    void SetSeg(unsigned short data, unsigned short segno) 

    { 
        switch(data) 
        { 
         case 0: PORTB = 0x3F; break; 
         case 1: PORTB = 0x06; break; 
         case 2: PORTB = 0x5B; break; 
         case 3: PORTB = 0x4F; break; 
         case 4: PORTB = 0x66; break; 
         case 5: PORTB = 0x6D; break; 
         case 6: PORTB = 0x7D; break; 
         case 7: PORTB = 0x07; break; 
         case 8: PORTB = 0x7F; break; 
         case 9: PORTB = 0x6F; break; 
         default : PORTB = 0X00; break; 
        } 

      if(segno==1) 
        { 
        PORTA = Seg4; 
        } 
      if(segno==2) 
        { 
        PORTA = Seg3; 
        } 
      if(segno==3) 
        { 
        PORTA = Seg2; 
        } 
      if(segno==4) 
        { 
        PORTA = Seg1; 
        } 


    } 


    unsigned int bcdtodecimal(unsigned int bcd) 
{ 
    unsigned int decimal; 
    decimal = (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F); 
    return decimal; 
} 



void wait_mssp(void) 
{ 
while(!PIR3bits.SSP1IF); 
PIR3bits.SSP1IF =0; 
} 



void ds1307_write(unsigned char addr ,unsigned char data) 
{ 
SSP1CON2bits.SEN =1; //Start bit 

//SSP1BUF = 0XD0; //slave address(address of ds1307) + write bit 
    SSP1BUF =0X68; 
SSP1BUF =addr; 

SSP1BUF = data; 

SSP1CON2bits.PEN =1; //stop bit 

} 


unsigned int ds1307_read(unsigned char addr) 
{ 
SSP1CON2bits.RSEN =1; 

//SSP1BUF =0XD0; //slave address(address of ds1307) + write bit; 
    SSP1BUF =0X68; 
SSP1BUF =addr; 

SSP1CON2bits.RSEN =1; 

//SSP1BUF =0XD1; //slave address(address of ds1307) + read bit; 

    SSP1BUF =0X69; 
SSP1CON2bits.RCEN =1; 

SSP1CON2bits.ACKDT=1; 
SSP1CON2bits.ACKEN =1; 
SSP1CON2bits.PEN=1; 

x = SSP1BUF; 
return (x); 
} 

void SetDateTime() 
{ 
      ds1307_write(0X00,0x03); 
      ds1307_write(0X01,0X07); 
      ds1307_write(0X02,0X00); 
       ds1307_write(0X3,0X01); 
      ds1307_write(0X04,0x07); 
      ds1307_write(0X5,0X08); 
      ds1307_write(0X6,0X08); 
} 


void GetDateTime() 
{ 
      sec = ds1307_read(0X00); 
       sec=bcdtodecimal(sec); 
       min = ds1307_read(0X01); 
       min = bcdtodecimal(min); 
       hour = ds1307_read(0X02); 
      hour=bcdtodecimal(hour); 
       day= ds1307_read(0X03); 
       day = bcdtodecimal(day); 
       date= ds1307_read(0X04); 
       date=bcdtodecimal(date); 
       month= ds1307_read(0X05); 
       month = bcdtodecimal(month); 
       year= ds1307_read(0X06); 
       year= bcdtodecimal(year); 
} 



void Blink_Count() 
{ 
    if(PIR0bits.TMR0IF == 1) 
    { 
     PIR0bits.TMR0IF =0; 
     count=count+1; 
     if(count>=15) 
     { 
      LED=!LED; 
      count=0; 
//    SetSeg(min/10,4); 
//     SetSeg(min%10,3); 
//     SetSeg(sec/ 10,2); 
//     SetSeg(sec%10,1); 

     } 

    } 

} 


void main(void) 
{ 
    // Initialize the device 
    SYSTEM_Initialize(); 

    // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts 
    // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global and Peripheral Interrupts 
    // Use the following macros to: 

    // Enable high priority global interrupts 
    //INTERRUPT_GlobalInterruptHighEnable(); 

    // Enable low priority global interrupts. 
    //INTERRUPT_GlobalInterruptLowEnable(); 

    // Disable high priority global interrupts 
    //INTERRUPT_GlobalInterruptHighDisable(); 

    // Disable low priority global interrupts. 
    //INTERRUPT_GlobalInterruptLowDisable(); 

    // Enable the Global Interrupts 
    //INTERRUPT_GlobalInterruptEnable(); 

    // Enable the Peripheral Interrupts 
    //INTERRUPT_PeripheralInterruptEnable(); 

    // Disable the Global Interrupts 
    //INTERRUPT_GlobalInterruptDisable(); 

    // Disable the Peripheral Interrupts 
    //INTERRUPT_PeripheralInterruptDisable(); 

    // I2C1_Initialize(); 


    SSP1CLKPPS = 0x0E; //RB6->MSSP:SCL; 
    SSP1DATPPS = 0x0C; //RB4->MSSP:SDA; 
    RB6PPS = 0x10; //RB6->MSSP:SCL; 
    RB4PPS = 0x11; //RB4->MSSP:SDA; 

     SetDateTime(); 
    while (1) 
    { 



    GetDateTime();     

     SetSeg(min/10,4); 
        SetSeg(min%10,3); 
        SetSeg(sec/ 10,2); 
        SetSeg(sec%10,1);    


    } 
} 

Répondre

0

D'après la configuration de code MCC et la bibliothèque utilisée ci-dessous. Mais je ne pouvais pas voir la mise à jour des paramètres sec après l'écriture.

void main(void) 
{ 

    uint8_t second; 
    uint8_t start_addres; 
    uint8_t length; 
    I2C1_MESSAGE_STATUS w_status; 
    I2C1_MESSAGE_STATUS r_status; 


    // Initialize the device 
    SYSTEM_Initialize(); 



    start_addres = 0; 
    length =12; 

    I2C1_MasterWriteTRBBuild(0X00, length, RTC_addres, &w_status); 


    while (1) 
    { 


    I2C1_MasterReadTRBBuild(&second, length, RTC_addres, &r_status); 
    I2C1_MasterRead(&second, length, RTC_addres, &r_status); 

    sec=second; 

    } 


} 

est un fichier I2C1.c THis créé après MCC

typedef union 
{ 
    struct 
    { 
      uint8_t full:1; 
      uint8_t empty:1; 
      uint8_t reserved:6; 
    }s; 
    uint8_t status; 
}I2C_TR_QUEUE_STATUS; 

/** 
    I2C Driver Queue Entry Type 

    @Summary 
    Defines the object used for an entry in the i2c queue items. 

    @Description 
    This defines the object in the i2c queue. Each entry is a composed 
    of a list of TRBs, the number of the TRBs and the status of the 
    currently processed TRB. 
*/ 
typedef struct 
{ 
    uint8_t        count;   // a count of trb's in the trb list 
    I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list;  // pointer to the trb list 
    I2C1_MESSAGE_STATUS   *pTrFlag;  // set with the error of the last trb sent. 
                 // if all trb's are sent successfully, 
                 // then this is I2C1_MESSAGE_COMPLETE 
} I2C_TR_QUEUE_ENTRY; 

/** 
    I2C Master Driver Object Type 

    @Summary 
    Defines the object that manages the i2c master. 

    @Description 
    This defines the object that manages the sending and receiving of 
    i2c master transactions. 
    */ 

typedef struct 
{ 
    /* Read/Write Queue */ 
    I2C_TR_QUEUE_ENTRY   *pTrTail;  // tail of the queue 
    I2C_TR_QUEUE_ENTRY   *pTrHead;  // head of the queue 
    I2C_TR_QUEUE_STATUS   trStatus;  // status of the last transaction 
    uint8_t       i2cDoneFlag; // flag to indicate the current 
                // transaction is done 
    uint8_t       i2cErrors;  // keeps track of errors 


} I2C_OBJECT ; 

/** 
    I2C Master Driver State Enumeration 

    @Summary 
    Defines the different states of the i2c master. 

    @Description 
    This defines the different states that the i2c master 
    used to process transactions on the i2c bus. 
*/ 

typedef enum 
{ 
    S_MASTER_IDLE, 
    S_MASTER_RESTART, 
    S_MASTER_SEND_ADDR, 
    S_MASTER_SEND_DATA, 
    S_MASTER_SEND_STOP, 
    S_MASTER_ACK_ADDR, 
    S_MASTER_RCV_DATA, 
    S_MASTER_RCV_STOP, 
    S_MASTER_ACK_RCV_DATA, 
    S_MASTER_NOACK_STOP, 
    S_MASTER_SEND_ADDR_10BIT_LSB, 
    S_MASTER_10BIT_RESTART, 

} I2C_MASTER_STATES; 

/** 
Section: Macro Definitions 
*/ 

/* defined for I2C1 */ 

#ifndef I2C1_CONFIG_TR_QUEUE_LENGTH 
     #define I2C1_CONFIG_TR_QUEUE_LENGTH 1 
#endif 

#define I2C1_TRANSMIT_REG      SSP1BUF     // Defines the transmit register used to send data. 
#define I2C1_RECEIVE_REG      SSP1BUF     // Defines the receive register used to receive data. 

// The following control bits are used in the I2C state machine to manage 
// the I2C module and determine next states. 
#define I2C1_WRITE_COLLISION_STATUS_BIT   SSP1CON1bits.WCOL  // Defines the write collision status bit. 
#define I2C1_MODE_SELECT_BITS     SSP1CON1bits.SSPM  // I2C Master Mode control bit. 
#define I2C1_MASTER_ENABLE_CONTROL_BITS   SSP1CON1bits.SSPEN // I2C port enable control bit. 

#define I2C1_START_CONDITION_ENABLE_BIT   SSP1CON2bits.SEN  // I2C START control bit. 
#define I2C1_REPEAT_START_CONDITION_ENABLE_BIT SSP1CON2bits.RSEN  // I2C Repeated START control bit. 
#define I2C1_RECEIVE_ENABLE_BIT     SSP1CON2bits.RCEN  // I2C Receive enable control bit. 
#define I2C1_STOP_CONDITION_ENABLE_BIT   SSP1CON2bits.PEN  // I2C STOP control bit. 
#define I2C1_ACKNOWLEDGE_ENABLE_BIT    SSP1CON2bits.ACKEN // I2C ACK start control bit. 
#define I2C1_ACKNOWLEDGE_DATA_BIT    SSP1CON2bits.ACKDT // I2C ACK data control bit. 
#define I2C1_ACKNOWLEDGE_STATUS_BIT    SSP1CON2bits.ACKSTAT // I2C ACK status bit. 

#define I2C1_7bit true 
/** 
Section: Local Functions 
*/ 

void I2C1_FunctionComplete(void); 
void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code); 

/** 
Section: Local Variables 
*/ 

static I2C_TR_QUEUE_ENTRY     i2c1_tr_queue[I2C1_CONFIG_TR_QUEUE_LENGTH]; 
static I2C_OBJECT       i2c1_object; 
static I2C_MASTER_STATES     i2c1_state = S_MASTER_IDLE; 
static uint8_t         i2c1_trb_count = 0; 

static I2C1_TRANSACTION_REQUEST_BLOCK  *p_i2c1_trb_current = NULL; 
static I2C_TR_QUEUE_ENTRY     *p_i2c1_current = NULL; 


/** 
    Section: Driver Interface 
*/ 


void I2C1_Initialize(void) 
{ 
    i2c1_object.pTrHead = i2c1_tr_queue; 
    i2c1_object.pTrTail = i2c1_tr_queue; 
    i2c1_object.trStatus.s.empty = true; 
    i2c1_object.trStatus.s.full = false; 

    i2c1_object.i2cErrors = 0; 

    // SMP Standard Speed; CKE enabled; 
    SSP1STAT = 0xC0; 
    // SSPEN enabled; CKP disabled; SSPM FOSC/4_SSPxADD_I2C; 
    SSP1CON1 = 0x28; 
    // SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled; 
    SSP1CON3 = 0x00; 
    // Baud Rate Generator Value: SSPADD 2; 
    SSP1ADD = 0x02; 


    // clear the master interrupt flag 
    PIR3bits.SSP1IF = 0; 
    // enable the master interrupt 
    PIE3bits.SSP1IE = 1; 

} 


uint8_t I2C1_ErrorCountGet(void) 
{ 
    uint8_t ret; 

    ret = i2c1_object.i2cErrors; 
    return ret; 
} 

void I2C1_ISR (void) 
{ 

    static uint8_t *pi2c_buf_ptr; 
    static uint16_t i2c_address   = 0; 
    static uint8_t i2c_bytes_left  = 0; 
    static uint8_t i2c_10bit_address_restart = 0; 

    PIR3bits.SSP1IF = 0; 

    // Check first if there was a collision. 
    // If we have a Write Collision, reset and go to idle state */ 
    if(I2C1_WRITE_COLLISION_STATUS_BIT) 
    { 
     // clear the Write colision 
     I2C1_WRITE_COLLISION_STATUS_BIT = 0; 
     i2c1_state = S_MASTER_IDLE; 
     *(p_i2c1_current->pTrFlag) = I2C1_MESSAGE_FAIL; 

     // reset the buffer pointer 
     p_i2c1_current = NULL; 

     return; 
    } 

    /* Handle the correct i2c state */ 
    switch(i2c1_state) 
    { 
     case S_MASTER_IDLE: /* In reset state, waiting for data to send */ 

      if(i2c1_object.trStatus.s.empty != true) 
      { 
       // grab the item pointed by the head 
       p_i2c1_current  = i2c1_object.pTrHead; 
       i2c1_trb_count  = i2c1_object.pTrHead->count; 
       p_i2c1_trb_current = i2c1_object.pTrHead->ptrb_list; 

       i2c1_object.pTrHead++; 

       // check if the end of the array is reached 
       if(i2c1_object.pTrHead == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH)) 
       { 
        // adjust to restart at the beginning of the array 
        i2c1_object.pTrHead = i2c1_tr_queue; 
       } 

       // since we moved one item to be processed, we know 
       // it is not full, so set the full status to false 
       i2c1_object.trStatus.s.full = false; 

       // check if the queue is empty 
       if(i2c1_object.pTrHead == i2c1_object.pTrTail) 
       { 
        // it is empty so set the empty status to true 
        i2c1_object.trStatus.s.empty = true; 
       } 

       // send the start condition 
       I2C1_START_CONDITION_ENABLE_BIT = 1; 

       // start the i2c request 
       i2c1_state = S_MASTER_SEND_ADDR; 
      } 

      break; 

     case S_MASTER_RESTART: 

      /* check for pending i2c Request */ 

      // ... trigger a REPEATED START 
      I2C1_REPEAT_START_CONDITION_ENABLE_BIT = 1; 

      // start the i2c request 
      i2c1_state = S_MASTER_SEND_ADDR; 

      break; 

     case S_MASTER_SEND_ADDR_10BIT_LSB: 

      if(I2C1_ACKNOWLEDGE_STATUS_BIT) 
      { 
       i2c1_object.i2cErrors++; 
       I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK); 
      } 
      else 
      { 
       // Remove bit 0 as R/W is never sent here 
       I2C1_TRANSMIT_REG = (i2c_address >> 1) & 0x00FF; 

       // determine the next state, check R/W 
       if(i2c_address & 0x01) 
       { 
        // if this is a read we must repeat start 
        // the bus to perform a read 
        i2c1_state = S_MASTER_10BIT_RESTART; 
       } 
       else 
       { 
        // this is a write continue writing data 
        i2c1_state = S_MASTER_SEND_DATA; 
       } 
      } 

      break; 

     case S_MASTER_10BIT_RESTART: 

      if(I2C1_ACKNOWLEDGE_STATUS_BIT) 
      { 
       i2c1_object.i2cErrors++; 
       I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK); 
      } 
      else 
      { 
       // ACK Status is good 
       // restart the bus 
       I2C1_REPEAT_START_CONDITION_ENABLE_BIT = 1; 

       // fudge the address so S_MASTER_SEND_ADDR works correctly 
       // we only do this on a 10-bit address resend 
       i2c_address = 0x00F0 | ((i2c_address >> 8) & 0x0006); 

       // set the R/W flag 
       i2c_address |= 0x0001; 

       // set the address restart flag so we do not change the address 
       i2c_10bit_address_restart = 1; 

       // Resend the address as a read 
       i2c1_state = S_MASTER_SEND_ADDR; 
      } 

      break; 

     case S_MASTER_SEND_ADDR: 

      /* Start has been sent, send the address byte */ 

      /* Note: 
       On a 10-bit address resend (done only during a 10-bit 
       device read), the original i2c_address was modified in 
       S_MASTER_10BIT_RESTART state. So the check if this is 
       a 10-bit address will fail and a normal 7-bit address 
       is sent with the R/W bit set to read. The flag 
       i2c_10bit_address_restart prevents the address to 
       be re-written. 
      */ 
      if(i2c_10bit_address_restart != 1) 
      { 
       // extract the information for this message 
       i2c_address = p_i2c1_trb_current->address; 
       pi2c_buf_ptr = p_i2c1_trb_current->pbuffer; 
       i2c_bytes_left = p_i2c1_trb_current->length; 
      } 

      // check for 10-bit address 
      if(!I2C1_7bit && (0x0 != i2c_address)) 
      { 
       if (0 == i2c_10bit_address_restart) 
       { 
        // we have a 10 bit address 
        // send bits<9:8> 
        // mask bit 0 as this is always a write      
        I2C1_TRANSMIT_REG = 0xF0 | ((i2c_address >> 8) & 0x0006); 
        i2c1_state = S_MASTER_SEND_ADDR_10BIT_LSB; 
       } 
       else 
       { 
        // resending address bits<9:8> to trigger read 
        I2C1_TRANSMIT_REG = i2c_address; 
        i2c1_state = S_MASTER_ACK_ADDR; 
        // reset the flag so the next access is ok 
        i2c_10bit_address_restart = 0; 
       } 
      } 
      else 
      { 
       // Transmit the address 
       I2C1_TRANSMIT_REG = i2c_address; 
       if(i2c_address & 0x01) 
       { 
        // Next state is to wait for address to be acked 
        i2c1_state = S_MASTER_ACK_ADDR; 
       } 
       else 
       { 
        // Next state is transmit 
        i2c1_state = S_MASTER_SEND_DATA; 
       } 
      } 
      break; 

     case S_MASTER_SEND_DATA: 

      // Make sure the previous byte was acknowledged 
      if(I2C1_ACKNOWLEDGE_STATUS_BIT) 
      { 
       // Transmission was not acknowledged 
       i2c1_object.i2cErrors++; 

       // Reset the Ack flag 
       I2C1_ACKNOWLEDGE_STATUS_BIT = 0; 

       // Send a stop flag and go back to idle 
       I2C1_Stop(I2C1_DATA_NO_ACK); 

      } 
      else 
      { 
       // Did we send them all ? 
       if(i2c_bytes_left-- == 0U) 
       { 
        // yup sent them all! 

        // update the trb pointer 
        p_i2c1_trb_current++; 

        // are we done with this string of requests? 
        if(--i2c1_trb_count == 0) 
        { 
         I2C1_Stop(I2C1_MESSAGE_COMPLETE); 
        } 
        else 
        { 
         // no!, there are more TRB to be sent. 
         //I2C1_START_CONDITION_ENABLE_BIT = 1; 

         // In some cases, the slave may require 
         // a restart instead of a start. So use this one 
         // instead. 
         I2C1_REPEAT_START_CONDITION_ENABLE_BIT = 1; 

         // start the i2c request 
         i2c1_state = S_MASTER_SEND_ADDR; 

        } 
       } 
       else 
       { 
        // Grab the next data to transmit 
        I2C1_TRANSMIT_REG = *pi2c_buf_ptr++; 
       } 
      } 
      break; 

     case S_MASTER_ACK_ADDR: 

      /* Make sure the previous byte was acknowledged */ 
      if(I2C1_ACKNOWLEDGE_STATUS_BIT) 
      { 

       // Transmission was not acknowledged 
       i2c1_object.i2cErrors++; 

       // Send a stop flag and go back to idle 
       I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK); 

       // Reset the Ack flag 
       I2C1_ACKNOWLEDGE_STATUS_BIT = 0; 
      } 
      else 
      { 
       I2C1_RECEIVE_ENABLE_BIT = 1; 
       i2c1_state = S_MASTER_ACK_RCV_DATA; 
      } 
      break; 

     case S_MASTER_RCV_DATA: 

      /* Acknowledge is completed. Time for more data */ 

      // Next thing is to ack the data 
      i2c1_state = S_MASTER_ACK_RCV_DATA; 

      // Set up to receive a byte of data 
      I2C1_RECEIVE_ENABLE_BIT = 1; 

      break; 

     case S_MASTER_ACK_RCV_DATA: 

      // Grab the byte of data received and acknowledge it 
      *pi2c_buf_ptr++ = I2C1_RECEIVE_REG; 

      // Check if we received them all? 
      if(--i2c_bytes_left) 
      { 

       /* No, there's more to receive */ 

       // No, bit 7 is clear. Data is ok 
       // Set the flag to acknowledge the data 
       I2C1_ACKNOWLEDGE_DATA_BIT = 0; 

       // Wait for the acknowledge to complete, then get more 
       i2c1_state = S_MASTER_RCV_DATA; 
      } 
      else 
      { 

       // Yes, it's the last byte. Don't ack it 
       // Flag that we will nak the data 
       I2C1_ACKNOWLEDGE_DATA_BIT = 1; 

       I2C1_FunctionComplete(); 
      } 

      // Initiate the acknowledge 
      I2C1_ACKNOWLEDGE_ENABLE_BIT = 1; 
      break; 

     case S_MASTER_RCV_STOP:     
     case S_MASTER_SEND_STOP: 

      // Send the stop flag 
      I2C1_Stop(I2C1_MESSAGE_COMPLETE); 
      break; 

     default: 

      // This case should not happen, if it does then 
      // terminate the transfer 
      i2c1_object.i2cErrors++; 
      I2C1_Stop(I2C1_LOST_STATE); 
      break; 

    } 
} 

void I2C1_FunctionComplete(void) 
{ 

    // update the trb pointer 
    p_i2c1_trb_current++; 

    // are we done with this string of requests? 
    if(--i2c1_trb_count == 0) 
    { 
     i2c1_state = S_MASTER_SEND_STOP; 
    } 
    else 
    { 
     i2c1_state = S_MASTER_RESTART; 
    } 

} 

void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code) 
{ 
    // then send a stop 
    I2C1_STOP_CONDITION_ENABLE_BIT = 1; 

    // make sure the flag pointer is not NULL 
    if (p_i2c1_current->pTrFlag != NULL) 
    { 
     // update the flag with the completion code 
     *(p_i2c1_current->pTrFlag) = completion_code; 
    } 

    // Done, back to idle 
    i2c1_state = S_MASTER_IDLE; 

} 

void I2C1_MasterWrite(
           uint8_t *pdata, 
           uint8_t length, 
           uint16_t address, 
           I2C1_MESSAGE_STATUS *pflag) 
{ 
    static I2C1_TRANSACTION_REQUEST_BLOCK trBlock; 

    // check if there is space in the queue 
    if (i2c1_object.trStatus.s.full != true) 
    { 
     I2C1_MasterWriteTRBBuild(&trBlock, pdata, length, address); 
     I2C1_MasterTRBInsert(1, &trBlock, pflag); 
    } 
    else 
    { 
     *pflag = I2C1_MESSAGE_FAIL; 
    } 

} 

void I2C1_MasterRead(
           uint8_t *pdata, 
           uint8_t length, 
           uint16_t address, 
           I2C1_MESSAGE_STATUS *pflag) 
{ 
    static I2C1_TRANSACTION_REQUEST_BLOCK trBlock; 



    // check if there is space in the queue 
    if (i2c1_object.trStatus.s.full != true) 
    { 
     I2C1_MasterReadTRBBuild(&trBlock, pdata, length, address); 
     I2C1_MasterTRBInsert(1, &trBlock, pflag); 
    } 
    else 
    { 
     *pflag = I2C1_MESSAGE_FAIL; 
    } 

} 

void I2C1_MasterTRBInsert(
           uint8_t count, 
           I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list, 
           I2C1_MESSAGE_STATUS *pflag) 
{ 

    // check if there is space in the queue 
    if (i2c1_object.trStatus.s.full != true) 
    { 
     *pflag = I2C1_MESSAGE_PENDING; 

     i2c1_object.pTrTail->ptrb_list = ptrb_list; 
     i2c1_object.pTrTail->count  = count; 
     i2c1_object.pTrTail->pTrFlag = pflag; 
     i2c1_object.pTrTail++; 

     // check if the end of the array is reached 
     if (i2c1_object.pTrTail == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH)) 
     { 
      // adjust to restart at the beginning of the array 
      i2c1_object.pTrTail = i2c1_tr_queue; 
     } 

     // since we added one item to be processed, we know 
     // it is not empty, so set the empty status to false 
     i2c1_object.trStatus.s.empty = false; 

     // check if full 
     if (i2c1_object.pTrHead == i2c1_object.pTrTail) 
     { 
      // it is full, set the full status to true 
      i2c1_object.trStatus.s.full = true; 
     } 

    } 
    else 
    { 
     *pflag = I2C1_MESSAGE_FAIL; 
    } 

    // for interrupt based 
    if (*pflag == I2C1_MESSAGE_PENDING) 
    { 
     while(i2c1_state != S_MASTER_IDLE); 
     { 
      // force the task to run since we know that the queue has 
      // something that needs to be sent 
      PIR3bits.SSP1IF = true; 
     } 
    } // block until request is complete 

} 

void I2C1_MasterReadTRBBuild(
           I2C1_TRANSACTION_REQUEST_BLOCK *ptrb, 
           uint8_t *pdata, 
           uint8_t length, 
           uint16_t address) 
{ 
    ptrb->address = address << 1; 
    // make this a read 
    ptrb->address |= 0x01; 
    ptrb->length = length; 
    ptrb->pbuffer = pdata; 
} 

void I2C1_MasterWriteTRBBuild(
           I2C1_TRANSACTION_REQUEST_BLOCK *ptrb, 
           uint8_t *pdata, 
           uint8_t length, 
           uint16_t address) 
{ 
    ptrb->address = address << 1; 
    ptrb->length = length; 
    ptrb->pbuffer = pdata; 
} 

bool I2C1_MasterQueueIsEmpty(void) 
{ 
    return(i2c1_object.trStatus.s.empty); 
} 

bool I2C1_MasterQueueIsFull(void) 
{ 
    return(i2c1_object.trStatus.s.full); 
}   

void I2C1_BusCollisionISR(void) 
{ 
    // enter bus collision handling code here 
}   


/** 
End of File 
*/