MSP430 DS1302 驱动

sys.h里面需要一些延时函数。

ds1302.h


#ifndef __DS1302_H
#define __DS1302_H

#include "msp430.h"
#include "sys.h"

struct ds1302time
{
	int	year;
	unsigned char	mouth;
	unsigned char	day;
	unsigned char	week;
	unsigned char	hour;
	unsigned char	minute;
	unsigned char	second;
};

void DS1302_read_time( struct ds1302time *p );//获取时间
void DS1302_write_time( struct ds1302time *p );//写入时间
int getWeekdayByYearday( int iY, int iM, int iD );//获取星期几


#endif

ds1302.c

#include "DS1302.h"


/**************宏定义***************/
#define DS_RST		BIT7    /* DS_RST = P2.7 */
#define DS_SCL		BIT5    /* DS_SCL = P2.5 */
#define DS_SDA		BIT6    /* DS_SDA = P2.6 */
#define DS_RST_IN	P2DIR	&= ~DS_RST
#define DS_RST_OUT	P2DIR	|= DS_RST
#define DS_RST0		P2OUT	&= ~DS_RST
#define DS_RST1		P2OUT	|= DS_RST
#define DS_SCL_IN	P2DIR	&= ~DS_SCL
#define DS_SCL_OUT	P2DIR	|= DS_SCL
#define DS_SCL0		P2OUT	&= ~DS_SCL
#define DS_SCL1		P2OUT	|= DS_SCL
#define DS_SDA_IN	P2DIR	&= ~DS_SDA
#define DS_SDA_OUT	P2DIR	|= DS_SDA
#define DS_SDA0		P2OUT	&= ~DS_SDA
#define DS_SDA1		P2OUT	|= DS_SDA
#define DS_SDA_BIT	(P2IN & DS_SDA)


/* DS1302地址定义 */
#define ds1302_sec_add		0x80    /* 秒数据地址 */
#define ds1302_min_add		0x82    /* 分数据地址 */
#define ds1302_hr_add		0x84    /* 时数据地址 */
#define ds1302_date_add		0x86    /* 日数据地址 */
#define ds1302_month_add	0x88    /* 月数据地址 */
#define ds1302_day_add		0x8a    /* 星期数据地址 */
#define ds1302_year_add		0x8c    /* 年数据地址 */
#define ds1302_control_add	0x8e    /* 控制数据地址 */
#define ds1302_charger_add	0x90
#define ds1302_clkburst_add	0xbe


/* 向DS1302写入一个字节数据 */
void W_Data( unsigned char addr, unsigned char data )
{
	unsigned char i;
        DS_RST_OUT;DS_SCL_OUT;DS_SDA_OUT;
        
	DS_RST0;            /* 停止DS1302总线 */
	DS_SCL0;            /* 清零时钟线 */
	delay_us( 10 );
	DS_RST1;            /* 启动DS1302总线 */
	addr		= addr & 0xFE;  /* 最低位置零,写数据 */
	DS_SDA_OUT;
	for ( i = 0; i < 8; i++ )       /* 写地址 */
	{
		DS_SCL0;
		if ( addr & 0x01 )
			DS_SDA1;
		else
			DS_SDA0;

		addr		= addr >> 1;
		DS_SCL1;    /* 产生时钟在上升沿输出数据到DS1302 */
		delay_us( 9 );
	}
	for ( i = 0; i < 8; i++ )       /* 写数据 */
	{
		DS_SCL0;
		if ( data & 0x01 )
			DS_SDA1;
		else
			DS_SDA0;
		data		= data >> 1;
		DS_SCL1;    /* 产生时钟在上升沿输出数据到DS1302 */
		delay_us( 9 );
	}
	DS_RST0;                 /* 停止DS1302总线 */
}


/* 从DS1302读出一个字节数据 */
unsigned char R_Data( unsigned char addr )
{
	unsigned char i, temp;
        DS_RST_OUT;DS_SCL_OUT;DS_SDA_OUT;
        
	DS_RST0;            /* 停止DS1302总线 */
	DS_SCL0;            /* 清零时钟线 */
	delay_us( 10 );
	DS_RST1;            /* 启动DS1302总线 */
	addr		= addr | 0x01;  /* 最低位置高,读数据 */
	DS_SDA_OUT;
	for ( i = 0; i < 8; i++ )       /* 写地址 */
	{
		DS_SCL0;
		if ( addr & 0x01 )
			DS_SDA1;
		else
			DS_SDA0;
		addr		= addr >> 1;
		DS_SCL1;    /* 产生时钟在上升沿输出数据到DS1302 */
		delay_us( 9 );
	}
	DS_SDA_IN;
	for ( i = 0; i < 8; i++ )       /* 读数据 */
	{
		if ( DS_SDA_BIT )
			temp |= 0x80;
		else
			temp &= 0x7F;
		DS_SCL1;    /* 产生时钟在下升沿输出数据到DS1302 */
		temp		= temp >> 1;
		DS_SCL0;
		delay_us( 9 );
	}
	DS_RST0;                 /* 停止DS1302总线 */
	return(temp);
}


/*******************************************
 * 函数名称:Set_DS1302
 * 功    能:设置DS1302内部的时间
 * 参    数:ptr--指向存放数据地址的指针
 * 返回值  :无
 * 说明    :写入数据的格式:
 *          秒 分 时 日 月 星期 年  【共7个字节】
 ********************************************/
void Set_DS1302( unsigned char *ptr )
{
	unsigned char	i;
	unsigned char	addr = 0x80;

	W_Data( 0x8e, 0x00 );                           /* 允许写入 */

	for ( i = 7; i > 0; i-- )
	{
		W_Data( addr, *ptr++ );
		addr += 2;
	}
	W_Data( 0x8e, 0x80 );                           /* 禁止 */
}


/* 从DS302读出时钟数据 */
void DS1302_Read_Time( unsigned char *ptr )
{
	ptr[1]	= R_Data( ds1302_year_add );            /* 年 */
	ptr[2]	= R_Data( ds1302_month_add );           /* 月 */
	ptr[3]	= R_Data( ds1302_date_add );            /* 日 */
	ptr[4]	= R_Data( ds1302_hr_add );              /* 时 */
	ptr[5]	= R_Data( ds1302_min_add );             /* 分 */
	ptr[6]	= (R_Data( ds1302_sec_add ) ) & 0x7f;   /* 秒,屏蔽秒的第7位,避免超出59 */
	ptr[7]	= R_Data( ds1302_day_add );             /* 周 */
}


/* 获取时间 */
void DS1302_read_time( struct ds1302time *p )
{
	/* 年月日 时分秒 星期 */
	unsigned char time_buf[8] = { 0x20, 0x20, 0x03, 0x03, 0x23, 0x59, 0x55, 0x02 };


	DS1302_Read_Time( time_buf ); /* 读取 */

	p->year		= 2000 + (time_buf[1] >> 4) * 10 + (time_buf[1] & 0x0f);
	p->mouth	= (time_buf[2] >> 4) * 10 + (time_buf[2] & 0x0f);
	p->day		= (time_buf[3] >> 4) * 10 + (time_buf[3] & 0x0f);

	p->hour		= (time_buf[4] >> 4) * 10 + (time_buf[4] & 0x0f);
	p->minute	= (time_buf[5] >> 4) * 10 + (time_buf[5] & 0x0f);
	p->second	= (time_buf[6] >> 4) * 10 + (time_buf[6] & 0x0f);

	p->week = (time_buf[7] >> 4) * 10 + (time_buf[7] & 0x0f);
}


/* 写入时间 */
void DS1302_write_time( struct ds1302time *p )
{
	/* 年月日 时分秒 星期 */
	unsigned char time_buf[8] = { 0x20, 0x20, 0x03, 0x03, 0x23, 0x59, 0x55, 0x02 };

	time_buf[1]	= p->year % 100 / 10 * 16 + p->year % 100 % 10;
	time_buf[2]	= p->mouth % 100 / 10 * 16 + p->mouth % 100 % 10;
	time_buf[3]	= p->day % 100 / 10 * 16 + p->day % 100 % 10;
	time_buf[4]	= p->hour % 100 / 10 * 16 + p->hour % 100 % 10;
	time_buf[5]	= p->minute % 100 / 10 * 16 + p->minute % 100 % 10;
	time_buf[6]	= p->second % 100 / 10 * 16 + p->second % 100 % 10;
	time_buf[7]	= p->week % 100 / 10 * 16 + p->week % 100 % 10;

	W_Data( ds1302_control_add, 0x00 );             /* 关闭写保护 */
	W_Data( ds1302_sec_add, 0x80 );                 /* 暂停时钟 */
	/* DS1302_Write_Byte(ds1302_charger_add, 0xA9);      //涓流充电 */
	W_Data( ds1302_year_add, time_buf[1] );         /* 年 */
	W_Data( ds1302_month_add, time_buf[2] );        /* 月 */
	W_Data( ds1302_date_add, time_buf[3] );         /* 日 */
	W_Data( ds1302_hr_add, time_buf[4] );           /* 时 */
	W_Data( ds1302_min_add, time_buf[5] );          /* 分 */
	W_Data( ds1302_sec_add, time_buf[6] );          /* 秒 */
	W_Data( ds1302_day_add, time_buf[7] );          /* 周 */
	W_Data( ds1302_control_add, 0x80 );             /* 打开写保护 */
}


/*
 * 由年月日获取星期 https://www.cnblogs.com/fengbohello/p/3264300.html
 * 返回1到7 代表星期一到星期天
 */
int getWeekdayByYearday( int iY, int iM, int iD )
{
	int iWeekDay = -1;
	if ( 1 == iM || 2 == iM )
	{
		iM += 12;
		iY--;
	}
	iWeekDay = (iD + 1 + 2 * iM + 3 * (iM + 1) / 5 + iY + iY / 4 - iY / 100 + iY / 400) % 7;
	if ( iWeekDay == 0 )
		iWeekDay = 7;
	return(iWeekDay);
}



使用:
定义时间变量结构体:

struct ds1302time	time;           /* DS1302时间 */

写入时间:

    time.year	= 2020;
	time.mouth	= 3;
	time.day	= 13;
	time.hour	= 12;
	time.minute	= 55;
	time.second	= 55;
	time.week	= getWeekdayByYearday( time.year, time.mouth, time.day );
	DS1302_write_time( &time );                                             /* 写入时间 */

更新时间time:

DS1302_read_time( &time );//读取时间
time.week = getWeekdayByYearday( time.year, time.mouth, time.day );//
上一篇:msp430的几个2B问题集锦


下一篇:MSP430-时钟系统和GPIO