Interfacing a DS1390/DS1391 RTC with a Motorola DSP with SPI
Abstract
This app note shows how to connect a DS1390 to a Motorola DSP that has a built-in SPI™ interface module. This circuit uses the Motorola DSP56F800DEMO Demonstration Board and CodeWarrior® IDE.
Description
The DS1390 Real-Time Clock (RTC) may be interfaced with a microcontroller (µC) or Digital Signal Processing (DSP) unit using a SPI interface. This app note shows how to connect a DS1390 to a Motorola DSP that has a built-in SPI interface module. This circuit uses the Motorola DSP56F800DEMO Demonstration Board and CodeWarrior IDE.
Using the Example Software
The example software was developed by starting with a blank project. Follow the instructions in the Motorola Kit Installation Guide (Tutorial: Creating a CodeWarrior Project) for details. Add the code included in this application note in main.c.
Operation
The program uses a GPIO port to control CS on the DS1390. The software initializes the SPI controller module and the DSP writes the time and date to the DS1390. The software then loops reading the time and date. The DS1390 and DS1391 support SPI modes 1and 3.
A schematic of the circuit is shown in Figure 1. This circuit comprises a daughter card that is attached to the Motorola demo board. Please note that the circuit in Figure 1 includes several RTCs with SPI interfaces. Only one RTC may be used at a time, and the software only supports the DS1390. The software is shown in Figure 2.

Figure 1.
Figure 2. Schematic of daughter card.
Figure 3. Code Listing
/* File: DS1390.c */
/* This example program was developed using the Motorola
56F800 Demo Board Kit. Follow the kit instalation guide
for creating a CodeWarrior Project. Use the shell of the
new project for this example. Note: This program is for
example only and is not supported by Dallas Semiconductor
Maxim. */
#include "port.h"
#include "stdio.h"
#include "stdlib.h"
/*******************************************************
* Main program for use with Embedded SDK
*******************************************************/
extern sampleASM (void);
void reset_spi(void);
void wbyte_spi(unsigned char);
void init_sci0(Word16);
tx_sci0(unsigned char);
void bcd2ascii(unsigned char);
unsigned char rbyte_spi(void);
#define REG_BASE 0x0000
#define SCI0_BASE 0x0F00
#define SPI_BASE 0x0F20
#define GPIOA_BASE 0x0FB0
#define GPIOB_BASE 0x0FC0
#define SCI0_SCIBR *(volatile UWord16 *)(SCI0_BASE + 0)
#define SCI0_SCICR *(volatile UWord16 *)(SCI0_BASE + 1)
#define SCI0_SCISR *(volatile UWord16 *)(SCI0_BASE + 2)
#define SCI0_SCIDR *(volatile UWord16 *)(SCI0_BASE + 3)
#define SPSCR *(volatile UWord16 *)(SPI_BASE + 0)
#define SPDSR *(volatile UWord16 *)(SPI_BASE + 1)
#define SPDRR *(volatile UWord16 *)(SPI_BASE + 2)
#define SPDTR *(volatile UWord16 *)(SPI_BASE + 3)
#define GPIO_A_PUR *(volatile UWord16 *)(GPIOA_BASE + 0)
#define GPIO_A_DR *(volatile UWord16 *)(GPIOA_BASE + 1)
#define GPIO_A_DDR *(volatile UWord16 *)(GPIOA_BASE + 2)
#define GPIO_A_PER *(volatile UWord16 *)(GPIOA_BASE + 3)
#define GPIO_B_PUR *(volatile UWord16 *)(GPIOB_BASE + 0)
#define GPIO_B_DR *(volatile UWord16 *)(GPIOB_BASE + 1)
#define GPIO_B_DDR *(volatile UWord16 *)(GPIOB_BASE + 2)
#define GPIO_B_PER *(volatile UWord16 *)(GPIOB_BASE + 3)
void main (void)
{
unsigned char msec=0, min=0x26, sec=0x00, hr=0x17, dow=0x06,
date=0x26, mon=0x12, yr=0x03, write = 0;
reset_spi();
init_sci0(195); // 30MHz / 195 = 9600 baud
GPIO_B_DR = 0x0008; // disable RTC - CS high
GPIO_B_DR = 0; // enable RTC - CS low
wbyte_spi(0x8d); // control register write address
rbyte_spi(); // dummy read
wbyte_spi(0x18); // enable osc, 32kHz sqw
rbyte_spi();
GPIO_B_DR = 0x0008; // disable RTC - CS high
if(write)
{
GPIO_B_DR = 0; // enable RTC - CS low
wbyte_spi(0x80); // select seconds register write address
rbyte_spi(); // dummy read
wbyte_spi(msec); // milliseconds register data
rbyte_spi();
wbyte_spi(sec); // seconds register data
rbyte_spi();
wbyte_spi(min); // minutes register
rbyte_spi();
wbyte_spi(hr); // hours register
rbyte_spi();
wbyte_spi(dow); // day of week register
rbyte_spi();
wbyte_spi(date); // date register
rbyte_spi();
wbyte_spi(mon); // month register
rbyte_spi();
wbyte_spi(yr); // year register
rbyte_spi();
GPIO_B_DR = 0x0008; // disable RTC - CS high
}
while(1)
{
GPIO_B_DR = 0u; // enable RTC - CS low
wbyte_spi(0); // seconds register read address
rbyte_spi(); // dummy read
wbyte_spi(0);
msec = rbyte_spi(); // read milliseconds register
wbyte_spi(0);
sec = rbyte_spi(); // read seconds register
wbyte_spi(0);
min = rbyte_spi(); // ditto minutes
wbyte_spi(0);
hr = rbyte_spi(); // and so on
wbyte_spi(0);
dow = rbyte_spi();
wbyte_spi(0);
date = rbyte_spi();
wbyte_spi(0);
mon = rbyte_spi();
wbyte_spi(0);
yr = rbyte_spi();
GPIO_B_DR = 0x0008; // disable RTC - CS high
tx_sci0(0x0d); // sequence to print time & date
tx_sci0(0x0a);
bcd2ascii(yr);
tx_sci0('/');
bcd2ascii(mon);
tx_sci0('/');
bcd2ascii(date);
tx_sci0(' ');
bcd2ascii(hr);
tx_sci0(':');
bcd2ascii(min);
tx_sci0(':');
bcd2ascii(sec);
}
return;
}
//SPSCR
//15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// r MSB SPRF ERRIE ovrf modf spte modfen spr1 spr0 sprie spmstr cpol cpha spe spite
void reset_spi()
{
int val;
SPSCR = 0x0056; // SPR0, SPMSTR, CPHA, SPE
SPDSR = 0x0007; // 8-bit size
SPSCR &= 0xfffd; // clear spe, resets SPI (partial)
SPSCR |= 0x0002; // set spe, new values take effect
GPIO_B_PER = 0x00f3; // use GPIOB3 as CS for RTC
GPIO_B_DDR = 0x000d; // direction is output
GPIO_A_PER = 0x00f9; // enable/disable per function (1=enable)
GPIO_A_DDR = 0x0006; // direction is output (1=output)
GPIO_A_DR = 0; // write bits low (0=low)
}
void wbyte_spi( unsigned char wbyte) // ------ write one byte -------
{
while (!(SPSCR & 0x0200)); // wait for transmitter empty flag
SPDTR = wbyte;
}
void bcd2ascii(unsigned char dat) // ----- convert bcd to ascii and send to sci ----
{
tx_sci0( (dat >> 4) + 0x30);
tx_sci0( (dat & 0x0f) + 0x30);
}
unsigned char rbyte_spi(void) // -------- read one byte ----------
{
while (!(SPSCR & 0x2000)); // wait for receiver full flag
return(SPDRR);
}
void init_sci0(Word16 baud)
{
GPIO_B_PER = 0x00f3; // set up
GPIO_B_DDR = 0x000d; // direction is output
SCI0_SCIBR = baud; // baud rate
SCI0_SCICR = 0x2000; // control reg
}
tx_sci0(unsigned char val)
{
UWord16 reg;
SCI0_SCICR &= 0xfffb; // turn receiver off
SCI0_SCICR |= 8; // turn transmitter on
do
{
reg = SCI0_SCISR; // clear flag by reading
} while( (reg & 0x8000) == 0); // wait until RDRF is false
SCI0_SCIDR = (unsigned int) (val);
}
