Ir ao conteúdo
  • Cadastre-se
Tiago Shimizu

Ds1307 +c18+18f2550

Recommended Posts

Olá pessoal. Estou precisando fazer um relógio utilizando o PIC 18F2550 e o DS1307 programando em C18 porém, não estou conseguindo de jeito algum...!

 

Já tentei utilizando o I2C do pic via hardware e via software porém em nenhum dos dois funcionou. Descartei a comunicação pois tenho uma memória I2C e consigo ler e escrever na mesma sem problemas.

 

Alguém poderia me ajudar?

 

Obrigado.

#include <p18f2550.h> 
#include <sw_i2c.h>
  
#pragma config FOSC = HS
#pragma config CPUDIV = OSC1_PLL2
#pragma config DEBUG  = OFF
#pragma config PWRT   = OFF        
#pragma config WDT    = OFF        
#pragma config PBADEN = OFF      
#pragma config MCLRE  = ON        
#pragma config LVP    = OFF 
  
unsigned char horas, minuto, segundo;
unsigned char dia, mes, ano, semana;  
  
  
void ds1307_init(void)
{
    BYTE seconds = 0;

    SWStartI2C();
    SWWriteI2C(0xD0);      // WR to RTC
    SWWriteI2C(0x00);      // REG 0
    SWRestartI2C ();
    SWWriteI2C(0xD1);      // RD from RTC
    if (!SWAckI2C ( )) //Checa o bit ACK.
    {
        seconds = SWGetcI2C(); // Read current "seconds" in DS1307
        SWStopI2C();
        seconds &= 0x7F;
        DelayMs(3);
        SWStartI2C();
        SWWriteI2C(0xD0);      // WR to RTC
        SWWriteI2C(0x00);      // REG 0
        SWWriteI2C(seconds);     // Start oscillator with current "seconds value
        SWRestartI2C ();
        SWWriteI2C(0xD0);      // WR to RTC
        SWWriteI2C(0x07);      // Control Register
        SWWriteI2C(0x10);     // Disable squarewave output pin
    }
    SWStopI2C();
}  
  
BYTE bin2bcd(BYTE binary_value)
{
  BYTE temp;
  BYTE retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }
  return(retval);
}

// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
  BYTE temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}  
  
void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
    sec &= 0x7F;
    hr &= 0x3F;

    SWStartI2C();
    SWWriteI2C(0xD0);            // I2C write address
    SWWriteI2C(0x00);            // Start at REG 0 - Seconds
    SWWriteI2C(bin2bcd(sec));      // REG 0
    SWWriteI2C(bin2bcd(min));      // REG 1
    SWWriteI2C(bin2bcd(hr));      // REG 2
    SWWriteI2C(bin2bcd(dow));      // REG 3
    SWWriteI2C(bin2bcd(day));      // REG 4
    SWWriteI2C(bin2bcd(mth));      // REG 5
    SWWriteI2C(bin2bcd(year));      // REG 6
    SWWriteI2C(0x10);            // REG 7 - Disable squarewave output pin
    SWStopI2C();
}  
  
void main(void)
{   
  ADCON1 = 0x0F;
  ds1307_init();
  ds1307_set_date_time(28, 11, 16, 2, 2, 25, 16);
  ds1307_get_date(dia, mes, ano, semana);
}

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

experimente colocar um i2crepstart após o start. Simule. Talvez não esteja reconhecendo o ds. Veja se realmente o acki2c está ocorrendo. Consulte o d.s. do ds e mc.  Não confie cegamente no sw. Rode passo a passo. etc

adicionado 2 minutos depois

ah sim... não detectei no programa onde você inicializa o hw do mc

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isadora Ferraz, primeiramente muito obrigado pela ajuda. 

 

Então, já havia feito exatamente isso que comentou. Por exemplo, até no código coloquei o endereço do DS como 0xD0 porém, percebi depois que ele não estava aceitando dessa forma, por isso alterei para 0b1101000 e ele começou a aceitar pelo menos o primeiro SWWriteI2C mas depois do comando de leitura e/ou escrita (SWWriteI2C(0x00); / SWWriteI2C(0x01);), já recusa o Ack.

Compartilhar este post


Link para o post
Compartilhar em outros sites

magina...

Creio que uma lidinha basica nos protocolos do seu ds há de solucionar seu problema. Outra...Tente programar o hw do pic na unha mesmo pois o fato de você alterar de 0xd0 e 0b1101000 que é a lesma lerda e dar resultados diferentes , pode indicar algum bug no compilador. Verifique também a velocidade do clock que pode estar muito alta. Tente bem baixa abaixo do recomendado pelo d.s. . Aproveite e dê uma olhada na sua montagem, pullups e etc.

 

Disponha...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, tive de dar uma pausa no projeto mas agora retomei nele, porém até agora nada. Filtrei todo o código e ficou assim:

#include <p18f2550.h> 
#include "../Bibliotecas/i2c.h"

unsigned char LeRelogio(void);
unsigned char GravaRelogio(void);
  
typedef struct {

    struct {
        unsigned char Horas;
        unsigned char Minutos;
        unsigned char Segundos;
    } Horario;

    struct {
        unsigned char Dia;
        unsigned char Mes;
        unsigned char Ano;
    } Data;
} RELOGIO_CONFIG;
RELOGIO_CONFIG Relogio;
  
void main(void) {
    LeRelogio();

    Temp[0] = '1';
    Temp[1] = '7';
    Relogio.Horario.Horas = StrToLong(Temp, 0, 2);
    Temp[0] = '2';
    Temp[1] = '3';
    Relogio.Horario.Minutos = StrToLong(Temp, 0, 2);
    Temp[0] = '5';
    Temp[1] = '6';
    Relogio.Horario.Segundos = StrToLong(Temp, 0, 2);

    Temp[0] = '2';
    Temp[1] = '8';
    Relogio.Data.Dia = StrToLong(Temp, 0, 2);
    Temp[0] = '1';
    Temp[1] = '2';
    Relogio.Data.Mes = StrToLong(Temp, 0, 2);
    Temp[0] = '1';
    Temp[1] = '6';
    Relogio.Data.Ano = StrToLong(Temp, 0, 2);

    GravaRelogio();
    LeRelogio();
}

../Biblioteca/i2c.h

#include <delays.h>

#define  DATA_LOW   TRISBbits.TRISB2 = 0; // define macro for data pin output
#define  DATA_HI    TRISBbits.TRISB2 = 1; // define macro for data pin input
#define  DATA_LAT   LATBbits.LATB2        // define macro for data pin latch
#define  DATA_PIN   PORTBbits.RB2         // define macro for data pin

#define  CLOCK_LOW  TRISBbits.TRISB3 = 0; // define macro for clock pin output
#define  CLOCK_HI   TRISBbits.TRISB3 = 1; // define macro for clock pin input
#define  SCLK_LAT   LATBbits.LATB3        // define macro for clock pin latch
#define  SCLK_PIN   PORTBbits.RB3         // define macro for clock pin

void SWStopI2C(void);
void SWStartI2C(void);
void SWRestartI2C(void);
void SWStopI2C(void);

signed char SWAckI2C(void);
signed char Clock_test(void);
signed int SWReadI2C(void);
signed char SWWriteI2C(unsigned char data_out);
signed char SWGetsI2C(unsigned char *rdptr, unsigned char length);
signed char SWPutsI2C(unsigned char *wrptr);

#define  SWPutcI2C    SWWriteI2C
#define  SWGetcI2C    SWReadI2C
#define  SWDelay      Delay10TCYx(20)
void SWNotAckI2C(void);

far unsigned char I2C_BUFFER; // temp buffer for R/W operations
far unsigned char BIT_COUNTER; // temp bufffer for bit counting

void I2CRead(unsigned char Device, unsigned address, char *out, char length);
void I2CWrite(unsigned char Device, unsigned address, const rom unsigned char *texto);

// <editor-fold defaultstate="collapsed" desc="SWAckI2C">

signed char SWAckI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0  
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_HI; // release data line to float high 
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock line to float high
    Delay1TCY(); // 1 cycle delay
    Delay1TCY(); // 1 cycle delay
    if (DATA_PIN) // error if ack = 1, slave did not ack
    {
        return ( -1); // return with acknowledge error
    } else {
        return ( 0); // return with no error
    }
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWNotAckI2C">

void SWNotAckI2C(void) {
    CLOCK_LOW; // make clock pin output to drive low
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // make data pin output to drive low
    //Delay10TCY();               // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock line to float high 
    //Delay10TCY();               // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Clock_test">

signed char Clock_test(void) {
    //Delay10TCYx(3);                 // user may need to adjust timeout period
    //DelayMs(1);
    SWDelay;
    if (!SCLK_PIN) // if clock is still low after wait 
    {
        return ( -2); // return with clock error
    } else {
        return ( 0); // return with no error
    }
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWReadI2C">

signed int SWReadI2C(void) {
    BIT_COUNTER = 8; // set bit count for byte 
    SCLK_LAT = 0; // set clock pin latch to 0

    do {
        CLOCK_LOW; // set clock pin output to drive low
        DATA_HI; // release data line to float high
        //Delay10TCY();                 // user may need to modify based on Fosc
        SWDelay;
        CLOCK_HI; // release clock line to float high
        //Delay1TCY();                  // user may need to modify based on Fosc
        //Delay1TCY();
        SWDelay;

        if (!SCLK_PIN) // test for clock low
        {
            if (Clock_test()) // clock wait routine
            {
                return ( -2); // return with error condition       
            }
        }

        I2C_BUFFER <<= 1; // shift composed byte by 1
        I2C_BUFFER &= 0xFE; // clear bit 0

        if (DATA_PIN) // is data line high
            I2C_BUFFER |= 0x01; // set bit 0 to logic 1

    } while (--BIT_COUNTER); // stay until 8 bits have been acquired

    return ( (unsigned int) I2C_BUFFER); // return with data
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWGetsI2C">

signed char SWGetsI2C(unsigned char *rdptr, unsigned char length) {
    unsigned int thold; // define auto variable

    while (length--) // stay in loop until byte count is zero
    {
        thold = SWGetcI2C(); // read and save 1 byte
        if (thold & 0xFF00) {
            return ( -1); // return with error condition
        } else {
            *rdptr++ = thold; // save off byte read
        }

        if (!length) // initiate NOT ACK
        {
            CLOCK_LOW; // make clock pin output to drive low
            DATA_HI; // release data line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
            CLOCK_HI; // release clock line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
        } else // else initiate ACK condition
        {
            CLOCK_LOW; // make clock pin output to drive low
            DATA_LAT = 0; // set data pin latch to 0
            DATA_LOW; // make data pin output to drive low
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
            CLOCK_HI; // release clock line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
        }
    }
    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWWriteI2C">

signed char SWWriteI2C(unsigned char data_out) {
    BIT_COUNTER = 8; // initialize bit counter
    I2C_BUFFER = data_out; // data to send out
    SCLK_LAT = 0; // set latch to 0

    do {
        if (!SCLK_PIN) // test if clock is low
        { // if it is then ..
            if (Clock_test()) // wait on clock for a short time
            {
                return ( -1); // return with error condition      
            }
        }
        else {
            I2C_BUFFER &= 0xFF; // generate movlb instruction
            _asm
            rlcf I2C_BUFFER, 1, 1 // rotate into carry and test  
                    _endasm

            if (STATUS & 0x01) // if carry set, transmit out logic 1
            {
                CLOCK_LOW; // set clock pin output to drive low
                DATA_HI; // release data line to float high 
                //Delay10TCY();              // user may need to modify based on Fosc
                SWDelay;
                CLOCK_HI; // release clock line to float high 
                //Delay10TCY();              // user may need to modify based on Fosc
                SWDelay;
            } else // transmit out logic 0
            {
                CLOCK_LOW; // set clock pin output to drive low
                DATA_LAT = 0; // set data pin latch to 0
                DATA_LOW; // set data pin output to drive low 
                //Delay10TCY();             // user may need to modify based on Fosc
                SWDelay;
                CLOCK_HI; // release clock line to float high 
                //Delay10TCY();             // user may need to modify based on Fosc
                SWDelay;
            }

            BIT_COUNTER--; // reduce bit counter by 1
        }
    } while (BIT_COUNTER); // stay in transmit loop until byte sent 

    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWPutsI2C">

signed char SWPutsI2C(unsigned char *wrptr) {
    while (*wrptr) {
        if (SWPutcI2C(*wrptr++)) // write out data string to I2C receiver
        {
            return ( -1); // return if there was an error in Putc()
        } else {
            if (SWAckI2C()) // go read bus ack status
            {
                return ( -1); // return with possible error condition 
            }
        }
    }
    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWRestartI2C">

void SWRestartI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_HI; // release data pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set data pin output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWStopI2C">

void SWStopI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set data pin output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    DATA_HI; // release data pin to float high
    //Delay1TCY();                    // user may need to modify based on Fosc
    //Delay1TCY();
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWStartI2C">

void SWStartI2C(void) {
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set pin to output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="I2CWrite">

void I2CWrite(unsigned char Device, unsigned address, const rom unsigned char *texto) {
    SWStartI2C();
    SWWriteI2C(Device);
    if (!SWAckI2C()) //Checa o bit ACK.
    {
        SWWriteI2C(((char*) &address)[1]);
        if (!SWAckI2C()) {
            SWWriteI2C(((char*) &address)[0]);
            if (!SWAckI2C()) {
                while (*texto) {
                    if (*texto == '\n')
                        break;
                    SWWriteI2C(*texto++);
                    SWAckI2C();
                }
            }
        }
    }
    SWStopI2C();
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="I2CRead">

void I2CRead(unsigned char Device, unsigned address, char *out, char length) {
    SWStartI2C();
    SWWriteI2C(Device); // Endereço slave
    if (!SWAckI2C()) //Checa o bit ACK.
    {
        SWWriteI2C(((char*) &address)[1]);
        if (!SWAckI2C()) {
            SWWriteI2C(((char*) &address)[0]);
            if (!SWAckI2C()) {
                SWRestartI2C();
                SWWriteI2C(Device + 1);
                if (!SWAckI2C()) {
                    while (length-- > 1) {
                        *out = SWGetcI2C();
                        SWNotAckI2C();
                        out++;
                    }
                    *out = SWGetcI2C();
                    SWAckI2C();
                    SWStopI2C();
                }
            }
        }
    }
}
// </editor-fold>

Quando simulo pelo proteus ele funciona perfeitamente contudo, quando monto o circuito, não vai de jeito nenhum... O problema anterior de ele se perder nas informações estava ocorrendo pois no arquivo i2c.h, o valor da linha  #define  SWDelay      Delay10TCYx(20) estava #define  SWDelay      Delay10TCYx(2) e como estou utilizando um cristal de 20MHz, gerava erro.

Alguma luz para esse problema?

Obrigado desde já.

Compartilhar este post


Link para o post
Compartilhar em outros sites
4 horas atrás, Tiago Shimizu disse:

simulo pelo proteus ele funciona perfeitamente contudo, quando monto o circuito, não vai de jeito nenhum

Baseando-me nisto, continuo achando que é problema de montagem ou alguma configuração dos fuses

Talvez você possa melhorar esta frase...

4 horas atrás, Tiago Shimizu disse:

não vai de jeito nenhum...

como: sintomas, como se comporta, como deveria se comportar, em qual parte do processo , etc

 

um spoiler caía bem... look...
 

Spoiler

 


#include <p18f2550.h> 
#include "../Bibliotecas/i2c.h"

unsigned char LeRelogio(void);
unsigned char GravaRelogio(void);
  
typedef struct {

    struct {
        unsigned char Horas;
        unsigned char Minutos;
        unsigned char Segundos;
    } Horario;

    struct {
        unsigned char Dia;
        unsigned char Mes;
        unsigned char Ano;
    } Data;
} RELOGIO_CONFIG;
RELOGIO_CONFIG Relogio;
  
void main(void) {
    LeRelogio();

    Temp[0] = '1';
    Temp[1] = '7';
    Relogio.Horario.Horas = StrToLong(Temp, 0, 2);
    Temp[0] = '2';
    Temp[1] = '3';
    Relogio.Horario.Minutos = StrToLong(Temp, 0, 2);
    Temp[0] = '5';
    Temp[1] = '6';
    Relogio.Horario.Segundos = StrToLong(Temp, 0, 2);

    Temp[0] = '2';
    Temp[1] = '8';
    Relogio.Data.Dia = StrToLong(Temp, 0, 2);
    Temp[0] = '1';
    Temp[1] = '2';
    Relogio.Data.Mes = StrToLong(Temp, 0, 2);
    Temp[0] = '1';
    Temp[1] = '6';
    Relogio.Data.Ano = StrToLong(Temp, 0, 2);

    GravaRelogio();
    LeRelogio();
}

../Biblioteca/i2c.h

#include <delays.h>

#define  DATA_LOW   TRISBbits.TRISB2 = 0; // define macro for data pin output
#define  DATA_HI    TRISBbits.TRISB2 = 1; // define macro for data pin input
#define  DATA_LAT   LATBbits.LATB2        // define macro for data pin latch
#define  DATA_PIN   PORTBbits.RB2         // define macro for data pin

#define  CLOCK_LOW  TRISBbits.TRISB3 = 0; // define macro for clock pin output
#define  CLOCK_HI   TRISBbits.TRISB3 = 1; // define macro for clock pin input
#define  SCLK_LAT   LATBbits.LATB3        // define macro for clock pin latch
#define  SCLK_PIN   PORTBbits.RB3         // define macro for clock pin

void SWStopI2C(void);
void SWStartI2C(void);
void SWRestartI2C(void);
void SWStopI2C(void);

signed char SWAckI2C(void);
signed char Clock_test(void);
signed int SWReadI2C(void);
signed char SWWriteI2C(unsigned char data_out);
signed char SWGetsI2C(unsigned char *rdptr, unsigned char length);
signed char SWPutsI2C(unsigned char *wrptr);

#define  SWPutcI2C    SWWriteI2C
#define  SWGetcI2C    SWReadI2C
#define  SWDelay      Delay10TCYx(20)
void SWNotAckI2C(void);

far unsigned char I2C_BUFFER; // temp buffer for R/W operations
far unsigned char BIT_COUNTER; // temp bufffer for bit counting

void I2CRead(unsigned char Device, unsigned address, char *out, char length);
void I2CWrite(unsigned char Device, unsigned address, const rom unsigned char *texto);

// <editor-fold defaultstate="collapsed" desc="SWAckI2C">

signed char SWAckI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0  
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_HI; // release data line to float high 
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock line to float high
    Delay1TCY(); // 1 cycle delay
    Delay1TCY(); // 1 cycle delay
    if (DATA_PIN) // error if ack = 1, slave did not ack
    {
        return ( -1); // return with acknowledge error
    } else {
        return ( 0); // return with no error
    }
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWNotAckI2C">

void SWNotAckI2C(void) {
    CLOCK_LOW; // make clock pin output to drive low
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // make data pin output to drive low
    //Delay10TCY();               // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock line to float high 
    //Delay10TCY();               // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Clock_test">

signed char Clock_test(void) {
    //Delay10TCYx(3);                 // user may need to adjust timeout period
    //DelayMs(1);
    SWDelay;
    if (!SCLK_PIN) // if clock is still low after wait 
    {
        return ( -2); // return with clock error
    } else {
        return ( 0); // return with no error
    }
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWReadI2C">

signed int SWReadI2C(void) {
    BIT_COUNTER = 8; // set bit count for byte 
    SCLK_LAT = 0; // set clock pin latch to 0

    do {
        CLOCK_LOW; // set clock pin output to drive low
        DATA_HI; // release data line to float high
        //Delay10TCY();                 // user may need to modify based on Fosc
        SWDelay;
        CLOCK_HI; // release clock line to float high
        //Delay1TCY();                  // user may need to modify based on Fosc
        //Delay1TCY();
        SWDelay;

        if (!SCLK_PIN) // test for clock low
        {
            if (Clock_test()) // clock wait routine
            {
                return ( -2); // return with error condition       
            }
        }

        I2C_BUFFER <<= 1; // shift composed byte by 1
        I2C_BUFFER &= 0xFE; // clear bit 0

        if (DATA_PIN) // is data line high
            I2C_BUFFER |= 0x01; // set bit 0 to logic 1

    } while (--BIT_COUNTER); // stay until 8 bits have been acquired

    return ( (unsigned int) I2C_BUFFER); // return with data
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWGetsI2C">

signed char SWGetsI2C(unsigned char *rdptr, unsigned char length) {
    unsigned int thold; // define auto variable

    while (length--) // stay in loop until byte count is zero
    {
        thold = SWGetcI2C(); // read and save 1 byte
        if (thold & 0xFF00) {
            return ( -1); // return with error condition
        } else {
            *rdptr++ = thold; // save off byte read
        }

        if (!length) // initiate NOT ACK
        {
            CLOCK_LOW; // make clock pin output to drive low
            DATA_HI; // release data line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
            CLOCK_HI; // release clock line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
        } else // else initiate ACK condition
        {
            CLOCK_LOW; // make clock pin output to drive low
            DATA_LAT = 0; // set data pin latch to 0
            DATA_LOW; // make data pin output to drive low
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
            CLOCK_HI; // release clock line to float high 
            //Delay10TCY();               // user may need to modify based on Fosc
            SWDelay;
        }
    }
    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWWriteI2C">

signed char SWWriteI2C(unsigned char data_out) {
    BIT_COUNTER = 8; // initialize bit counter
    I2C_BUFFER = data_out; // data to send out
    SCLK_LAT = 0; // set latch to 0

    do {
        if (!SCLK_PIN) // test if clock is low
        { // if it is then ..
            if (Clock_test()) // wait on clock for a short time
            {
                return ( -1); // return with error condition      
            }
        }
        else {
            I2C_BUFFER &= 0xFF; // generate movlb instruction
            _asm
            rlcf I2C_BUFFER, 1, 1 // rotate into carry and test  
                    _endasm

            if (STATUS & 0x01) // if carry set, transmit out logic 1
            {
                CLOCK_LOW; // set clock pin output to drive low
                DATA_HI; // release data line to float high 
                //Delay10TCY();              // user may need to modify based on Fosc
                SWDelay;
                CLOCK_HI; // release clock line to float high 
                //Delay10TCY();              // user may need to modify based on Fosc
                SWDelay;
            } else // transmit out logic 0
            {
                CLOCK_LOW; // set clock pin output to drive low
                DATA_LAT = 0; // set data pin latch to 0
                DATA_LOW; // set data pin output to drive low 
                //Delay10TCY();             // user may need to modify based on Fosc
                SWDelay;
                CLOCK_HI; // release clock line to float high 
                //Delay10TCY();             // user may need to modify based on Fosc
                SWDelay;
            }

            BIT_COUNTER--; // reduce bit counter by 1
        }
    } while (BIT_COUNTER); // stay in transmit loop until byte sent 

    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWPutsI2C">

signed char SWPutsI2C(unsigned char *wrptr) {
    while (*wrptr) {
        if (SWPutcI2C(*wrptr++)) // write out data string to I2C receiver
        {
            return ( -1); // return if there was an error in Putc()
        } else {
            if (SWAckI2C()) // go read bus ack status
            {
                return ( -1); // return with possible error condition 
            }
        }
    }
    return ( 0); // return with no error
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWRestartI2C">

void SWRestartI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_HI; // release data pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set data pin output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWStopI2C">

void SWStopI2C(void) {
    SCLK_LAT = 0; // set clock pin latch to 0
    CLOCK_LOW; // set clock pin to output to drive low
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set data pin output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    CLOCK_HI; // release clock pin to float high
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
    DATA_HI; // release data pin to float high
    //Delay1TCY();                    // user may need to modify based on Fosc
    //Delay1TCY();
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="SWStartI2C">

void SWStartI2C(void) {
    DATA_LAT = 0; // set data pin latch to 0
    DATA_LOW; // set pin to output to drive low
    //Delay10TCY();                   // user may need to modify based on Fosc
    SWDelay;
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="I2CWrite">

void I2CWrite(unsigned char Device, unsigned address, const rom unsigned char *texto) {
    SWStartI2C();
    SWWriteI2C(Device);
    if (!SWAckI2C()) //Checa o bit ACK.
    {
        SWWriteI2C(((char*) &address)[1]);
        if (!SWAckI2C()) {
            SWWriteI2C(((char*) &address)[0]);
            if (!SWAckI2C()) {
                while (*texto) {
                    if (*texto == '\n')
                        break;
                    SWWriteI2C(*texto++);
                    SWAckI2C();
                }
            }
        }
    }
    SWStopI2C();
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="I2CRead">

void I2CRead(unsigned char Device, unsigned address, char *out, char length) {
    SWStartI2C();
    SWWriteI2C(Device); // Endereço slave
    if (!SWAckI2C()) //Checa o bit ACK.
    {
        SWWriteI2C(((char*) &address)[1]);
        if (!SWAckI2C()) {
            SWWriteI2C(((char*) &address)[0]);
            if (!SWAckI2C()) {
                SWRestartI2C();
                SWWriteI2C(Device + 1);
                if (!SWAckI2C()) {
                    while (length-- > 1) {
                        *out = SWGetcI2C();
                        SWNotAckI2C();
                        out++;
                    }
                    *out = SWGetcI2C();
                    SWAckI2C();
                    SWStopI2C();
                }
            }
        }
    }
}

 

 

 

(ctrl-c ctrl-v do seu fonte)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isadora Ferraz, obrigado pela ajuda. Na realidade, estava simulando tanto pelo proteus quanto pelo PicKit3 diretamente no pic. 

Resolvi primeiro verificar se estava tudo certo e rodei o código diretamente no pic só que com a biblioteca de hardware do controlador e funcionou tudo certinho, então matei a parte de fuses e de montagem. porém, meu projeto utiliza os pinos padrões do I2C do pic para outra comunicação, e nessa altura do projeto, é melhor eu alterar a comunicação i2c para software mesmo.

Utilizo essa comunicação para controlar outros dois dispositivos já, uma memória (24C128) e um expansor de I/O (PCF8574), ambos por meio da I2C por software e tudo funciona ok.

Depois que coloquei a última mensagem aqui, quebrei mais a cabeça testando e percebi que quando acessava via hardware e logo após via software, ele pegava as informações certinho, porém reiniciava o controlador e tentava acessar via software direto não ia.

Tentei alterar tudo que era coisa na comunicação via software mas não foi.

porém, uma hora sem querer, realizei duas leituras consecutivas e na segunda leitura lê normal.

Sempre, sem exceção, na primeira leitura ele faz todos os passos porém só retorna zero nos valores, daí posso ler e escrever a vontade no ds que ele aceita todos os comando certinho.

Não entendi direito o porque disso pois via hardware não tenho esse problema.

Sendo assim, sempre que inicio o controlador, realizo uma leitura porém descarto ela e as demais funcionam 100%.

Obrigado pela ajuda.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×