Actualmente estoy probando el expansor de E/S de 16 bits MCP23017 (dispositivo esclavo) usando un PIC18F45K20 con el compilador C18 para transmitir datos al MCP23017. Los pines de dirección (A0, A1 y A2) del MCP23017 están conectados a tierra. El reloj serie (SCL) funciona a 100 kHz.
Revisé el código de mi programa de pies a cabeza y no pude encontrar ningún problema en mi código a pesar de que se compiló sin errores.
Los problemas que enfrenté son:
El MCP23017 no emite los datos transmitidos desde el PIC18F45K20 (el código de programa se muestra a continuación).
La forma de onda SCL de PIC18F45K20 no es una onda cuadrada. Se midió con un osciloscopio.
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <i2c.h>
#include <p18f45k20.h>
#include <sw_i2c.h>
#define MCP_IODIR_A 0x00
#define MCP_IPOL_A 0x02
#define MCP_OLAT_A 0x14
#define MCP_GPIO_A 0x12
#define MCP_IOCON_A 0x0A
#define MCP_GPINTEN_A 0x04
/*
*
*/
//----------------------------Global variable----------------------------
// PIC18F45K20 Configuration Bit Settings
// CONFIG1H
#pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 30 // Brown Out Reset Voltage bits (VBOR set to 3.0 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF // MCLR Pin Enable bit (RE3 input pin enabled; MCLR disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0(000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
void init_I2C()
{
DDRCbits.RC3 = 1; //Configure SCL as input
DDRCbits.RC4 = 1; //Configure SDA as input
// SSPSTAT Configuration (0x80)
SSPSTATbits.SMP = 1; //Slew rate control disabled
SSPSTATbits.CKE = 0; //SMBus disabled
SSPSTATbits.D_A = 0; //Reserved in master mode
SSPSTATbits.P = 0; //Stop bit was not detected last
SSPSTATbits.S = 0; //Start bit was not detected last
SSPSTATbits.R_W = 0;
SSPSTATbits.UA = 0; //Address doesnot need to be updated
SSPSTATbits.BF = 0;
// SSPCON1 Configuration (0x28)
SSPCON1bits.WCOL = 0;
SSPCON1bits.SSPOV = 0;
SSPCON1bits.SSPEN = 1; //Serial port enabled
SSPCON1bits.CKP = 0; //Holds clock low
SSPCON1bits.SSPM3 = 1; //1000 = I2C Master mode
SSPCON1bits.SSPM2 = 0; //BitRate = FOSC/(4*(SPPADD+1))
SSPCON1bits.SSPM1 = 0;
SSPCON1bits.SSPM0 = 0;
// SSPADD Configuration
SSPADD = 0x27; //should be 0x27 for 100kHz
//SSPADD = [(FOSC/BitRate)/4]-1
// SSPCON2 Configuration (0x00)
SSPCON2bits.GCEN = 0; //General call address disabled
SSPCON2bits.ACKSTAT = 0; //Acknowledge was received from slave
SSPCON2bits.ACKDT = 0; //Acknowledge
SSPCON2bits.ACKEN = 0; //Acknowledge sequence idle
SSPCON2bits.RCEN = 0; //Receive idle
SSPCON2bits.PEN = 0; //Stop condition idle
SSPCON2bits.RSEN = 0; //Repeated start condition idle
SSPCON2bits.SEN = 0;
}
void MCP_write()
{
WriteI2C(0x40);
}
void MCP_read()
{
WriteI2C(0x41);
}
void MCP_addr()
{
StartI2C();
MCP_write();
}
void init_MCP()
{
//IODIR A configuration
MCP_addr();
AckI2C();
WriteI2C(MCP_IODIR_A);
AckI2C();
WriteI2C(0x00);
StopI2C();
//IPOL A configuration
MCP_addr();
AckI2C();
WriteI2C(MCP_IPOL_A);
AckI2C();
WriteI2C(0x00);
StopI2C();
//OLAT A configuration
MCP_addr();
AckI2C();
WriteI2C(MCP_OLAT_A);
AckI2C();
WriteI2C(0xFF);
StopI2C();
//IOCON A configuration
MCP_addr();
AckI2C();
WriteI2C(MCP_IOCON_A);
AckI2C();
WriteI2C(0x00);
StopI2C();
//GPINTEN A configuration
MCP_addr();
AckI2C();
WriteI2C(MCP_GPINTEN_A);
AckI2C();
WriteI2C(0x00);
StopI2C();
}
//----------------------------Main program----------------------------
void main(void)
{
OSCCON = 0x70; //Set internal oscillation to 16 MHz
TRISD=0;
init_I2C(); //I2C initialization
init_MCP(); //MCP23017 initialization
while(1)
{
MCP_addr();
AckI2C();
WriteI2C(MCP_GPIO_A);
AckI2C();
WriteI2C(0x11);
StopI2C();
}
}
Los problemas habían sido resueltos. El origen de este problema es que había bits de reconocimiento en el wcode. No es necesario que el dispositivo maestro envíe un bit de reconocimiento al dispositivo esclavo durante la operación de escritura. De hecho, el dispositivo maestro debe esperar el bit de reconocimiento del dispositivo esclavo.
A continuación se muestra el código para probar el protocolo I2C del PIC18F45K20 con MCP23017.
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <i2c.h>
#include <p18f45k20.h>
#include <sw_i2c.h>
#define MCP_IODIR_A 0x00
#define MCP_IPOL_A 0x02
#define MCP_OLAT_A 0x14
#define MCP_GPIO_A 0x12
#define MCP_IOCON_A 0x0A
#define MCP_GPINTEN_A 0x04
/*
*
*/
//----------------------------Global variable----------------------------
// PIC18F45K20 Configuration Bit Settings
// CONFIG1H
#pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 30 // Brown Out Reset Voltage bits (VBOR set to 3.0 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF // MCLR Pin Enable bit (RE3 input pin enabled; MCLR disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0(000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
void init_I2C()
{
DDRCbits.RC3 = 1; //Configure SCL as input
DDRCbits.RC4 = 1; //Configure SDA as input
// SSPSTAT Configuration (0x80)
SSPSTATbits.SMP = 1; //Slew rate control disabled
SSPSTATbits.CKE = 0; //SMBus disabled
SSPSTATbits.D_A = 0; //Reserved in master mode
SSPSTATbits.P = 0; //Stop bit was not detected last
SSPSTATbits.S = 0; //Start bit was not detected last
SSPSTATbits.R_W = 0;
SSPSTATbits.UA = 0; //Address doesnot need to be updated
SSPSTATbits.BF = 0;
// SSPCON1 Configuration (0x28)
SSPCON1bits.WCOL = 0;
SSPCON1bits.SSPOV = 0;
SSPCON1bits.SSPEN = 1; //Serial port enabled
SSPCON1bits.CKP = 0; //Holds clock low
SSPCON1bits.SSPM3 = 1; //1000 = I2C Master mode
SSPCON1bits.SSPM2 = 0; //BitRate = FOSC/(4*(SPPADD+1))
SSPCON1bits.SSPM1 = 0;
SSPCON1bits.SSPM0 = 0;
// SSPADD Configuration
SSPADD = 0x27; //should be 0x27 for 100kHz
//SSPADD = [(FOSC/BitRate)/4]-1
// SSPCON2 Configuration (0x00)
SSPCON2bits.GCEN = 0; //General call address disabled
SSPCON2bits.ACKSTAT = 0; //Acknowledge was received from slave
SSPCON2bits.ACKDT = 0; //Acknowledge
SSPCON2bits.ACKEN = 0; //Acknowledge sequence idle
SSPCON2bits.RCEN = 0; //Receive idle
SSPCON2bits.PEN = 0; //Stop condition idle
SSPCON2bits.RSEN = 0; //Repeated start condition idle
SSPCON2bits.SEN = 0;
}
void MCP_write()
{
WriteI2C(0x40);
}
void MCP_read()
{
WriteI2C(0x41);
}
void MCP_addr()
{
StartI2C();
MCP_write();
}
void init_MCP()
{
//IODIR A configuration
MCP_addr();
WriteI2C(MCP_IODIR_A);
WriteI2C(0x00);
StopI2C();
//IPOL A configuration
MCP_addr();
WriteI2C(MCP_IPOL_A);
WriteI2C(0x00);
StopI2C();
//OLAT A configuration
MCP_addr();
WriteI2C(MCP_OLAT_A);
WriteI2C(0xFF);
StopI2C();
//IOCON A configuration
MCP_addr();
WriteI2C(MCP_IOCON_A);
WriteI2C(0x00);
StopI2C();
//GPINTEN A configuration
MCP_addr();
WriteI2C(MCP_GPINTEN_A);
WriteI2C(0x00);
StopI2C();
}
//----------------------------Main program----------------------------
void main(void)
{
OSCCON = 0x70; //Set internal oscillation to 16 MHz
TRISD=0;
init_I2C(); //I2C initialization
init_MCP(); //MCP23017 initialization
while(1)
{
MCP_addr();
WriteI2C(MCP_GPIO_A);
WriteI2C(0x11);
StopI2C();
}
}
Estoy de acuerdo en que esta es una publicación anterior, pero solo para la gente que usa las series PIC18f4xk22 y MSSP2, es decir, i2c_2, tenga en cuenta que debe desactivar el soporte de pines analógicos muxed a PIND0 y PIND1. Debe deshabilitar ANALOG usando ANSELD &= 0xFC;
olin lathrop
PedroJ
adam lorenzo
RonnÉ
Iancovici