前言

TI-TMS320F2812(DSP2812)实现DS1308时钟芯片功能


一、原理图

依据数据手册(datasheet)参考设计:采用上拉电阻10K,晶振32.768kHz。

在这里插入图片描述
在这里插入图片描述

二、代码相关知识(需注意点)

1.串口初始化配置

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.读写时序及寄存器需注意点

在这里插入图片描述

在这里插入图片描述

三、代码

代码如下.h部分:

/*
 * DS1308.h
 *
 *  Created on: 2024-9-10
 *      Author: Administrator
 */

#ifndef DS1308_H_
#define DS1308_H_

#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "DSP281x_Examples.h"   // DSP281x Examples Include File


//I2C的IO口宏定义
#define IIC_SCL_SETH	(GpioDataRegs.GPASET.bit.GPIOA8=1)    //将引脚输出为高电平
#define IIC_SCL_SETL	(GpioDataRegs.GPACLEAR.bit.GPIOA8=1)  //将引脚输出为低电平

#define IIC_SDA_SETH	(GpioDataRegs.GPASET.bit.GPIOA9=1)    //将引脚输出为高电平
#define IIC_SDA_SETL	(GpioDataRegs.GPACLEAR.bit.GPIOA9=1)  //将引脚输出为低电平


#define READ_SDA   		(GpioDataRegs.GPADAT.bit.GPIOA9)

//DS1308宏定义
typedef struct
{
    Uint16 sec;
    Uint16 min;
    Uint16 hour;
    Uint16 week;
    Uint16 day;
    Uint16 month;
    Uint16 year;
} _calendar_part;    //时间结构体

extern _calendar_part calendar;


#define DS1308_Write_Address  0xD0  //写地址
#define DS1308_Read_Address   0xD1  //读地址

#define DS1308_SEC_REG        0x00  //秒
#define DS1308_MIN_REG        0x01  //分
#define DS1308_HOUR_REG       0x02  //时
#define DS1308_WDAY_REG       0x03  //星期
#define DS1308_MDAY_REG       0x04  //天
#define DS1308_MONTH_REG      0x05  //月
#define DS1308_YEAR_REG       0x06  //年


//IIC所有操作函数
void IICA_Init(void);                //初始化IIC的IO口
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(unsigned char txd);			//IIC发送一个字节
unsigned char IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
unsigned char IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

//DS1308操作函数
void DS1308_IIC_Write(u8 addr,u8 data) ;
u8 DS1308_IIC_Read(u8 addr);
void ModifyTime(u8 year,u8 month,u8 day,u8 hour,u8 min,u8 sec);
void get_time(void);

u8 BCD_DEC(u8 val);
u8 DEC_BCD(u8 val);

#endif /* IIC_H_ */

代码如下.c部分:

/*
 * DS1308.c
 *
 *  Created on: 2024-9-9
 *      Author: Administrator
 */

#include "DS1308.h"

/*******************************************************************************
* 函 数 名         : IIC_Init
* 函数功能         : IIC初始化
* 输    入         : 无
* 输    出         : 无
*
*******************************************************************************/
void IICA_Init(void)
{
    EALLOW;
    GpioMuxRegs.GPAMUX.bit.CAP1Q1_GPIOA8=0;  //将其设置为GPIO
    GpioMuxRegs.GPAMUX.bit.CAP2Q2_GPIOA9=0; //将其设置为GPIO
    GpioMuxRegs.GPADIR.bit.GPIOA8=1;// 输出端口
    GpioMuxRegs.GPADIR.bit.GPIOA9=1;// 输出端口
    GpioMuxRegs.GPAQUAL.all=0x0000;//输入采样限定关闭// GPIOA
    EDIS;
}

/*******************************************************************************
* 函 数 名         : SDA_OUT
* 函数功能         : SDA输出配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_OUT(void)
{
    EALLOW;
     GpioMuxRegs.GPADIR.bit.GPIOA9=1;       //Output. SDA
    EDIS;
}

/*******************************************************************************
* 函 数 名         : SDA_IN
* 函数功能         : SDA输入配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_IN(void)
{
    EALLOW;
     GpioMuxRegs.GPADIR.bit.GPIOA9=0;       //Input, SDA
    EDIS;
}

/*******************************************************************************
* 函 数 名         : IIC_Start
* 函数功能         : 产生IIC起始信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Start(void)
{
    SDA_OUT();     //sda线输出
    IIC_SDA_SETH;
    IIC_SCL_SETH;
    DELAY_US(14);
    IIC_SDA_SETL;//START:when CLK is high,DATA change form high to low
    DELAY_US(14);
    IIC_SCL_SETL;//钳住I2C总线,准备发送或接收数据
}

/*******************************************************************************
* 函 数 名         : IIC_Stop
* 函数功能         : 产生IIC停止信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Stop(void)
{
    SDA_OUT();//sda线输出
    IIC_SCL_SETL;
    IIC_SDA_SETL;//STOP:when CLK is high DATA change form low to high
    DELAY_US(14);
    IIC_SCL_SETH;
   // DELAY_US(6);
    IIC_SDA_SETH;//发送I2C总线结束信号
    DELAY_US(14);
}

/*******************************************************************************
* 函 数 名         : IIC_Wait_Ack
* 函数功能         : 等待应答信号到来
* 输    入         : 无
* 输    出         : 1,接收应答失败
                     0,接收应答成功
*******************************************************************************/
unsigned char IIC_Wait_Ack(void)
{
    unsigned char tempTime=0;

    SDA_IN();      //SDA设置为输入
    IIC_SDA_SETH;
    DELAY_US(10);
    IIC_SCL_SETH;
    DELAY_US(10);
    while(READ_SDA)
    {
        tempTime++;
        if(tempTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL_SETL;//时钟输出0
    return 0;
}

/*******************************************************************************
* 函 数 名         : IIC_Ack
* 函数功能         : 产生ACK应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Ack(void)
{
    IIC_SCL_SETL;
    SDA_OUT();
    IIC_SDA_SETL;
    DELAY_US(22);
    IIC_SCL_SETH;
    DELAY_US(22);
    IIC_SCL_SETL;
}

/*******************************************************************************
* 函 数 名         : IIC_NAck
* 函数功能         : 产生NACK非应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_NAck(void)
{
    IIC_SCL_SETL;
    SDA_OUT();
    IIC_SDA_SETH;
    DELAY_US(22);
    IIC_SCL_SETH;
    DELAY_US(22);
    IIC_SCL_SETL;
}

/*******************************************************************************
* 函 数 名         : IIC_Send_Byte
* 函数功能         : IIC发送一个字节
* 输    入         : txd:发送一个字节
* 输    出         : 无
*******************************************************************************/
void IIC_Send_Byte(unsigned char txd)
{
    unsigned char t;
    SDA_OUT();
    IIC_SCL_SETL;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
  //       if((txd&0x80)>0) //0x80  1000 0000
  //          IIC_SDA_SETH;
  //       else
  //           IIC_SDA_SETL;
  //       txd<<=1;
        if((txd&0x80)>>7)    IIC_SDA_SETH;
           else              IIC_SDA_SETL;
        txd<<=1;

        DELAY_US(22);
        IIC_SCL_SETH;
        DELAY_US(22);
        IIC_SCL_SETL;
        DELAY_US(22);
    }
}

/*******************************************************************************
* 函 数 名         : IIC_Read_Byte
* 函数功能         : IIC读一个字节
* 输    入         : ack=1时,发送ACK,ack=0,发送nACK
* 输    出         : 应答或非应答
*******************************************************************************/
unsigned char IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        IIC_SCL_SETL;
        DELAY_US(22);
        IIC_SCL_SETH;
        receive<<=1;
        if(READ_SDA)receive++;
        DELAY_US(20);
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK
    return receive;
}

//DS1308操作函数
void DS1308_IIC_Write(u8 addr,u8 data)  //写数据
{
    IIC_Start();
    IIC_Send_Byte(DS1308_Write_Address);
    IIC_Wait_Ack();
    DELAY_US(5);
    IIC_Send_Byte(addr);
    IIC_Wait_Ack();
    DELAY_US(5);
    IIC_Send_Byte(data);
    IIC_Wait_Ack();
    DELAY_US(5);
    IIC_Stop();
}


u8 DS1308_IIC_Read(u8 addr) //读数据
{
    u8 data_s;
    IIC_Start();
    IIC_Send_Byte(DS1308_Write_Address);
    IIC_Wait_Ack();
    DELAY_US(15);
    IIC_Send_Byte(addr);
    IIC_Wait_Ack();
    DELAY_US(5);
    IIC_Start();
    IIC_Send_Byte(DS1308_Read_Address);
    IIC_Wait_Ack();
    DELAY_US(50);
    data_s = IIC_Read_Byte(0);
    IIC_Stop();
    return data_s;
}

void ModifyTime(u8 year,u8 month,u8 day,u8 hour,u8 min,u8 sec)//修改时间
{
    u8 temp;

    temp = DEC_BCD(year);
    DS1308_IIC_Write(DS1308_YEAR_REG,temp);


    temp = DEC_BCD(month);
    DS1308_IIC_Write(DS1308_MONTH_REG,temp);


    temp = DEC_BCD(day);
    DS1308_IIC_Write(DS1308_MDAY_REG,temp);


    temp = DEC_BCD(hour);
    DS1308_IIC_Write(DS1308_HOUR_REG,temp);


    temp = DEC_BCD(min);
    DS1308_IIC_Write(DS1308_MIN_REG,temp);


    temp = DEC_BCD(sec);
    DS1308_IIC_Write(DS1308_SEC_REG,temp);

}



void get_time(void)//获取时间
{

    calendar.year = DS1308_IIC_Read(DS1308_YEAR_REG);
    calendar.year = BCD_DEC(calendar.year);


    calendar.month = DS1308_IIC_Read(DS1308_MONTH_REG);
    calendar.month = BCD_DEC(calendar.month);


    calendar.day = DS1308_IIC_Read(DS1308_MDAY_REG);
    calendar.day = BCD_DEC(calendar.day);


    calendar.hour = DS1308_IIC_Read(DS1308_HOUR_REG);
    calendar.hour &= 0x3f;
    calendar.hour = BCD_DEC(calendar.hour);


    calendar.min = DS1308_IIC_Read(DS1308_MIN_REG);
    calendar.min = BCD_DEC(calendar.min);


    calendar.sec = DS1308_IIC_Read(DS1308_SEC_REG);
    calendar.sec = BCD_DEC(calendar.sec);

}

u8 BCD_DEC(u8 val)//BCD码转化为十进制
{
    u8 temp;
    temp=val&0x0f;
    val>>=4;
    val&=0x0f;
    val*=10;
    temp+=val;
    return temp;
}

u8 DEC_BCD(u8 val)//十进制转化为BCD码
{
    u8 i,j,k;
    i=val/10;
    j=val%10;
    k=j+(i<<4);
    return k;
}


2.main调用代码部分(仅展示有DS1308部分)

代码如下:

#include "DS1308.h"

_calendar_part calendar;//DS1308声明时钟结构体

void main(void)
{
IICA_Init();
ModifyTime(24,9,12,12,58,45); //写入DS1308时钟芯片时间的初始值
while (1)
	{
	    get_time();
	    SendString("   DATA:  ");
	    SendUint16DecAscii(calendar.year);
	    SendString(" 年 ");
	    SendUint16DecAscii(calendar.month);
	    SendString(" 月 ");
	    SendUint16DecAscii(calendar.day);
	    SendString(" 日 ");
	    SendUint16DecAscii(calendar.hour);
	    SendString(" : ");
	    SendUint16DecAscii(calendar.min);
	    SendString(" : ");
	    SendUint16DecAscii(calendar.sec);
	    SendString("\n\r");
	}
}


总结

DS1308使用I2C通信,在使用时需注意时序及寄存器的准确性。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐