PIC 16F88 SPI Interface with DS3234 RTC

Discussion in 'Embedded Systems and Microcontrollers' started by b_gravedigger, Feb 12, 2012.

  1. b_gravedigger

    Thread Starter New Member

    May 12, 2009
    6
    0
    Ι have a ds3234 RTC with which i successfully interacted via SPI using an Arduino Duemilanove.

    I did this using the code below:

    Code ( (Unknown Language)):
    1. #include <SPI.h>
    2. #include <avr/sleep.h>
    3. const int alarmPin = 2;
    4. const int RTC_CS=10;
    5. int count =0;
    6.  
    7. void setup()
    8. {
    9.     RTC_init();
    10. }
    11.  
    12. void loop(){
    13.    if (count >= 10) {
    14.       delay(100);    
    15.       count = 0;
    16.  
    17.     set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
    18.  
    19.     sleep_enable();          // enables the sleep bit in the mcucr register
    20.                              // so sleep is possible. just a safety pin
    21.  
    22.     attachInterrupt(0,rtcAlarm, LOW); // use interrupt 0 (pin 2) and run function
    23.                                        // rtcAlarm when pin 2 gets LOW
    24.  
    25.     sleep_mode();            // here the device is actually put to sleep!!
    26.                              // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
    27.  
    28.     sleep_disable();         // first thing after waking from sleep:
    29.                              // disable sleep...
    30.     detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
    31.                              // wakeUpNow code will not be executed
    32.                              // during normal running time.                      
    33.   }                          
    34. }
    35.  
    36.  
    37. void RTC_init(){
    38.   pinMode(RTC_CS,OUTPUT); // chip select
    39.      // start the SPI library:
    40.      SPI.begin();
    41.      SPI.setBitOrder(MSBFIRST);
    42.      SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work
    43.      //set control register
    44.      digitalWrite(RTC_CS, LOW);  
    45.      SPI.transfer(0x8E);
    46.          SPI.transfer(0x05); //00000110 EOSC/BBSQW/TEMPCONV/RS1/RS2/INTCN/A2IE/A1IE
    47.          digitalWrite(RTC_CS, HIGH);
    48.          delay(10);
    49.          digitalWrite(RTC_CS, LOW);
    50.          SPI.transfer(0x8F);
    51.          SPI.transfer(0x0);
    52.      digitalWrite(RTC_CS, HIGH);
    53.      delay(10);
    54.     SetAlarm();
    55.  //Turn on internal pullup for INT/SQW pin
    56.          pinMode(alarmPin, INPUT);
    57.          digitalWrite(alarmPin, HIGH);  
    58.          attachInterrupt(0, rtcAlarm, LOW);    
    59. }
    60.  
    61. void rtcAlarm(){
    62.   digitalWrite(RTC_CS, LOW);
    63.   SPI.transfer(0x8F);
    64.   SPI.transfer(0x0);
    65.   digitalWrite(RTC_CS, HIGH);
    66. }
    67.  
    68. void SetAlarm(){
    69.  delay(10);
    70.  digitalWrite(RTC_CS, LOW);
    71.  
    72.   //Set Alarm 1 to once per sec
    73.        
    74.   SPI.transfer(0x87);
    75.   SPI.transfer(0x80);
    76.  
    77.   digitalWrite(RTC_CS, HIGH);
    78.   delay(10);
    79.   digitalWrite(RTC_CS, LOW);
    80.  
    81.   SPI.transfer(0x88);
    82.   SPI.transfer(0x80);
    83.    
    84.   digitalWrite(RTC_CS, HIGH);
    85.   delay(10);
    86.   digitalWrite(RTC_CS, LOW);
    87.  
    88.   SPI.transfer(0x89);
    89.   SPI.transfer(0x80);
    90.   delay(10);
    91.  
    92.   digitalWrite(RTC_CS, HIGH);
    93.   delay(10);
    94.   digitalWrite(RTC_CS, LOW);
    95.  
    96.   SPI.transfer(0x8A);
    97.   SPI.transfer(0x80);
    98.   delay(10);
    99.  
    100.   digitalWrite(RTC_CS, HIGH);
    101. }
    102.  
    103.  
    104.  
    105.  
    106.  
    I then tried to program a PIC16F88 to take the place of Arduino. As i didn't want to program it in assembly, i started looking for a way to program it in C. After rejecting HI-TECH C compiler due to non-helpfull documentation, i ended up using CCS C compiler.

    I tried to replicate the commands used in the Arduino program, as it had proven to be working all right. After several hours, i managed to blink a led using an external interrupt with my PIC, but no luck in using the SPI.

    The code i have created so far is this:
    Code ( (Unknown Language)):
    1. #include <16F88.h>
    2. #device adc=8
    3.  
    4. #FUSES NOWDT                    //No Watch Dog Timer
    5. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
    6. #FUSES NOPUT                    //No Power Up Timer
    7. #FUSES NOMCLR                   //Master Clear pin used for I/O
    8. #FUSES BROWNOUT                 //Reset when brownout detected
    9. #FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
    10. #FUSES NOCPD                    //No EE protection
    11. #FUSES NOWRT                    //Program memory not write protected
    12. #FUSES NODEBUG                  //No Debug mode for ICD
    13. #FUSES NOPROTECT                //Code not protected from reading
    14. #FUSES FCMEN                    //Fail-safe clock monitor enabled
    15.  
    16. #use delay(clock=16000000)
    17. #INT_EXT
    18.  
    19.  
    20. void blink(){
    21.    output_high(PIN_A2);
    22.    delay_ms(1000);
    23.    output_low(PIN_A2);
    24.    delay_ms(1000);
    25.    clear_interrupt(INT_EXT);
    26.    output_low(PIN_B5);
    27.    spi_write(0x8F);
    28.    spi_write(0x0);
    29.    output_high(PIN_B5);
    30. }
    31.  
    32. void setalarm()
    33. {
    34.    output_low(PIN_B5);
    35.    spi_write(0x87);
    36.    spi_write(0x80);
    37.    output_high(PIN_B5);
    38.    delay_ms(10);
    39.    output_low(PIN_B5);  
    40.    spi_write(0x88);
    41.    spi_write(0x80);
    42.    output_high(PIN_B5);
    43.    delay_ms(10);
    44.    output_low(PIN_B5);  
    45.    spi_write(0x89);
    46.    spi_write(0x80);
    47.    output_high(PIN_B5);
    48.    delay_ms(10);
    49.    output_low(PIN_B5);  
    50.    spi_write(0x8A);
    51.    spi_write(0x80);
    52.    output_high(PIN_B5);
    53. }
    54.  
    55. void rtcinit()
    56. {
    57.    output_high(PIN_B5);
    58.    spi_write(0x8E);
    59.    spi_write(0x05);
    60.    output_low(PIN_B5);
    61.    delay_ms(10);
    62.    output_high(PIN_B5);  
    63.    spi_write(0x8F);
    64.    spi_write(0x00);
    65.    output_low(PIN_B5);
    66.    delay_ms(10);
    67.    setalarm();
    68. }
    69.  
    70. void main()
    71. {
    72.    output_low(PIN_B5);
    73.    setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
    74.    delay_ms(3000);
    75.    set_tris_a(0x00);
    76.    enable_interrupts(INT_EXT);
    77.    enable_interrupts(GLOBAL);
    78.    rtcinit();
    79.  
    80.    while(1){
    81.  
    82.    }
    83. }
    84.  
    85.  
    The connections on the breadboard are:

    ds3234 PIC16F88

    SQW -> RB0
    MISO -> RB1
    MOSI -> RB2
    CLK -> RB4
    SS -> RB5

    and i have a led connected in pin RA2.

    The led blinks if i manually cause an external interrupt on RB0, so i now that my basic connections (oscillator, ground, vcc and led) and programming are correct.

    However, an interrupt from the ds3234 never occurs, so there's something i'm not doing right with the SPI.

    Any help will be appreciated. :)
     
  2. b_gravedigger

    Thread Starter New Member

    May 12, 2009
    6
    0
    I managed to get it to work after all, so i'm posting the code here for future reference.

    Programming DS3234 RTC through SPI using PIC 16F88 (programming in C with CCS compiler).

    Code ( (Unknown Language)):
    1. #include <16F88.h>
    2.  
    3. #FUSES NOWDT                    //No Watch Dog Timer
    4. #FUSES INTRC_IO
    5. #FUSES NOPUT                    //No Power Up Timer
    6. #FUSES NOMCLR                   //Master Clear pin used for I/O
    7. #FUSES BROWNOUT                 //Reset when brownout detected
    8. #FUSES NOLVP                    
    9. #FUSES NOCPD                    //No EE protection
    10. #FUSES NOWRT                    //Program memory not write protected
    11. #FUSES NODEBUG                  //No Debug mode for ICD
    12. #FUSES NOPROTECT                //Code not protected from reading
    13. #FUSES FCMEN                    //Fail-safe clock monitor enabled
    14.  
    15. #define DS3234_CS  PIN_B5
    16.  
    17. #use delay(clock=8000000)
    18. //#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1)
    19.  
    20. #INT_EXT
    21. void ext_isr()
    22. {
    23.    output_high(PIN_A2);
    24.    delay_ms(150);
    25.    output_low(PIN_A2);
    26.    
    27.    output_low(DS3234_CS);
    28.    spi_write(0x8F);
    29.    spi_write(0x00);
    30.    output_high(DS3234_CS);
    31.    
    32.    ext_int_edge(H_TO_L);  
    33. }
    34.  
    35. void setalarm()
    36. {
    37.    output_low(DS3234_CS);
    38.    spi_write(0x87);
    39.    spi_write(0x80);
    40.    output_high(DS3234_CS);
    41.    
    42.    output_low(DS3234_CS);  
    43.    spi_write(0x88);
    44.    spi_write(0x80);
    45.    output_high(DS3234_CS);
    46.  
    47.    output_low(DS3234_CS);  
    48.    spi_write(0x89);
    49.    spi_write(0x80);
    50.    output_high(DS3234_CS);
    51.  
    52.    output_low(DS3234_CS);  
    53.    spi_write(0x8A);
    54.    spi_write(0x80);
    55.    output_high(DS3234_CS);
    56.    
    57.    output_low(DS3234_CS);  
    58.    spi_write(0x8F);
    59.    spi_write(0x00);
    60.    output_high(DS3234_CS);
    61. }
    62.  
    63. void rtcinit()
    64. {
    65.    output_low(DS3234_CS);
    66.    spi_write(0x8E);
    67.    spi_write(0x05);
    68.    output_high(DS3234_CS);
    69.    
    70.    output_low(DS3234_CS);  
    71.    spi_write(0x8F);
    72.    spi_write(0x00);
    73.    output_high(DS3234_CS);
    74.    
    75.    setalarm();
    76. }
    77.  
    78. void main()
    79. {
    80.    setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);
    81.    
    82.    rtcinit();
    83.    
    84.    enable_interrupts(INT_EXT);
    85.    enable_interrupts(GLOBAL);
    86.    
    87.    while(TRUE)
    88.    {
    89.    sleep();
    90.    }
    91. }

    Maybe i'll post a full description of the project when i finish it (that's after the exams period is over :D)
     
Loading...