初级会员
- 积分
- 145
- 金钱
- 145
- 注册时间
- 2016-2-25
- 在线时间
- 44 小时
|
1金钱
本帖最后由 ChanTselin5213 于 2016-3-8 19:55 编辑
[mw_shl_code=c,true]/******************************************************************************
* @ File name --> ds1302.c
* @ Author --> By@ Sam Chan
* @ Version --> V1.0
* @ Date --> 08 - 23 - 2012
* @ Brief --> 时钟芯片DS1302驱动
*
* @ Copyright (C) 20**
* @ All rights reserved
*******************************************************************************
*
* File Update
* @ Version --> V1.0.1
* @ Author --> By@ Sam Chan
* @ Date --> 10 - 20 - 2013
* @ Revise --> A、增加对STM32控制的移植支持
* @ --> B、增加对内置的RAM操作相关函数
* @ --> C、增加检测DS1302是否存在,是否第一次上电检测函数
* @ --> D、增加对DS1302内置的锂电池充电寄存器参数设置函数和结构体
*
******************************************************************************/
#include "ds1302.h"
/******************************************************************************
定义变量
******************************************************************************/
#define Date TimeValue.date
#define Min TimeValue.minute
#define Sec TimeValue.second
#define Hour TimeValue.hour
#define Week TimeValue.week
#define Month TimeValue.month
#define Year TimeValue.year
Time_Typedef TimeValue; //定义时间数据指针
void Time_Init()
{
TimeValue.date=24;
TimeValue.hour=6;
TimeValue.minute=12;
TimeValue.month=5;
TimeValue.second=0;
TimeValue.week=2;
TimeValue.year=16;
}
Charge_Typedef ChargeValue; //定义充电寄存器
/******************************************************************************
* Function Name --> GPIO初始化
* Description --> none
* Input --> none
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //开启GPIOC外设时钟
/* 初始化GPIOC */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/******************************************************************************
* Function Name --> DS1302写入一个字节数据
* Description --> none
* Input --> dat:要写入的数据
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_Write_Byte(u8 dat)
{
u8 i;
DS1302_SDA_OUT(); //设置为输出口
for(i=0;i<8;i++)
{
DS1302_SCL = 0; //时钟线拉低
if(dat & 0x01) DS1302_SDA = 1; //数据线放上数据,先发低位
else DS1302_SDA = 0;
dat >>= 1; //数据右移一位
DS1302_SCL = 1; //发送数据,上升沿有效
}
}
/******************************************************************************
* Function Name --> DS1302读出一个字节数据
* Description --> none
* Input --> none
* Output --> none
* Reaturn --> 读到的数据
******************************************************************************/
unsigned DS1302_Read_Byte()
{
u8 ReData=0x00;
u8 i;
DS1302_SDA_IN(); //设置为输入口
for(i=0;i<8;i++)
{
if(DS1302_IN_SDA == 1)
{ ReData |= 0x80; } //读出一位数据是“1”
DS1302_SCL = 0; //时钟线拉低
ReData >>= 1; //数据右移一位,先读取低位,数据补“0”
DS1302_SCL = 1; //上升沿读取数据
}
return(ReData); //返回读取到的数据
}
/******************************************************************************
* Function Name --> 向DS1302某地址写入数据
* Description --> none
* Input --> add:要操作的地址
* dat:要写入的数据
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_Write_Data(u8 add,u8 dat)
{
DS1302_RST = 0; //复位脚拉低
DS1302_SCL = 0; //时钟线拉低
DS1302_RST = 1; //复位脚拉高
DS1302_Write_Byte(add); //写入要操作地址
DS1302_Write_Byte(dat); //写入数据
//delay_us(5);
DS1302_RST = 0;
DS1302_SCL = 0;
}
/******************************************************************************
* Function Name --> 从DS1302某地址读取数据
* Description --> none
* Input --> add:要操作的地址
* Output --> none
* Reaturn --> 要读取的寄存器的数值
******************************************************************************/
unsigned DS1302_Read_Data(u8 add)
{
u8 Temp;
DS1302_RST = 1;
DS1302_Write_Byte(add); //写入要操作地址
Temp = DS1302_Read_Byte(); //开始读取数据
DS1302_RST = 0;
return(Temp); //返回读取到的数据
}
/******************************************************************************
* Function Name --> 主电源对备用电池充电设置
* Description --> 如果备用电池接的是可充电的锂电池或者其他可充电电池的时候,
* 可以打开DS1302的充电电路,利用主供电对电池进行充电,免的换电池的麻烦
* Input --> *CHG_dat:寄存器控制指针
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_Charge_Manage(Charge_Typedef* CHG_dat)
{
u8 CHG_Value;
CHG_Value = (CHG_dat->TCSx << 4) | (CHG_dat->DSx << 2) | CHG_dat->RSx;
DS1302_WP_Disable(); //取消写保护
DS1302_Write_Data(Trickle_Charger_Address,CHG_Value);
DS1302_WP_Enable(); //打开写保护
}
/******************************************************************************
* Function Name --> DS1302内置的RAM读写操作
* Description --> none
* Input --> *pBuff:读写数据存放区
* WRadd:读写起始地址,范围在RAM_Address0 ~ RAM_Address28之间,最后一位地址有其他用途
* num:读写字节数据的数量,范围在1 ~ 28之间
* RW:读写判断位。0x00为写操作,0x01为读操作
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_RAM_WriteRead_Data(u8* pBuff,u8 WRadd,u8 num,u8 RW)
{
u8 i;
if(WRadd == RAM_Address29) return; //要写入数据的RAM地址是最后一个,直接退出
//因为最后一个字节是用来检测DS1302的
if(RW == 0x00) //写数据操作
{
for(i = 0;i < num;i++)
{
DS1302_WP_Disable(); //取消写保护
DS1302_Write_Data(WRadd+(i<<1),pBuff);
DS1302_WP_Enable(); //打开写保护
}
}
else
{
for(i = 0;i < num;i++)
{
DS1302_WP_Disable(); //取消写保护
pBuff = DS1302_Read_Data(WRadd+1+(i<<1));
DS1302_WP_Enable(); //打开写保护
}
}
}
/******************************************************************************
* Function Name --> 测试设备好坏
* Description --> 在DS1302芯片的RAM的最后一个地址写入一个数据并读出来判断
* 与上次写入的值相等,不是第一次上电,否则则初始化时间
* Input --> none
* Output --> none
* Reaturn --> 0:设备正常并不是第一次上电
* 1:设备错误或者已损坏
******************************************************************************/
u8 DS1302_Check(void)
{
u8 test_value;
DS1302_WP_Disable(); //取消写保护
test_value = DS1302_Read_Data(RAM_Address29 + 1); //读出最后一个RAM地址里的数据
DS1302_WP_Enable(); //打开写保护
if(test_value == test_data) //判断数据是否对
{
return 0; //设备正常,不是第一次上电
}
else
{
return 1; //不是第一次上电或者设备异常
// DS1302_WP_Disable(); //取消写保护
// DS1302_Write_Data(RAM_Address29,0x55); //向RAM最后一个地址里写入数据
// DS1302_WP_Enable(); //打开写保护
//
// _nop_();_nop_();
//
// DS1302_WP_Disable(); //取消写保护
// test_value = DS1302_Read_Data(RAM_Address29 + 1); //读出最后一个RAM地址里的数据
// DS1302_WP_Enable(); //打开写保护
//
// if(test_value == test_data) return 0; //设备正常,不是第一次上电
}
// return 1; //设备不在线或者已损坏
}
/******************************************************************************
* Function Name --> DS1302初始化
* Description --> none
* Input --> *Time: 时间结构体指针
* Output --> none
* Reaturn --> none
******************************************************************************/
void DS1302_Init(Time_Typedef* Time)
{
DS1302_RST = 0;
DS1302_SCL = 0;
DS1302_WP_Disable(); //取消写保护
DS1302_Write_Data(Address_year,(((Time->year)/10)<<4|(Time->year)%10)); //写年数据
delay_us(3);
DS1302_Write_Data(Address_week,(((Time->week)/10)<<4|(Time->week)%10)); //写星期数据
delay_us(3);
DS1302_Write_Data(Address_month,(((Time->month)/10)<<4|(Time->month)%10));//写月数据
delay_us(3);
DS1302_Write_Data(Address_date,(((Time->date)/10)<<4|(Time->date)%10)); //写日数据
delay_us(3);
DS1302_Write_Data(Address_hour,(((Time->hour)/10)<<4|(Time->hour)%10)); //写小时数据
delay_us(3);
DS1302_Write_Data(Address_minute,(((Time->minute)/10)<<4|(Time->minute)%10)); //写分钟数据
delay_us(3);
DS1302_Write_Data(Address_second ,(((Time->second)/10)<<4|(Time->second)%10)); //写秒数据并使时钟运行
delay_us(3);
DS1302_WP_Enable(); //打开写保护
DS1302_WP_Disable(); //取消写保护
DS1302_Write_Data(RAM_Address29,test_data); //向RAM最后一个地址里写入数据
DS1302_WP_Enable(); //打开写保护
}
[mw_shl_code=c,true]#include "led.h"
#include "delay.h"
#include "sys.h"
#include "ds1302.h"
#include "usart.h"
#define Date TimeValue.date
#define Min TimeValue.minute
#define Sec TimeValue.second
#define Hour TimeValue.hour
#define Week TimeValue.week
#define Month TimeValue.month
#define Year TimeValue.year
int main()
{
Time_Typedef TimeValue;
delay_init();
LED_Init();
uart_init(115200);
DS1302_GPIOInit();
DS1302_Init(&TimeValue);
while(1)
{
Sec=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Min=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Hour=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Date=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Month=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Week=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Year=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
printf("%d年%d月%d日%d:%d:%d 星期%d\r\n",Year,Month,Date,Hour,Min,Sec,Week);
delay_ms(300);
}
}
[/mw_shl_code]
[mw_shl_code=c,true]/******************************************************************************
* @ File name --> ds1302.h
* @ Author --> By@ Sam Chan
* @ Version --> V1.0
* @ Date --> 08 - 23 - 2012
* @ Brief --> 时钟芯片DS1302驱动
*
* @ Copyright (C) 20**
* @ All rights reserved
*******************************************************************************
*
* File Update
* @ Version --> V1.0.1
* @ Author --> By@ Sam Chan
* @ Date --> 10 - 20 - 2013
* @ Revise --> A、增加对STM32控制的移植支持
* @ --> B、增加对内置的RAM操作相关函数
* @ --> C、增加检测DS1302是否存在,是否第一次上电检测函数
* @ --> D、增加对DS1302内置的锂电池充电寄存器参数设置函数和结构体
*
******************************************************************************/
#ifndef _ds1302_h_
#define _ds1302_h_
/******************************************************************************
外部函数头文件
******************************************************************************/
#include "sys.h"
#include "delay.h"
/******************************************************************************
定义接口
所接的IO不一样请修改这里
设置IO的方向请修改这里,对于不是具有准双向IO的MCU
******************************************************************************/
#define DS1302_SDA_IN() {GPIOC->CRL &= 0xfffff0ff;GPIOC->CRL |= 8<<8;}
#define DS1302_SDA_OUT() {GPIOC->CRL &= 0xfffff0ff;GPIOC->CRL |= 0xa<<8;}
#define DS1302_RST PCout(0) //RST
#define DS1302_SCL PCout(1) //SCL
#define DS1302_SDA PCout(2) //SDA
#define DS1302_IN_SDA PCin(2) //读取SDA上数据用到
/******************************************************************************
定义时间结构
******************************************************************************/
typedef struct
{
u8 year; //年
u8 month; //月
u8 date; //日
u8 week; //星期
u8 hour; //小时
u8 minute; //分钟
u8 second; //秒钟
}Time_Typedef;
extern Time_Typedef TimeValue; //定义时间数据缓存
#define test_data 0x55 //此数据用来检测DS1302是否存在于总线上用,可以改用其他值
/******************************************************************************
定义相关命令宏
******************************************************************************/
#define Clock_Address_Bass 0x80 //基地址
#define Address_year (Clock_Address_Bass | 0x0c) //年
#define Address_month (Clock_Address_Bass | 0x08) //月
#define Address_date (Clock_Address_Bass | 0x06) //日
#define Address_week (Clock_Address_Bass | 0x0a) //星期
#define Address_hour (Clock_Address_Bass | 0x04) //小时
#define Address_minute (Clock_Address_Bass | 0x02) //分钟
#define Address_second (Clock_Address_Bass | 0x00) //秒
#define Clock_Burst (Clock_Address_Bass | 0x3e) //时钟软复位
//写保护寄存器
#define Address_WP (Clock_Address_Bass | 0x0e) //写保护
#define WP_Enable 0x80 //打开写保护
#define WP_Disable 0x00 //关闭写保护
/******************************************************************************
电源管理寄存器位描述
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
TCS3 TCS2 TCS1 TCS0 DS1 DS0 RS1 RS0
TCSx:充电电流大小选择,值为0xa0时打开充电,其他值时关闭,DS1302默认是关闭的
DSx:设置VCC1和VCC2之间的二极管串联数量,0x01时为串联一只二极管,0x10时为串联两只二极管,0x00或0x11时关闭充电功能
RSx:设置限流电阻大小,0x00为开路并关闭充电功能,0x01为2K,0x10为4K,0x11为8K
******************************************************************************/
//充电管理寄存器结构
typedef struct
{
u8 TCSx; //充电开关
u8 DSx; //串联二极管
u8 RSx; //限流电阻
}Charge_Typedef;
extern Charge_Typedef ChargeValue; //定义充电寄存器
//电源管理
#define Trickle_Charger_Address (Clock_Address_Bass | 0x10) //管理电源,主电源供电时可以设置给备用电池充电
#define Open_Trickle_Charge 0x0a
#define Close_Trickle_Charge 0x00 //设置为其他值也可以
#define One_Diode 0x01
#define Two_Diode 0x10
#define None_Diode 0x00 //or 0x11,断开串联并关闭充电功能
#define Resistor_For2K 0x01
#define Resistor_For4K 0x10
#define Resistor_For8K 0x11
#define None_Resistor 0x00 //断开串联限流电阻并关闭充电功能
//RAM地址
#define RAM_Address_Bass 0xc0 //基地址
#define RAM_Address0 (RAM_Address_Bass | 0x00) //RAM地址 = 基地址 + 地址偏移量
#define RAM_Address1 (RAM_Address_Bass | 0x02)
#define RAM_Address2 (RAM_Address_Bass | 0x04)
#define RAM_Address3 (RAM_Address_Bass | 0x06)
#define RAM_Address4 (RAM_Address_Bass | 0x08)
#define RAM_Address5 (RAM_Address_Bass | 0x0a)
#define RAM_Address6 (RAM_Address_Bass | 0x0c)
#define RAM_Address7 (RAM_Address_Bass | 0x0e)
#define RAM_Address8 (RAM_Address_Bass | 0x10)
#define RAM_Address9 (RAM_Address_Bass | 0x12)
#define RAM_Address10 (RAM_Address_Bass | 0x14)
#define RAM_Address11 (RAM_Address_Bass | 0x16)
#define RAM_Address12 (RAM_Address_Bass | 0x18)
#define RAM_Address13 (RAM_Address_Bass | 0x1a)
#define RAM_Address14 (RAM_Address_Bass | 0x1c)
#define RAM_Address15 (RAM_Address_Bass | 0x1e)
#define RAM_Address16 (RAM_Address_Bass | 0x20)
#define RAM_Address17 (RAM_Address_Bass | 0x22)
#define RAM_Address18 (RAM_Address_Bass | 0x24)
#define RAM_Address19 (RAM_Address_Bass | 0x26)
#define RAM_Address20 (RAM_Address_Bass | 0x28)
#define RAM_Address21 (RAM_Address_Bass | 0x2a)
#define RAM_Address22 (RAM_Address_Bass | 0x2c)
#define RAM_Address23 (RAM_Address_Bass | 0x2e)
#define RAM_Address24 (RAM_Address_Bass | 0x32)
#define RAM_Address25 (RAM_Address_Bass | 0x34)
#define RAM_Address26 (RAM_Address_Bass | 0x36)
#define RAM_Address27 (RAM_Address_Bass | 0x38)
#define RAM_Address28 (RAM_Address_Bass | 0x3a)
#define RAM_Address29 (RAM_Address_Bass | 0x3c)
#define RAM_BURST (RAM_Address_Bass | 0x3e)
//写秒为00并启动时钟
#define DS1302_Start_Second() (DS1302_Write_Data(Address_second,0x00))
//写保护命令
#define DS1302_WP_Enable() (DS1302_Write_Data(Address_WP,WP_Enable)) //打开写保护
#define DS1302_WP_Disable() (DS1302_Write_Data(Address_WP,WP_Disable)) //关闭写保护
//关闭充电功能,可以直接调用
#define DS1302_Disable_Charge() (DS1302_Write_Data(Trickle_Charger_Address,0x00))
/******************************************************************************
外部功能函数
******************************************************************************/
void DS1302_GPIOInit(void); //GPIO初始化
void DS1302_Init(Time_Typedef *Time); //DS1302初始化
extern unsigned DS1302_Read_Data(u8 add); //从DS1302某地址读取数据
extern void DS1302_Write_Data(u8 add,u8 dat); //向DS1302某地址写入数据
extern u8 DS1302_Check(void); //测试设备好坏
extern void DS1302_Charge_Manage(Charge_Typedef *CHG_dat); //主电源对备用电池充电设置
extern void DS1302_RAM_WriteRead_Data(u8* pBuff,u8 WRadd,u8 num,u8 RW); //DS1302内置的RAM读写操作
#endif /* end ds1302.h */
[/mw_shl_code][mw_shl_code=c,true]#include "led.h"
#include "delay.h"
#include "sys.h"
#include "ds1302.h"
#include "usart.h"
#define Date TimeValue.date
#define Min TimeValue.minute
#define Sec TimeValue.second
#define Hour TimeValue.hour
#define Week TimeValue.week
#define Month TimeValue.month
#define Year TimeValue.year
int main()
{
Time_Typedef TimeValue;
delay_init();
LED_Init();
uart_init(115200);
DS1302_GPIOInit();
DS1302_Init(&TimeValue);
while(1)
{
Sec=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Min=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Hour=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Date=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Month=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Week=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
Year=(DS1302_Read_Data(Address_second|0x01)&0x0f+(DS1302_Read_Data(Address_second|0x01)>>4)*10);
delay_us(3);
printf("%d年%d月%d日%d:%d:%d 星期%d\r\n",Year,Month,Date,Hour,Min,Sec,Week);
delay_ms(300);
}
}
[/mw_shl_code]
一直拒绝做伸手党 可是实在是没办法了 一直没找到问题到底在哪里出错了 上拉了电阻还是不行
我用了八度空间提供的模板 然后修改了一下ds1302.c的参数 写上main函数 结果实验失败了 求指教自上而下为ds1302.c ds1302.h main
|
-
这是串口调试助手的
|