PIC16F877A I2C communication problem

  • Thread starter Thread starter thegreengineer
  • Start date Start date
  • Tags Tags
    Communication
Click For Summary
SUMMARY

The forum discussion centers on troubleshooting I2C communication issues between a PIC16F877A microcontroller and a DS3231 RTC module while developing a programmable clock. The user has implemented several subroutines for I2C control, including initialization, start, stop, and data transmission. Despite successfully compiling the code and building the circuit in Proteus, the RTC fails to display the intended time, remaining at 00:00:00. Key suggestions include ensuring proper reset of devices and enhancing code comments for clarity.

PREREQUISITES
  • Understanding of PIC16F877A microcontroller architecture
  • Familiarity with I2C communication protocol
  • Knowledge of DS3231 RTC module functionality
  • Experience with Proteus simulation software
NEXT STEPS
  • Investigate proper reset mechanisms for I2C devices
  • Learn about I2C addressing and data transmission protocols
  • Explore debugging techniques in Proteus for microcontroller simulations
  • Review best practices for commenting and documenting code
USEFUL FOR

Embedded systems developers, hobbyists working with microcontrollers, and anyone involved in I2C communication troubleshooting and RTC integration.

thegreengineer
Messages
54
Reaction score
3
Good evening people, I was planing to make a programmable clock using a PIC16F877A microcontroller, a LM016 LCD display and a DS3232 RTC module. The DS3231 RTC module communicates with the PIC via I2C bus. At first I built some subroutines for controlling I2C communication: the commands have names in Spanish yet I explain what they do:

Code:
    i2c_inicializa    ;This subroutine is for initiating the I2C module
    bcf    STATUS,RP1
    bsf    STATUS,RP0
    bsf    TRISC,TRISC3
    bsf    TRISC,TRISC4
    movlw    B'10000000'
    movwf    SSPSTAT
    bcf    STATUS,RP0
    movlw    B'00101000'
    movwf    SSPCON
    bsf    STATUS,RP0
    movlw    B'00000000'
    movwf    SSPCON2
    movlw    D'9'
    movwf    SSPADD
    return

    i2c_espera    ;This is just an idle subroutine for producing a delay time between commands
    call    retardo_2ms
    return

    i2c_inicio    ;Start condition
    bcf    STATUS,RP1
    bsf    STATUS,RP0
    call    i2c_espera
    bsf    SSPCON2,SEN
    return
   
    i2c_reinicio    ;Restarting condition
    bcf    STATUS,RP1
    bsf    STATUS,RP0   
    call    i2c_espera
    bsf    SSPCON2,RSEN
    return

    i2c_parada    ;Stop condition
    bcf    STATUS,RP1
    bsf    STATUS,RP0
    call    i2c_espera
    bsf    SSPCON2,PEN
    return

    i2c_envia_dato    ;Write data into slave device
    bcf    STATUS,RP1
    bcf    STATUS,RP0
    call    i2c_espera
    movwf    SSPBUF
    return

    i2c_recibe_dato    ;Reading data from slave
    bcf    STATUS,RP1
    bsf    STATUS,RP0
    call    i2c_espera
    bsf    SSPCON2,RCEN
    call    i2c_espera
    bsf    SSPCON2,ACKDT
    bsf    SSPCON2,ACKEN
    bcf    STATUS,RP1
    bcf    STATUS,RP0
    movf    SSPBUF,0
    return

I built the circuit in Proteus to test if the I2C communication works fine. For this purpose I just built the DS3231 part.
22789211_1982901315327736_5943802453130935664_n.jpg

If I upload a hex file with no i2c instructions the RTC starts counting from TIME at 00:00:00 and DATE at 00/00/00. Now let's suppose when I start the simulation I want the TIME to display at 00:10:00. For this what do I have to do? Well it's obvious that I need to write into the DS3232. So the first thing I do is initialializing the I2C comunication by calling the i2c_inicializa function at the very first. After that I send the start condition with the i2c_inicio command. Then I have to send the address of the slave plus the R/W bit for declaring if I want to read or write. Since DS3232 has an address of B'1101000' and I want to write in the DS3232 I send the byte B'11010000' with the i2c_envia_dato command (by previously loading the B'11010000' value into the W register). The I send the address, so I check the DS3232 datasheet and I find that the MINUTES register is in address 01H of the address map, so I send the value B'00000001' with the i2c_envia_dato command. Then I'm at the MINUTES register so if I want a "10" at the minutes register then I send (in BCD) B'00010000' with the i2c_envia_dato command. Finally to end the communication I call the i2c_parada for the stop condition. The source code is this:
Code:
;RELOJ PROGRAMABLE CON ALARMA ELABORADO CON PIC16F877A
;AUTOR: MARCO AURELIO VILLARREAL DEL VALLE
;MATRICULA: 1639019
;CLASE DE MICROCONTROLADORES
    __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF
    LIST    P=16F877A
    #INCLUDE    <P16F877A.INC>
    ;Iniciando en el banco 0
    ORG 0x00
    CBLOCK  0x26
    CONT_PAL
    ENDC
    bcf    STATUS,RP1
    bsf    STATUS,RP0
    clrf    TRISB
    clrf    TRISC
    clrf    TRISD
    bcf    STATUS,RP0
    call    i2c_inicializa
    call    i2c_inicio
    movlw   B'11010000'
    call    i2c_envia_dato
    movlw   B'00000001'
    call    i2c_envia_dato
    movlw   B'00010000'
    call    i2c_envia_dato
    call    i2c_parada
    principal
 
    goto principal
    #INCLUDE    <retardos.INC>
    #INCLUDE    <i2c.INC>
    #INCLUDE    <lcd.INC>
    END
After that I compile (build) and there are no errors, however when loading the code in PROTEUS the simulation still starts at time 00:00:00. And I don't know where my mistake is, I already checked the datasheet of the RTC module, still don't know. I would appreciate your answers. Thanks.
 

Attachments

  • 22789211_1982901315327736_5943802453130935664_n.jpg
    22789211_1982901315327736_5943802453130935664_n.jpg
    57.8 KB · Views: 1,255
Engineering news on Phys.org
MarcusAu314 said:
I built the circuit in Proteus to test if the I2C communication works fine. For this purpose I just built the DS3231 part.
I'll try to check the addressing later today (that is the trickiest part of I2C for me), but first, in your schematic, what is pin 18/20 on U2 supposed to represent? I have not seen that notation before...
 
Two things.

1. You need to tie your RST line to something, and you should reset all devices before using them. Typically if a device isn't reset you are not sure of its states and it will not function properly. You can either reset the device through the pic, or use an RC network to reset the device shortly after powerup. (use a lowpass filter with a time constant greater than the min required reset time.

2. Try to include more comments inside of each of your functions in the code. It will help you, trust me!
 

Similar threads

  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 10 ·
Replies
10
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 1 ·
Replies
1
Views
3K
Replies
2
Views
4K
  • · Replies 3 ·
Replies
3
Views
3K