2016年7月27日 星期三

pic i2c example

Ref :  http://www.microchip.com/forums/m741878.aspx




用7688  和 pic 互通


當  pic 的 address 為2

7688  的address 要為 1 (2/2)




PIC 18F I2C / IIC Example

I don't know why, but I spent ages looking for simple working I2C/IIC code something like this and couldn't find anything.
This code works and I'm posting it here so the next person to go looking finds a better starting point.

 /* ***********************************************************
*
*  PIC C18 Example I2C SLAVE for PIC18F ()PIC18F45K20)
*  Author:  John Clegg 
*  Date:    26 August 2013
*
*  Read/write to a bank of 8 bit register values.
*  I2C read returns the contents of the current register, multi-byte
*  reads return subsequent register bytes. 
*  I2C write, the first data byte is the register address, subsequent bytes
*  are written, initially to the register address supplied, then to 
*  successive registers addresses.
************************************************************* */

/** C O N F I G U R A T I O N   B I T S ******************************/

#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF                       // CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30                        // CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768                                    // CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC       // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF                             // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                    // CONFIG5L
#pragma config CPB = OFF, CPD = OFF                                          // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF                // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                            // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF            // CONFIG7L
#pragma config EBTRB = OFF                                                   // CONFIG7H


/** I N C L U D E S **************************************************/
#include "p18f45k20.h"
#include "delays.h"

/** D E C L A R A T I O N S *******************************************/

#define I2C_ADDR    0xaa    // 8 bit address

typedef unsigned char   byte;
 void low_isr(void);
void high_isr(void);

volatile byte           i2c_reg_addr     = 0;
volatile byte           i2c_reg_map[16 ] = {0,};
volatile byte           i2c_byte_count   = 0;

/*
* For PIC18 devices the high interrupt vector is found at
* 00000008h. The following code will branch to the
* high_interrupt_service_routine function to handle
* interrupts that occur at the high vector.
*/
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm GOTO high_isr _endasm
}

#pragma code /* return to the default code section */
/*
* For PIC18 devices the low interrupt vector is found at
* 00000018h. The following code will branch to the
* low_interrupt_service_routine function to handle
* interrupts that occur at the low vector.
*/
#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
{
_asm GOTO low_isr _endasm
}

#pragma code /* return to the default code section */

void main (void)
{
    OSCCON            = 0x60;       // IRCFx = 110
    OSCTUNEbits.PLLEN = 0;          // x4 PLL disabled

    // Port D used for diagnostic LEDs
    TRISD      = 0b00111111;     // PORTD bit 7 to output (0) ; bits 6:0 are inputs (1)
    LATDbits.LATD7 = 0;             // RED LED 
    LATDbits.LATD6 = 0;             // YLW LED 
        
    // Setup MSSP in 7 bit I2C Slave mode
    TRISC          = 0b00011000;    // TRISC 3&4 (SCL & SDA) inputs
    LATC           = 0b00011000;
    SSPADD         = I2C_ADDR;      // Set I2C address
    SSPCON1        = 0x36;          // SSPEN: Synchronous Serial Port Enable bit - Enables the serial port and configures the SDA and SCL pins as the serial port pins
                                    // CKP: SCK Release Control bit              - Release clock
                                    // SSPM3:SSPM0: SSP Mode Select bits         - 0110 = I2C Slave mode, 7-bit address    
    SSPSTAT        = 0x00;
    SSPCON2        = 0x01;          // GCEN: General Call address (00h) (Slave mode only) 0 = General call address disabled
                                    // SEN: Start Condition Enable/Stretch Enable bit(1) ()Slave mode) 1 = Clock stretching is enabled 
    PIR1bits.SSPIF = 0;             // Clear MSSP interrupt request flag
    PIE1bits.SSPIE = 1;             // Enable MSSP interrupt enable bit
    INTCONbits.GIE_GIEH  = 1;       // GIE/GIEH: Global Interrupt Enable bit
    INTCONbits.PEIE_GIEL = 1;       // PEIE/GIEL: Peripheral Interrupt Enable bit

    while (1)
    {
        Delay1KTCYx(50);    // Delay 50 x 1000 = 50,000 cycles; 200ms @ 1MHz
    }    
}

#pragma interruptlow low_isr
void low_isr (void)
{
} 

#pragma interruptlow high_isr
void high_isr (void)
{
    byte    sspBuf;
    
    if (PIR1bits.SSPIF) {
        
        if (!SSPSTATbits.D_NOT_A) {
            //
            // Slave Address 
            //
            i2c_byte_count = 0;

            if (SSPSTATbits.BF) {
                // Discard slave address 
                sspBuf = SSPBUF;    // Clear BF
            }
            
            if (SSPSTATbits.R_NOT_W) {                
                // Reading - read from register map
                SSPCON1bits.WCOL = 0;
                SSPBUF           = i2c_reg_map[i2c_reg_addr++];
            } 
            
        } else {
            //
            // Data bytes 
            //
            i2c_byte_count++;

            if (SSPSTATbits.BF) {
                sspBuf = SSPBUF;    // Clear BF
            }

            if (SSPSTATbits.R_NOT_W) {

                // Multi-byte read - advance to next address
                SSPCON1bits.WCOL = 0;
                SSPBUF           = i2c_reg_map[i2c_reg_addr++];
                LATDbits.LATD6 = 1;
                
            } else {                

                if (i2c_byte_count == 1) {
                    // First write byte is register address
                    i2c_reg_addr = sspBuf;

                } else {
                    // Write to register address - auto advance
                    //   to allow multiple bytes to be written
                    i2c_reg_map[i2c_reg_addr++] = sspBuf;
                }
            }
        }
        // Limit address to size of register map
        i2c_reg_addr %= sizeof(i2c_reg_map);
        
        // Finally
        PIR1bits.SSPIF  = 0;            // Clear MSSP interrupt flag
        SSPCON1bits.CKP = 1;            // Release clock        
    }    
} 





SSPADD MSSP Address Register in I2C™ Slave Mode. MSSP Baud Rate Reload Register in I2C Master Mode. 0000 0000 50, 170
SSPSTAT SMP CKE D/A P S R/W UA BF 0000 0000 50, 162,
171
SSPCON1 WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0 0000 0000 50, 163,
172
SSPCON2 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN 0000 0000 50, 173




MASTER SYNCHRONOUS
SERIAL PORT (MSSP)
MODULE


Master SSP (MSSP) Module
Overview
The Master Synchronous Serial Port (MSSP) module is
a serial interface, useful for communicating with other
peripheral or microcontroller devices. These peripheral
devices may be serial EEPROMs, shift registers,
display drivers, A/D converters, etc. The MSSP module
can operate in one of two modes:
Serial Peripheral Interface (SPI)
Inter-Integrated Circuit (I2C)
- Full Master mode
- Slave mode (with general address call)



The I2C interface supports the following modes in
hardware:
• Master mode
• Multi-Master mode
• Slave mode


Two pins are used for data transfer:
• Serial clock (SCL) – RC3/SCK/SCL
• Serial data (SDA) – RC4/SDI/SDA


The MSSP module has six registers for I2C operation.
These are:
• MSSP Control Register 1 (SSPCON1)
• MSSP Control Register 2 (SSPCON2)
• MSSP Status Register (SSPSTAT)
• Serial Receive/Transmit Buffer Register
(SSPBUF)
• MSSP Shift Register (SSPSR) – Not directly
accessible
• MSSP Address Register (SSPADD)





SSPCON1, SSPCON2 and SSPSTAT are the control
and status registers in I2C mode operation
The lower 6 bits of the SSPSTAT are read-only


SSPSR is the shift register used for shifting data in or
out. SSPBUF is the buffer register to which data bytes
are written to or read from.
SSPADD register holds the slave device address when
the MSSP is configured in I2C Slave mode. When the
MSSP is configured in Master mode, the lower seven
bits of SSPADD act as the Baud Rate Generator reload
value.


In receive operations, SSPSR and SSPBUF together
create a double-buffered receiver. When SSPSR
receives a complete byte, it is transferred to SSPBUF
and the SSPIF interrupt is set.






















SSPSTAT: MSSP STATUS REGISTER (I2C™ MODE)



R/W-0 R/W-0 R-0 R-0 R-0 R-0 R-0 R-0
SMP CKE D/A P(1) S(1) R/W(2,3) UA BF
bit 7 bit 0



bit 7 SMP: Slew Rate Control bit
In Master or Slave mode:
1 = Slew rate control disabled for Standard Speed mode (100 kHz)
0 = Slew rate control enabled for High-Speed mode (400 kHz)
bit 6 CKE: SMBus Select bit
In Master or Slave mode:
1 = Enable SMBus specific inputs
0 = Disable SMBus specific inputs
bit 5 D/A: Data/Address bit
In Master mode:
Reserved.
In Slave mode:
1 = Indicates that the last byte received or transmitted was data
0 = Indicates that the last byte received or transmitted was address
bit 4 P: Stop bit(1)
1 = Indicates that a Stop bit has been detected last
0 = Stop bit was not detected last
bit 3 S: Start bit(1)
1 = Indicates that a Start bit has been detected last
0 = Start bit was not detected last
bit 2 R/W: Read/Write Information bit (I2C mode only)(2,3)
In Slave mode:
1 = Read
0 = Write
In Master mode:
1 = Transmit is in progress
0 = Transmit is not in progress
bit 1 UA: Update Address bit (10-Bit Slave mode only)
1 = Indicates that the user needs to update the address in the SSPADD register
0 = Address does not need to be updated
bit 0 BF: Buffer Full Status bit
In Transmit mode:
1 = SSPBUF is full
0 = SSPBUF is empty
In Receive mode:
1 = SSPBUF is full (does not include the ACK and Stop bits)
0 = SSPBUF is empty (does not include the ACK and Stop bits)



REGISTER 17-4: SSPCON1: MSSP CONTROL REGISTER 1 (I2C™ MODE)
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
WCOL SSPOV SSPEN(1) CKP SSPM3 SSPM2 SSPM1 SSPM0
bit 7 bit 0


bit 7 WCOL: Write Collision Detect bit
In Master Transmit mode:
1 = A write to the SSPBUF register was attempted while the I2C conditions were not valid for a
transmission to be started (must be cleared in software)
0 = No collision
In Slave Transmit mode:
1 = The SSPBUF register is written while it is still transmitting the previous word (must be cleared in
software)
0 = No collision
In Receive mode (Master or Slave modes):
This is a “don’t care” bit.
bit 6 SSPOV: Receive Overflow Indicator bit
In Receive mode:
1 = A byte is received while the SSPBUF register is still holding the previous byte (must be cleared in
software)
0 = No overflow
In Transmit mode:
This is a “don’t care” bit in Transmit mode.
bit 5 SSPEN: Master Synchronous Serial Port Enable bit(1)
1 = Enables the serial port and configures the SDA and SCL pins as the serial port pins
0 = Disables serial port and configures these pins as I/O port pins
bit 4 CKP: SCK Release Control bit
In Slave mode:
1 = Releases clock
0 = Holds clock low (clock stretch), used to ensure data setup time
In Master mode:
Unused in this mode.
bit 3-0 SSPM3:SSPM0: Master Synchronous Serial Port Mode Select bits(2)
1111 = I2C Slave mode, 10-bit address with Start and Stop bit interrupts enabled
1110 = I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled
1011 = I2C Firmware Controlled Master mode (Slave Idle)
1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
0111 = I2C Slave mode, 10-bit address
0110 = I2C Slave mode, 7-bit address
Bit combinations not specifically listed here are either reserved or implemented in SPI mode only.

=================================================================



void  i2c_init(){

    TRISC          = 0b00011000;    // TRISC 3&4 (SCL & SDA) inputs
    LATC           = 0b00011000;
    SSPADD         = I2C_ADDR;      // Set I2C address
    SSPCON1        = 0x36;          // SSPEN: Synchronous Serial Port Enable bit - Enables the serial port and configures the SDA and SCL pins as the serial port pins
                                    // CKP: SCK Release Control bit              - Release clock
                                    // SSPM3:SSPM0: SSP Mode Select bits         - 0110 = I2C Slave mode, 7-bit address  
    SSPSTAT        = 0x00;
    SSPCON2        = 0x01;          // GCEN: General Call address (00h) (Slave mode only) 0 = General call address disabled
                                    // SEN: Start Condition Enable/Stretch Enable bit(1) ()Slave mode) 1 = Clock stretching is enabled
    PIR1bits.SSPIF = 0;             // Clear MSSP interrupt request flag
    PIE1bits.SSPIE = 1;             // Enable MSSP interrupt enable bit
    INTCONbits.GIE_GIEH  = 1;       // GIE/GIEH: Global Interrupt Enable bit
    INTCONbits.PEIE_GIEL = 1;       // PEIE/GIEL: Peripheral Interrupt Enable bit
}




===================================================

void high_isr (void)
{
    unsigned char    sspBuf;
   
    if (PIR1bits.SSPIF) {
       
        if (!SSPSTATbits.D_NOT_A) {
            //
            // Slave Address
            //
            i2c_byte_count = 0;

            if (SSPSTATbits.BF) {
                // Discard slave address
                sspBuf = SSPBUF;    // Clear BF
            }
           
            if (SSPSTATbits.R_NOT_W) {              
                // Reading - read from register map
                SSPCON1bits.WCOL = 0;
           //     SSPBUF           = i2c_reg_map[i2c_reg_addr++];
             SSPBUF =   i2c_reg_map[i2c_reg_addr++];
            }
           
        } else {
            //
            // Data bytes
            //
           // i2c_byte_count++;

            if (SSPSTATbits.BF) {
                sspBuf = SSPBUF;    // Clear BF
            }

           if(i2c_byte_count==0)
  i2c_reg_addr = sspBuf;

   

            if (SSPSTATbits.R_NOT_W) {  // read

                // Multi-byte read - advance to next address
                SSPCON1bits.WCOL = 0;
            //    SSPBUF           = i2c_reg_map[i2c_reg_addr++];

              if(i2c_byte_count==1)
                  SSPBUF =  i2c_reg_map[i2c_reg_addr];
             

            } else {                              //  write

               /*
                if (i2c_byte_count == 1) {
                    // First write byte is register address
                    i2c_reg_addr = sspBuf;

                } else {*/
                  gCmdBuffer[i2c_reg_addr] = sspBuf;

   // i2c_reg_w_addr++;
                    // Write to register address - auto advance
                    //   to allow multiple bytes to be written
                    //i2c_reg_map[i2c_reg_addr++] = sspBuf;
                    //gCmdBuffer[i2c_reg_w_addr++] = sspBuf;


                //}
            }
        }
        // Limit address to size of register map

       
       i2c_byte_count++;

        //i2c_reg_addr %= sizeof(i2c_reg_map);
     

if(i2c_byte_count==2 ){
if(SSPSTATbits.R_NOT_W==0){
   copy_i2c_flag = 1;
          i2c_reg_map[1] = 1;}
  i2c_byte_count=0;
}
        // Finally
        PIR1bits.SSPIF  = 0;            // Clear MSSP interrupt flag
        SSPCON1bits.CKP = 1;            // Release clock      
    }  
}





沒有留言:

張貼留言