El módulo I2C no responde

2

Estoy escribiendo un esclavo I2C básico como parte de mi código en un PIC16f de 20 pines de 20 bits MCU . Lo mejor que puedo decir, este microcontrolador tiene un módulo que vigila el bus I2C y solo actualiza mis registros si hay mensajes entrantes dirigidos al PIC; no puedo interactuar con ningún otro mensaje. El maestro es una CPU que ejecuta un kernel de Linux y algún otro software. Desde la CPU, puedo ejecutar un script de sonda I2C que solo intenta leer desde cada dirección de dispositivo posible en la cadena I2C (bus).

Tengo problemas para que el PIC responda a cualquier indagación. He escrito el código I2C más simple que puedo administrar: solo debe parpadear los LED cada vez que el dispositivo recibe algún tipo de mensaje I2C dirigido a él.

Conecté las líneas al osciloscopio y pude confirmar que el tráfico está llegando a través del reloj y las líneas de datos cuando sondeo la cadena.

Mi código está abajo. Mi compilador es la versión gratuita (sin optimizaciones) de XC8 de Microchip. Estoy usando la versión más nueva (v1.34) para Windows.

¿Me faltan algunos pasos de inicialización o configuración necesarios para que mi PIC pueda ver los mensajes entrantes de I2C?

#include <xc.h>                 /* XC8 General Include File */
#include <pic16lf1709.h>        /* Definitions of I/O pins */

#pragma config WDTE = OFF       // disable watchdog timer, for simplicity

// I2C address is 7 bits: 1111110
#define I2C_ADDRESS 0x7E

typedef unsigned char byte;

void main(void) {

    /* configure MSSP module */
    TRISBbits.TRISB4    = 1;    // set SDA to input
    TRISBbits.TRISB6    = 1;    // set SCL to input
    SSPCON1bits.SSPEN   = 1;    // enable SSP module
    SSPCON1bits.SSPM    = 0x6;  // SSP is in I2C slave mode, 7-bit addressing
    SSP1ADD             = I2C_ADDRESS<<1;  // set the device address (left-aligned)
    SSPCON1bits.CKP     = 1;    // release clock
    TRISC               = 0x00; // set LEDs to output
    PORTC               = 0xFF; // initialize LEDs to OFF

    while(1) {

        byte ssp_buf;           // for the data we read from the bus

        if(SSPSTATbits.BF) {    // if the I2C buffer is not empty
            PORTC = 0x00;       // turn on LEDs for a moment
            for(int i=0; i<100; i++) _delay(250);
            PORTC = 0xFF;       // turn them back off
            ssp_buf = SSPBUF;   // read the buffer
                                // BF flag is cleared by hardware
        }

        SSPCON1bits.CKP = 1;    // finally, release clock

    }

}
    
pregunta Woodrow Barlow

2 respuestas

2

Hay varias funciones de conexión de E / S que están en uso por diferentes PIC. El PIC que está utilizando tiene las siguientes características (como se copió del encabezado de los capítulos relevantes de la hoja de datos):

  

11.0 PUERTOS DE E / S

     

Cada puerto tiene seis registros estándar para su funcionamiento. Estas   los registros son:

     
  • registros TRISx (dirección de datos)

  •   
  • registros PORTx (lee los niveles en los pines del dispositivo)

  •   
  • registros LATx (cierre de salida)

  •   
  • INLVLx (control de nivel de entrada)

  •   
  • Registros ODCONx (drenaje abierto)

  •   
  • registros SLRCONx (velocidad de giro

  •   

Algunos puertos pueden tener uno o más de los siguientes registros adicionales.   Estos registros son:

     
  • ANSELx (selección analógica)

  •   
  • WPUx (pull-up débil)

  •   

Los puertos que admiten entradas analógicas tienen un registro ANSELx asociado.   Cuando se establece un bit ANSEL, el búfer de entrada digital asociado con   ese bit está deshabilitado Deshabilitar el búfer de entrada evita analógico   niveles de señal en el pin entre una lógica alta y baja de causar   Corriente excesiva en los circuitos de entrada lógica.

     

11.3.5 CONTROL ANALÓGICO

     

El registro ANSELB (Registro 11-12) se utiliza para configurar la entrada   Modo de un pin de E / S a analógico. Configuración del bit ANSELB apropiado alto   hará que todas las lecturas digitales en el pin se lean como "0" y permitan   Funciones analógicas en el pin para funcionar correctamente. El estado de la   Los bits ANSELB no tienen efecto en las funciones de salida digital. Un pin con   TRIS clear y ANSELB set seguirán funcionando como una salida digital, pero   El modo de entrada será analógico. Esto puede causar un comportamiento inesperado cuando   ejecutando instrucciones de lectura-modificación-escritura en el puerto afectado.

     

Nota: Los bits de ANSELB se establecen de manera predeterminada en el modo Analógico después del reinicio. Usar   Cualquier pin como digital de propósito general o entradas periféricas, el   el software del usuario debe inicializar los bits ANSEL correspondientes a "0".

     

12.0 MÓDULO DE SELECCIÓN DE PIN PERIFÉRICO (PPS)

     

El módulo de selección de pin periférico (PPS) conecta entradas y salidas periféricas al dispositivo de E / S   patas. Solo se incluyen señales digitales en las selecciones. Todo analógico   Las entradas y salidas permanecen fijas a sus pines asignados. Entrada y   Las selecciones de salida son independientes como se muestra en el bloque simplificado   diagrama Figura 12-1.

     

12.2 Salidas PPS

     

Cada pin de E / S tiene un registro PPS con el que la fuente de salida del pin es   seleccionado. Con pocas excepciones, el control de puerto TRIS asociado con   ese pin conserva el control sobre el controlador de salida de pin. Periféricos que   controlar el controlador de salida pin como parte de la operación periférica se   anular el control TRIS según sea necesario. Estos periféricos incluyen:

     
  • EUSART (operación síncrona)

  •   
  • MSSP (I2C)

  •   
  • COG (apagado automático)

  •   

12.3 Pines bidireccionales

     

Selecciones de PPS para periféricos con señales bidireccionales en un solo   El pin debe hacerse de modo que la entrada PPS y la salida PPS seleccionen el mismo   alfiler. Los periféricos que tienen señales bidireccionales incluyen:

     
  • EUSART (operación síncrona)

  •   
  • MSSP (I2C)

  •   

Debe leer las partes relevantes de la hoja de datos y configurar todos los registros de configuración de E / S necesarios para su configuración. En este caso, configurar ANSELB para habilitar las entradas digitales, y configurar los registros PPS para enrutar la entrada & Faltan las funciones de salida del módulo I2C a los pines deseados. Además, los registros PPS están protegidos contra cambios no deseados, por lo que hay un mecanismo de bloqueo que debe utilizar antes de poder acceder a los registros.

Después de realizar los cambios anteriores, el código debería tener este aspecto. Tenga en cuenta que, dado que los mensajes I2C aún no se han reconocido correctamente, es posible que el dispositivo no sea "visible" para el maestro, pero al menos debería ver parpadear la luz.

#include <xc.h>                 /* XC8 General Include File */
#include <pic16lf1709.h>        /* Definitions of I/O pins */

#pragma config WDTE = OFF

// I2C address is 7 bits: 1111110
#define I2C_ADDRESS 0x6E

typedef unsigned char byte;

void main(void) {

    /* configure ports */
    TRISBbits.TRISB4    = 1;    // set SDA to input
    TRISBbits.TRISB6    = 1;    // set SCL to input

    ANSELBbits.ANSB4    = 0;    // make sure SDA is set to digital

    TRISC               = 0x00; // set LEDs to output
    PORTC               = 0xFF; // initialize LEDs to OFF

    /* configure peripheral pin select */
    PPSLOCK             = 0x55;
    PPSLOCK             = 0xAA;
    PPSLOCK             = 0x00; // PPS is now unlocked
    SSPDATPPS           = 0x0C; // RB4 input is SDA (pg 140)
    SSPCLKPPS           = 0x0E; // RB6 input is SCL (pg 140)
    RB4PPS              = 0x11; // RB4 output is SDA (pg 141)
    RB6PPS              = 0x10; // RB6 output is SCL (pg 141)
    PPSLOCK             = 0x55;
    PPSLOCK             = 0xAA;
    PPSLOCK             = 0x01; // PPS is now locked

    /* configure MSSP module */
    SSPCON1bits.SSPEN   = 1;    // enable SSP module
    SSPCON1bits.SSPM    = 0x6;  // SSP is in I2C slave mode, 7-bit addressing
    SSP1ADD             = I2C_ADDRESS<<1;  // set the device address (left-aligned)
    SSPCON1bits.CKP     = 1;    // release clock

    while(1) {

        byte ssp_buf;

        if(SSPSTATbits.BF) {    // if the I2C buffer is not empty
            PORTC = 0x00;       // turn on LEDs for a moment
            for(int i=0; i<100; i++) _delay(250);
            PORTC = 0xFF;       // turn them back off
            ssp_buf = SSPBUF;   // read the buffer
                                // BF flag is cleared by hardware
        }

        SSPCON1bits.CKP = 1;    // finally, release clock

    }

}
    
respondido por el Laszlo Valko
0

La capacitancia del bus afecta a la sincronización, por lo que debe configurar correctamente los tiempos de espera / inicio del SDA maestro, para que el esclavo pueda reconocer las condiciones de inicio y parada.

    
respondido por el Maastonakki

Lea otras preguntas en las etiquetas