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 );//
标签:ds1302,DS1302,add,time,驱动,buf,DS,MSP430 来源: https://blog.csdn.net/x1131230123/article/details/104886378