SPI Comunication

Ok so I am having problems with my DS3234 and after a lot of help and trial and error it looks like it is being caused by my sd card reader. any help in showing my how to switch between the 2 will be appreciated. thank you

// DS3234_Serial_Easy 
// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
// web: http://www.RinkyDinkElectronics.com/
//
// A quick demo of how to use my DS3234 library to 
// quickly send time and date information over a serial link
//
// Connections:
// ------------
//            |              Arduino             |         |        chipKit        |
// | DS3234   |  Uno  | Mega  |  Due  | Leonardo | Bobuino | Uno32 | uC32  | Max32 |
// +----------+-------+-------+-------+----------+---------+-------+-------+-------+
// | DIN      |  D11  |  D51  |  D75  |   D16    |   D11   |  D11  |  D11  |  D51  |  -> MOSI
// | DOUT     |  D12  |  D50  |  D74  |   D14    |   D12   |  D12  |  D12  |  D50  |  -> MISO
// | SCLK     |  D13  |  D52  |  D76  |   D15    |   D13   |  D13  |  D13  |  D52  |
// | CS       |        User selectable (Set to D8 by default in this demo)         |
// +----------+-------+-------+-------+----------+---------+-------+-------+-------+
//
// Note that the SPI pins are only available on the ICSP header
// on the Arduino Due and Arduino Leonardo.
// Boards with SPI Master/Slave Select jumpers should be set to the Master position.
//
// ICSP header pinout:      +---+---+
//                1 - MISO  | X | X |  2 - Vcc
//                          +---+---+
//                3 - SCLK  | X | X |  4 - MOSI
//                          +---+---+
//                5 - Reset | X | X |  6 - GND
//                          +---+---+
//

#include <DS3234.h>
#include<SPI.h>
// Init the DS3234
DS3234 rtc(8);

void setup()
{
  // Initialize the rtc object
  rtc.begin();
  
  pinMode(8, OUTPUT);
  pinMode(53, OUTPUT);
  digitalWrite(53, HIGH);
  digitalWrite(8, LOW);
  // Setup Serial connection
  Serial.begin(115200);
#ifdef __AVR_ATmega32U4__
  while (!Serial) {}; // wait for serial port to connect. Needed for Arduino Leonardo only
#endif

  // The following lines can be uncommented and edited to set the time and date in the DS3234
//  rtc.setDOW(SATURDAY);        // Set Day-of-Week to SATURDAY
//  rtc.setTime(12, 0, 0);       // Set the time to 12:00:00 (24hr format)
//  rtc.setDate(25, 1, 2014);    // Set the date to January 25th, 2014
}

void loop()
{
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.print(rtc.getTimeStr());
  Serial.print(" -- ");
  
  // Send temperature
  Serial.print("Internal temp: ");
  Serial.print(rtc.getTemp());
  Serial.println("C");
  // Wait one second before repeating :)
  delay (1000);
}

I am using a mega 2560 with ITDB05-5 and the mega shield thanks

Two different SPI modes. One or the other library will have to be modified to always set the SPI mode before starting a transfer.

Ok how do I go about doing that?
this is the library for the DS3234

DS3234.cpp (8.96 KB)

DS3234.h (2.8 KB)

keywords.txt (621 Bytes)

Tough with that library. The one that I found here for the 3234 was a little easier to fix. I had the same issue between it and my LCD.

https://bitbucket.org/KristoZ/arduino-ds3234-rtc-library

Fortunately this library has a method call just to set the chip select pin. That seemed wasteful until I needed this fix.

I changed this:

void DS3234RTC::cs(int _value)
{
  digitalWrite(cs_pin,_value);
}

To this, where my LCD requires SPImode0 and the RTC needs mode1.

void DS3234RTC::cs(int _value)
{
	if(_value == LOW){
		SPI.setDataMode(SPI_MODE1);
	} else {
		SPI.setDataMode(SPI_MODE0);
	}
  digitalWrite(cs_pin,_value);
}

Now, any time the RTC wants to communicate, it sets its own SPI mode. When it releases the CS pin, it turns it back to what the rest of my program needs.

you cant switch it in the program itself? I can open the .ccp but it will not let me save as same with notepad

You can but it would be a pain.

Copy the library into your sketch folder and make the changes there. So you'll have a separate copy for just this project.

That didn't work, it just threw up error codes for the .cpp

What I find funny though is in the sketch I'm not calling any sd functions, the library is not even included in the sketch. How is it just being plugged in interfering with the rtc? If the sd is ss for 53 and I put it HIGH the rtc should work

What is the ss pin for the rtc?

Post the code that threw the error. I've been using that fix and it compiles fine for me.

the rtc is on pin 8,
the sketch

#include <Time.h>
#include <SPI.h>
#include <Wire.h>
#include <DS3234RTC.h>

void setup () {
  Serial.begin(9600);
  pinMode(53, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(53, HIGH);
  digitalWrite(8, LOW);
  SPI.setDataMode(SPI_MODE1);
  RTC.begin(8); //Start the RTC using the chip select pin it's connected to
  //Optional: Check whether the RTC has been correctly connected
  if (RTC.isRunning()) {
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus()!= timeSet) 
      Serial.println("Unable to sync with the RTC");
    else
      Serial.println("RTC has set the system time");  
  }  
  else
    Serial.println("ERROR: RTC is NOT connected!");     
}

void loop () {
  if(Serial.available())
  {
    time_t t = processSyncMessage();
    if(t >0)
    {
      RTC.set(t);   // set the RTC and the system time to the received value
      setTime(t);   
      setSyncProvider(RTC.get);   // the function to get the time
      Serial.println("RTC has set the system time");            
    } 
  }

  //Optional: Update system time from RTC
  //Every day at 23:00:00
  if ((hour(now()) % 23 == 0) && (minute(now()) % 0 == 0) && (second(now()) % 0 == 0)) {
    setTime(RTC.get());
    if(timeStatus()!= timeSet) 
      Serial.println("Unable to sync with the RTC");
    else
      Serial.println("RTC has set the system time");    
  }

  digitalClockDisplay();  
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(year());
  Serial.print(".");
  Serial.print(month());
  Serial.print(".");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*  code to process time sync messages from the serial port   */
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message

time_t processSyncMessage() {
  // return the time if a valid sync message is received on the serial port.
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    char c = Serial.read() ; 
    Serial.print(c);  
    if( c == TIME_HEADER ) {       
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        c = Serial.read();          
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      }   
      return pctime; 
    }  
  }
  return 0;
}[code]

the .cpp

/*
 * DS3234RTC.h - library for DS3234 RTC
 * Assembled by KristoZ (http://kristoz.com)

  This library is intended to be used with Arduino Time.h library functions

  The library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
 */

#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

#include <avr/pgmspace.h>
#include <SPI.h>
#include "DS3234RTC.h"

const int CONTROL_R = 0x0e;
const int CONTROL_W = 0x8e;
const int CONTROL_STATUS_R = 0x0f;
const int CONTROL_STATUS_W = 0x8f;
const int SECONDS_R = 0x00;
const int SECONDS_W = 0x80;
const int MODE = 0x60; //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
const int EOSC = 7;
const int OSF = 7;
int cs_pin;

DS3234RTC::DS3234RTC() {
  SPI.begin();
}
void DS3234RTC::begin(int _cs_pin)
{
  cs_pin = _cs_pin;
  pinMode(cs_pin,OUTPUT);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work 
  cs(LOW);
  SPI.transfer(CONTROL_W);
  SPI.transfer(MODE); 
  cs(HIGH);
  delay(10);
}

void DS3234RTC::cs(int _value)
{
	if(_value == LOW){
		SPI.setDataMode(SPI_MODE1);
	} else {
		SPI.setDataMode(SPI_MODE0);
	}
  digitalWrite(cs_pin,_value);

bool DS3234RTC::isRunning()
{
  cs(LOW);
  SPI.transfer(CONTROL_R);
  uint8_t ss = SPI.transfer(-1);
  cs(HIGH);
  return !(ss & _BV(OSF));
}

time_t DS3234RTC::get()   // Aquire data from buffer and convert to time_t
{
  tmElements_t tm;
  read(tm);
  time_t rt = makeTime(tm);
  return(rt);
}

void  DS3234RTC::set(time_t t)
{
  tmElements_t tm;
  breakTime(t, tm);
  int TimeDate [7]={
    second(t),minute(t),hour(t),weekday(t),day(t),month(t),year(t)-2000  };
  for(int i=0; i<=6;i++){
    if(i==3)
      i++;
    int b= TimeDate[i]/10;
    int a= TimeDate[i]-b*10;
    if(i==2){
      if (b==2)
        b=B00000010;
      else if (b==1)
        b=B00000001;
    }	
    TimeDate[i]= a+(b<<4);
    cs(LOW);
    SPI.transfer(i+SECONDS_W); 
    SPI.transfer(TimeDate[i]);        
    cs(HIGH);
  }
}

// Aquire data from the RTC chip in BCD format
void DS3234RTC::read( tmElements_t &tm)
{
  cs(LOW);
  SPI.transfer(SECONDS_R);
  tm.Second = bcd2dec(SPI.transfer(-1) & 0x7F); 
  tm.Minute = bcd2dec(SPI.transfer(-1));
  tm.Hour = bcd2dec(SPI.transfer(-1));  // mask assumes 24hr clock
  tm.Wday = bcd2dec(SPI.transfer(-1));
  tm.Day = bcd2dec(SPI.transfer(-1));
  tm.Month = bcd2dec(SPI.transfer(-1));
  tm.Year = y2kYearToTm((bcd2dec(SPI.transfer(-1))));
  cs(HIGH);
}

// PRIVATE FUNCTIONS

// Convert Decimal to Binary Coded Decimal (BCD)
uint8_t DS3234RTC::dec2bcd(uint8_t num)
{
  return ((num/10 * 16) + (num % 10));
}

// Convert Binary Coded Decimal (BCD) to Decimal
uint8_t DS3234RTC::bcd2dec(uint8_t num)
{
  return ((num/16 * 10) + (num % 16));
}

DS3234RTC RTC = DS3234RTC(); // create an instance for the user[code]

the error

Arduino: 1.6.1 (Windows 7), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

DS3234RTC.cpp: In static member function 'static void DS3234RTC::cs(int)':

DS3234RTC.cpp:65:1: error: a function-definition is not allowed here before '{' token

 {

 ^

DS3234RTC.cpp:74:1: error: a function-definition is not allowed here before '{' token

 {

 ^

DS3234RTC.cpp:82:1: error: a function-definition is not allowed here before '{' token

 {

 ^

DS3234RTC.cpp:135:28: error: expected '}' at end of input

 DS3234RTC RTC = DS3234RTC(); // create an instance for the user

                            ^

Error compiling.

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
[code]

It appears you forgot a brace.

void DS3234RTC::cs(int _value)
{
	if(_value == LOW){
		SPI.setDataMode(SPI_MODE1);
	} else {
		SPI.setDataMode(SPI_MODE0);
	}
  digitalWrite(cs_pin,_value);

// you forgot the closing brace here
}
 

bool DS3234RTC::isRunning()
{

Ah yes thank you. Hopefully I will get a chance latter to try it

ok well I was able to get back to this. I downloaded notepad++ and changed the .cpp file as directed. I uploaded it to the arduino and results are the same. when I open the serial connection it displays 1999.12.31 0:00:00, seconds increment properly and minutes roll up when appropriate. when the sd reader is unplugged and serial monitor is reopened then current time and date will display.
the sketch

#include <Time.h>
#include <SPI.h>
#include <Wire.h>
#include <DS3234RTC.h>

void setup () {
  Serial.begin(9600);
  pinMode(53, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(53, HIGH);
  digitalWrite(8, LOW);
  SPI.setDataMode(SPI_MODE1);
  RTC.begin(8); //Start the RTC using the chip select pin it's connected to
  //Optional: Check whether the RTC has been correctly connected
  if (RTC.isRunning()) {
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus()!= timeSet) 
      Serial.println("Unable to sync with the RTC");
    else
      Serial.println("RTC has set the system time");  
  }  
  else
    Serial.println("ERROR: RTC is NOT connected!");     
}

void loop () {
  if(Serial.available())
  {
    time_t t = processSyncMessage();
    if(t >0)
    {
      RTC.set(t);   // set the RTC and the system time to the received value
      setTime(t);   
      setSyncProvider(RTC.get);   // the function to get the time
      Serial.println("RTC has set the system time");            
    } 
  }

  //Optional: Update system time from RTC
  //Every day at 23:00:00
  if ((hour(now()) % 23 == 0) && (minute(now()) % 0 == 0) && (second(now()) % 0 == 0)) {
    setTime(RTC.get());
    if(timeStatus()!= timeSet) 
      Serial.println("Unable to sync with the RTC");
    else
      Serial.println("RTC has set the system time");    
  }

  digitalClockDisplay();  
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(year());
  Serial.print(".");
  Serial.print(month());
  Serial.print(".");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*  code to process time sync messages from the serial port   */
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message

time_t processSyncMessage() {
  // return the time if a valid sync message is received on the serial port.
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    char c = Serial.read() ; 
    Serial.print(c);  
    if( c == TIME_HEADER ) {       
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        c = Serial.read();          
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      }   
      return pctime; 
    }  
  }
  return 0;
}[code]

the .cpp

/*
 * DS3234RTC.h - library for DS3234 RTC
 * Assembled by KristoZ (http://kristoz.com)

  This library is intended to be used with Arduino Time.h library functions

  The library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
 */

#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

#include <avr/pgmspace.h>
#include <SPI.h>
#include "DS3234RTC.h"

const int CONTROL_R = 0x0e;
const int CONTROL_W = 0x8e;
const int CONTROL_STATUS_R = 0x0f;
const int CONTROL_STATUS_W = 0x8f;
const int SECONDS_R = 0x00;
const int SECONDS_W = 0x80;
const int MODE = 0x60; //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
const int EOSC = 7;
const int OSF = 7;
int cs_pin;

DS3234RTC::DS3234RTC() {
  SPI.begin();
}
void DS3234RTC::begin(int _cs_pin)
{
  cs_pin = _cs_pin;
  pinMode(cs_pin,OUTPUT);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work 
  cs(LOW);
  SPI.transfer(CONTROL_W);
  SPI.transfer(MODE); 
  cs(HIGH);
  delay(10);
}



void DS3234RTC::cs(int _value)
{
	if(_value == LOW){
		SPI.setDataMode(SPI_MODE1);
	} else {
		SPI.setDataMode(SPI_MODE0);
	}
  digitalWrite(cs_pin,_value);
}



bool DS3234RTC::isRunning()
{
  cs(LOW);
  SPI.transfer(CONTROL_R);
  uint8_t ss = SPI.transfer(-1);
  cs(HIGH);
  return !(ss & _BV(OSF));
}

time_t DS3234RTC::get()   // Aquire data from buffer and convert to time_t
{
  tmElements_t tm;
  read(tm);
  time_t rt = makeTime(tm);
  return(rt);
}

void  DS3234RTC::set(time_t t)
{
  tmElements_t tm;
  breakTime(t, tm);
  int TimeDate [7]={
    second(t),minute(t),hour(t),weekday(t),day(t),month(t),year(t)-2000  };
  for(int i=0; i<=6;i++){
    if(i==3)
      i++;
    int b= TimeDate[i]/10;
    int a= TimeDate[i]-b*10;
    if(i==2){
      if (b==2)
        b=B00000010;
      else if (b==1)
        b=B00000001;
    }	
    TimeDate[i]= a+(b<<4);
    cs(LOW);
    SPI.transfer(i+SECONDS_W); 
    SPI.transfer(TimeDate[i]);        
    cs(HIGH);
  }
}

// Aquire data from the RTC chip in BCD format
void DS3234RTC::read( tmElements_t &tm)
{
  cs(LOW);
  SPI.transfer(SECONDS_R);
  tm.Second = bcd2dec(SPI.transfer(-1) & 0x7F); 
  tm.Minute = bcd2dec(SPI.transfer(-1));
  tm.Hour = bcd2dec(SPI.transfer(-1));  // mask assumes 24hr clock
  tm.Wday = bcd2dec(SPI.transfer(-1));
  tm.Day = bcd2dec(SPI.transfer(-1));
  tm.Month = bcd2dec(SPI.transfer(-1));
  tm.Year = y2kYearToTm((bcd2dec(SPI.transfer(-1))));
  cs(HIGH);
}

// PRIVATE FUNCTIONS

// Convert Decimal to Binary Coded Decimal (BCD)
uint8_t DS3234RTC::dec2bcd(uint8_t num)
{
  return ((num/10 * 16) + (num % 10));
}

// Convert Binary Coded Decimal (BCD) to Decimal
uint8_t DS3234RTC::bcd2dec(uint8_t num)
{
  return ((num/16 * 10) + (num % 16));
}

DS3234RTC RTC = DS3234RTC(); // create an instance for the user
[code]

No one has an awnser?

So like I mentioned if I unplug the sd card the rtc works fine without a change in the sketch. Further playing determains I don’t need to unplug the whole sd…just the miso line and the rtc works fine without change in code. Ideas?

The DS3234 RTC is a mode 1 device, and the SD card is mode 0.

  SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work

You must switch the SPI mode when changing from one device to the other.

// change to mode 1 for the RTC
  SPI.setDataMode(SPI_MODE1);
// do the RTC stuff here
// then change back to mode 0 for the SD card
  SPI.setDataMode(SPI_MODE0);