DS1390/DS1391 RTC与Motorola SPI接口DSP的连接

Abstract

本应用笔记说明了DS1390与内置SPI™接口的Motorola DSP的连接方式,该电路使用了Motorola DSP56F800DEMO开发板和CodeWarrior® IDE。

说明

DS1390实时时钟(RTC)可以通过SPI接口与微控制器(µC)或数字信号处理器(DSP)单元连接,本应用笔记给出了DS1390与内置SPI接口的Motorola DSP的连接方式。该电路使用了Motorola DSP56F800DEMO开发板和CodeWarrior IDE。

使用例程

本例程从新建空白项目开始,详细资料请参考Motorola工具包安装指南指南:创建CodeWarrior项目。本应用笔记的增加代码在main.c中。

操作过程

该程序通过GPIO口控制DS1390的CS。由软件初始化SPI控制器,DSP向DS1390内部写入时间和日期。然后,该软件可以循环读取时间和日期。DS1390和DS1391支持SPI模式1和模式3。

原理图如图1所示,该电路包含一个子卡,附有Motorola开发板。请注意,图1电路中包括几款带有SPI接口的RTC。每次只需使用一款RTC,本文给出了程序仅支持DS1390。程序清单如图2所示。

图1.
图1.

图2. 子卡原理图
详细电路图
(PDF, 138kB)
图2. 子卡原理图

图3. 程序清单

/* 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);
}