Ir ao conteúdo
  • Cadastre-se

Ds1307 +c18+18f2550


Posts recomendados

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);
}

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

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

Link para o comentário
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.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

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...

Link para o comentário
Compartilhar em outros sites

  • 5 semanas depois...

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á.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
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)

Link para o comentário
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.

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...