TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: LucasBols en 03 de Junio de 2014, 17:41:25

Título: 16F877A, I2C y DS1307 [SOLUCIONADO]
Publicado por: LucasBols en 03 de Junio de 2014, 17:41:25
hola, buenas tardes,

estoy aprendiendo a usar el módulo i2c del 877 y a comunicar el pic con el rt ds1307,

después de muchas horas de lectura, encontré esta página http://.../pic-i2c-code-example.php (http://www.8051projects.net/i2c-twi-tutorial/pic-i2c-code-example.php), copié el código, le agregué una especie de mini debug por un lcd y resulta que el código se clava en el envío de los datos por i2c,

(http://www.dysd.com.ar/electronica/img/proteus_i2c.jpg)
el proteus me dice que el clock i2c queda flotante, ese es el warning que se ve,

el código es este:

main.c
Código: C#
  1. #include "main.h"
  2.  
  3. //------------------------------------------------------------------------------
  4.  
  5. int main(void)
  6. {
  7.     /* Buffer where we will read/write our data */
  8.     unsigned char I2CData[] = {0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x00};
  9.     t_byte caracter;
  10.  
  11.     /**** PORTD I/O ****/
  12.     TRISEbits.PSPMODE = 0; // PORTD functions in general purpose I/O mode
  13.  
  14.     TRISEbits.TRISE2  = 0; // Output
  15.     TRISEbits.TRISE1  = 0; // Output
  16.     TRISEbits.TRISE0  = 0; // Output
  17.  
  18.     /**** PORTA / PORTE I/O ****/
  19.     ADCON1 = 0b00000111; // RA5:RA0 y RE2:RE0 Digital
  20.  
  21.     TRISA = 0b00000000; // lcd
  22.     TRISE = 0b00000000; // lcd
  23.    
  24.     inicializaLCD();
  25.  
  26.     caracter.byte = _LCD_L1_C_01_;
  27.     enviaComandoLCD( caracter );
  28.  
  29.     /* Initialize I2C Port */
  30.     I2CInit();
  31.     escribeLineaLCD( "1", 0 );
  32.  
  33.     /* Send Start condition */
  34.     I2CStart();
  35.     escribeLineaLCD( "2", 0 );
  36.  
  37.     /* Send DS1307 slave address with write operation */
  38.     I2CSend(0xD0); //#### ACA SE CLAVA ####
  39.     escribeLineaLCD( "3", 0 );
  40.  
  41.     /* Send subaddress 0x00, we are writing to this location */
  42.     I2CSend(0x00);
  43.     escribeLineaLCD( "4", 0 );
  44.  
  45.     /* Loop to write 8 bytes */
  46.     for (unsigned char i = 0; i < 8; i++)
  47.     {
  48.         /* send I2C data one by one */
  49.         I2CSend(I2CData[i]);
  50.     }
  51.     escribeLineaLCD( "5", 0 );
  52.  
  53.     /* Send a stop condition - as transfer finishes */
  54.     I2CStop();
  55.     escribeLineaLCD( "6", 0 );
  56.  
  57.     /* We will now read data from DS1307 */
  58.     /* Reading for a memory based device always starts with a dummy write */
  59.     /* Send a start condition */
  60.     I2CStart();
  61.     escribeLineaLCD( "7", 0 );
  62.  
  63.     /* Send slave address with write */
  64.     I2CSend(0xD0);
  65.     escribeLineaLCD( "8", 0 );
  66.  
  67.     /* Send address for dummy write operation */
  68.     /* this address is actually where we are going to read from */
  69.     I2CSend(0x00);
  70.     escribeLineaLCD( "9", 0 );
  71.  
  72.  
  73.     /* Send a repeated start, after a dummy write to start reading */
  74.     I2CRestart();
  75.     escribeLineaLCD( "0", 0 );
  76.  
  77.     /* send slave address with read bit set */
  78.     I2CSend(0xD1);
  79.     escribeLineaLCD( "1", 0 );
  80.  
  81.  
  82.     caracter.byte = _LCD_L2_C_01_;
  83.     enviaComandoLCD( caracter );
  84.    
  85.     /* Loop to read 8 bytes from I2C slave */
  86.     for (unsigned char i = 8; i > 0; i--) {
  87.         /* read a byte */
  88.         I2CData[i] = I2CRead();
  89.  
  90.         caracter.byte = I2CData[i];
  91.         enviaDatoLCD( caracter );
  92.  
  93.         /* ACK if its not the last byte to read */
  94.         /* if its the last byte then send a NAK */
  95.         if (i - 1)
  96.             I2CAck();
  97.         else
  98.             I2CNak();
  99.     }
  100.     /* Send stop */
  101.     I2CStop();
  102.     /* end of program */
  103.     while (1);
  104. }
  105.  
  106. //------------------------------------------------------------------------------

main.h
Código: C#
  1. //------------------------------------------------------------------------------
  2.  
  3. #ifndef MAIN_H
  4. #define MAIN_H
  5.  
  6. #include <xc.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. #include "i2c_lib.h"
  11. #include "lcd16x2.h"
  12.  
  13. //******************************************************************************
  14. //******** configuracion del pic ***********************************************
  15. //******************************************************************************
  16.  
  17. #define _XTAL_FREQ 4000000 // Velocidad clock en Hz
  18.  
  19. #pragma config FOSC  = XT       // Oscillator Selection bits
  20.                                 // (XT oscillator)
  21.  
  22. #pragma config WDTE  = OFF      // Watchdog Timer Enable bit
  23.                                 // (WDT disabled)
  24.  
  25. #pragma config PWRTE = OFF      // Power-up Timer Enable bit
  26.                                 // (PWRT disabled)
  27.  
  28. #pragma config BOREN = ON       // Brown-out Reset Enable bit
  29.                                 // (BOR enabled)
  30.  
  31. #pragma config LVP   = OFF      // Low-Voltage (Single-Supply)
  32.                                 // In-Circuit Serial Programming
  33.                                 // Enable bit
  34.                                 // (RB3 is digital I/O, HV on MCLR
  35.                                 // must be usedfor programming)
  36.  
  37. #pragma config CPD   = OFF      // Data EEPROM Memory Code
  38.                                 // Protection bit
  39.                                 // (Data EEPROM code protection off)
  40.  
  41. #pragma config WRT   = OFF      // Flash Program Memory Write
  42.                                 // Enable bits
  43.                                 // (Write protection off;
  44.                                 // all program memory may be written
  45.                                 // to by EECON control)
  46.  
  47. #pragma config CP    = OFF      // Flash Program Memory
  48.                                 // Code Protection bit
  49.                                 // (Code protection off)
  50.  
  51. //******************************************************************************
  52. //******** retardos ************************************************************
  53. //******************************************************************************
  54.  
  55. #ifndef __DELAYS__
  56. #define __DELAYS__
  57.     #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
  58.     #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
  59. #endif
  60.  
  61. //******************************************************************************
  62. //********
  63. //******************************************************************************
  64.  
  65. //------------------------------------------------------------------------------
  66.  
  67. #endif  /* MAIN_H */

i2c_lib.c
Código: C#
  1. #include "i2c_lib.h"
  2.  
  3. //------------------------------------------------------------------------------
  4. /*
  5.  * Function: I2CInit
  6.  * Return:
  7.  * Arguments:
  8.  * Description: Initialize I2C in master mode, Sets the required baudrate
  9.  */
  10. void I2CInit(void)
  11. {
  12.     TRISC3 = 1; /* SDA and SCL as input pin */
  13.     TRISC4 = 1; /* these pins can be configured either i/p or o/p */
  14.     SSPSTAT |= 0x80; /* Slew rate disabled */
  15.     SSPCON = 0x28; /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
  16.     SSPADD = 0x28; /* 100Khz @ 4Mhz Fosc */
  17. }
  18.  
  19. //------------------------------------------------------------------------------
  20. /*
  21.  * Function: I2CStart
  22.  * Return:
  23.  * Arguments:
  24.  * Description: Send a start condition on I2C Bus
  25.  */
  26. void I2CStart()
  27. {
  28.     SEN = 1; /* Start condition enabled */
  29.     while (SEN); /* automatically cleared by hardware */
  30.     /* wait for start condition to finish */
  31. }
  32.  
  33. //------------------------------------------------------------------------------
  34. /*
  35.  * Function: I2CStop
  36.  * Return:
  37.  * Arguments:
  38.  * Description: Send a stop condition on I2C Bus
  39.  */
  40. void I2CStop()
  41. {
  42.     PEN = 1; /* Stop condition enabled */
  43.     while (PEN); /* Wait for stop condition to finish */
  44.     /* PEN automatically cleared by hardware */
  45. }
  46.  
  47. //------------------------------------------------------------------------------
  48. /*
  49.  * Function: I2CRestart
  50.  * Return:
  51.  * Arguments:
  52.  * Description: Sends a repeated start condition on I2C Bus
  53.  */
  54. void I2CRestart()
  55. {
  56.     RSEN = 1; /* Repeated start enabled */
  57.     while (RSEN); /* wait for condition to finish */
  58. }
  59.  
  60. //------------------------------------------------------------------------------
  61. /*
  62.  * Function: I2CAck
  63.  * Return:
  64.  * Arguments:
  65.  * Description: Generates acknowledge for a transfer
  66.  */
  67. void I2CAck()
  68. {
  69.     ACKDT = 0; /* Acknowledge data bit, 0 = ACK */
  70.     ACKEN = 1; /* Ack data enabled */
  71.     while (ACKEN); /* wait for ack data to send on bus */
  72. }
  73.  
  74. //------------------------------------------------------------------------------
  75. /*
  76.  * Function: I2CNck
  77.  * Return:
  78.  * Arguments:
  79.  * Description: Generates Not-acknowledge for a transfer
  80.  */
  81. void I2CNak()
  82. {
  83.     ACKDT = 1; /* Acknowledge data bit, 1 = NAK */
  84.     ACKEN = 1; /* Ack data enabled */
  85.     while (ACKEN); /* wait for ack data to send on bus */
  86. }
  87.  
  88. //------------------------------------------------------------------------------
  89. /*
  90.  * Function: I2CWait
  91.  * Return:
  92.  * Arguments:
  93.  * Description: wait for transfer to finish
  94.  */
  95. void I2CWait()
  96. {
  97.     while ((SSPCON2 & 0x1F) || (SSPSTAT & 0x04));
  98.     /* wait for any pending transfer */
  99. }
  100.  
  101. //------------------------------------------------------------------------------
  102. /*
  103.  * Function: I2CSend
  104.  * Return:
  105.  * Arguments: dat - 8-bit data to be sent on bus
  106.  * data can be either address/data byte
  107.  * Description: Send 8-bit data on I2C bus
  108.  */
  109. void I2CSend(unsigned char dat)
  110. {
  111.     SSPBUF = dat; /* Move data to SSPBUF */
  112.      //#### ACA SE CLAVA ####
  113.     while (BF); /* wait till complete data is sent from buffer */
  114.     I2CWait(); /* wait for any pending transfer */
  115. }
  116.  
  117. //------------------------------------------------------------------------------
  118. /*
  119.  * Function: I2CRead
  120.  * Return: 8-bit data read from I2C bus
  121.  * Arguments:
  122.  * Description: read 8-bit data from I2C bus
  123.  */
  124. unsigned char I2CRead(void)
  125. {
  126.     unsigned char temp;
  127.  
  128.     /* Reception works if transfer is initiated in read mode */
  129.     RCEN = 1; /* Enable data reception */
  130.     while (!BF); /* wait for buffer full */
  131.     temp = SSPBUF; /* Read serial buffer and store in temp register */
  132.     I2CWait(); /* wait to check any pending transfer */
  133.     return temp; /* Return the read data from bus */
  134. }
  135.  
  136. //------------------------------------------------------------------------------

i2c_lib.h
Código: C#
  1. #ifndef I2C_LIB_H
  2. #define I2C_LIB_H
  3.  
  4. #include <xc.h>
  5. #include <pic16f877a.h>
  6.  
  7. //------------------------------------------------------------------------------
  8.  
  9. void I2CInit(void);
  10. void I2CStart();
  11. void I2CStop();
  12. void I2CRestart();
  13. void I2CAck();
  14. void I2CNak();
  15. void I2CWait();
  16. void I2CSend(unsigned char dat);
  17. unsigned char I2CRead(void);
  18.  
  19.  
  20. //------------------------------------------------------------------------------
  21.  
  22. #endif  /* I2C_LIB_H */

adjunto el proyecto y el proteus,

muchas gracias,

saludos,
Título: Re: 16F877A, I2C y DS1307
Publicado por: LucasBols en 04 de Junio de 2014, 12:31:01
volviendo sobre el tema, noto que en el data del i2c del 877, para el bit BF de SSPSTAT dice esto:

BF: Buffer Full Status bit
    In Transmit mode:
        1 = Receive complete, SSPBUF is full
        0 = Receive not complete, SSPBUF is empty
    In Receive mode:
        1 = Data Transmit in progress (does not include the ACK and Stop bits), SSPBUF is full
        0 = Data Transmit complete (does not include the ACK and Stop bits), SSPBUF is empty

¿no debería decir esto?

BF: Buffer Full Status bit
    In Transmit mode:
        1 = Data Transmit in progress (does not include the ACK and Stop bits), SSPBUF is full
        0 = Data Transmit complete (does not include the ACK and Stop bits), SSPBUF is empty
    In Receive mode:
        1 = Receive complete, SSPBUF is full
        0 = Receive not complete, SSPBUF is empty

porque en el código de envío tengo esto:
Código: C#
  1. SSPBUF = dat;
  2.     while (BF); /* si el data esta bien, esto no deberia ser while ( !BF ) ; ? */
  3.     while ((SSPCON2 & 0x1F) || (SSPSTAT & 0x04));
Gracias,

saludos,
Título: Re: 16F877A, I2C y DS1307
Publicado por: LucasBols en 04 de Junio de 2014, 13:14:14
solucionado, el problema estaba en el proteus, reemplacé las dos pullup de SCL y SDA por dos de 10k y funcionó

saludos