📄 ds1302.c
字号:
#include <avr/io.h>
#include <avr/delay.h>
#include "DS1302.h"
#include "spi.h"
//读写操作位
#define CMD_READ 0x01
#define CMD_WRITE 0x00
//时钟 命令
#define CMD_SECOND 0x80 //秒
#define CMD_MINUTE 0x82 //分
#define CMD_HOUR 0x84 //时
#define CMD_DAY 0x86 //日
#define CMD_MONTH 0x88 //月
#define CMD_WEEK 0x8A //星期 DATE
#define CMD_YEAR 0x8C //年
#define CMD_CONTROL 0x8E //控制(写保护)
#define CMD_TRICKLE_CHARGE 0x90 //涓流充电
#define CMD_CLOCK_BURST 0xBE //连续读取
//时钟配置常量
#define CFG_CLOCK_HALT 0x80 //停止时钟控制位 SECOND bit7
#define CFG_12_24 0x80 //12/24小时值选择位 HOUR bit7
#define CFG_AM_PM 0x20 //AP/PM位 HOUR bit5
#define CFG_PROTECT 0x80 //写保护控制位 CONTROL bit7
#define CFG_UNPROTECT 0x00 //写保护控制位 CONTROL bit7
//涓流充电控制常量
#define CFG_TC_D1R2 0xA5 //high 1 Diode +2K Resistors
#define CFG_TC_D2R8 0xAB //low 2 Diodes+8K Resistors
#define CFG_TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)
//RAM 命令
#define CMD_RAM_BASE 0xC0 //RAM0~RAM30<<1 地址需左移一位
#define CMD_RAM_BURST 0xFE //连续读取
//M16管脚定义
#define DS1302_CE 1 //PA1 必须设为输出 ----DS1302 pin5
//宏定义
#define EnDS1302 PORTA|= (1<<DS1302_CE) // 置CE为高电平,使能SPI接口
#define DiDS1302 PORTA&=~(1<<DS1302_CE) // 置CE为低电平,关闭SPI接口
unsigned char sWEEK[]="Wr 1 2 3 4 5 6Su";
unsigned char CURDATE[7];
/*-----------------------------------------------------------------------
Single_SPI : 使用SPI接口读写数据到DS1302
输入参数: command: 命令选择;
wdata: 写入的数据;
返回值 rdata: 读回的数据;
(SPI的收发是同时进行的)
-----------------------------------------------------------------------*/
unsigned char Single_SPI(unsigned char command,unsigned char wdata)
{
unsigned char rdata;
EnDS1302; // 使能LCD
_delay_us(10);
spi_rw(command); // 传送命令到SPI寄存器
_delay_us(10); rdata = spi_rw(wdata); // 传送数据到SPI寄存器 DiDS1302; // 关断LCD SPI通讯
_delay_us(10);
return rdata;
}
/*-----------------------------------------------------------------------
Burst_SPI : 使用SPI接口读写一批数据到DS1302
输入参数: CMD: 选择Clock/RAM,选择读写
lenth: 数据长度
pwdata: 写入数据的缓冲区;
prdata: 读回数据的缓冲区;
(SPI的收发是同时进行的)
读CLOCK的数据从SECOND寄存器开始,到CONTROL寄存器,最大8字节
写CLOCK的数据必须一次写完8个字节
读写RAM的数据从 RAM0地址开始,到RAM30地址,最大31字节
-----------------------------------------------------------------------*/
void Burst_SPI(unsigned char CMD,unsigned char len,
unsigned char *pwdata,unsigned char *prdata)
{
EnDS1302; // 使能SPI通讯
_delay_us(10); spi_rw(CMD); // 传送命令到SPI寄存器
_delay_us(10);
while (len--)
{ *prdata++=spi_rw(*pwdata++); // 传送数据到SPI寄存器
};
DiDS1302; // 关断SPI通讯
_delay_us(10);}
//检测DS1302
unsigned char check_RTC(void)
{
unsigned char i;
Single_SPI(CMD_CONTROL|CMD_WRITE,CFG_UNPROTECT);//写允许
Single_SPI(CMD_RAM_BASE|CMD_WRITE,0xA5); //写RAM0
Single_SPI(CMD_CONTROL|CMD_WRITE,CFG_PROTECT); //写保护
i=Single_SPI(CMD_RAM_BASE|CMD_READ,0); //读取RAM0
if(i==0xA5) return 1;
else return 0;
}
//初始化DS1302
void init_RTC(char *init_data)
{
unsigned char temp[8];
DiDS1302;
DDRA|= (1<<DS1302_CE);
Single_SPI(CMD_CONTROL|CMD_WRITE,CFG_UNPROTECT); //写允许
Burst_SPI(CMD_CLOCK_BURST|CMD_WRITE,8,init_data,&temp[0]); //初始化时间
Single_SPI(CMD_TRICKLE_CHARGE,CFG_TC_D1R2); //涓流充电选择
Single_SPI(CMD_CONTROL|CMD_WRITE,CFG_PROTECT); //写保护
}
//压缩BCD码转换成ASCII码
void BCDtoASCII(unsigned char cBCD,unsigned char *pstr)
{
unsigned char i,j;
i=cBCD>>4;
j=cBCD&0x0F;
*pstr++=i+0x30;
*pstr=j+0x30;
}
//BCD码0~7转换成汉字'一'~'日'
void decodeWEEK(unsigned char WEEK,unsigned char *pstr)
{
unsigned char i;
i=WEEK;
i&=0x07;
i=i<<1;
*pstr++=sWEEK[i++];
*pstr=sWEEK[i];
}
//读取当前时间并解释
void read_date(char *s_cur_date)
{
Burst_SPI(CMD_CLOCK_BURST|CMD_READ,7,0,CURDATE); //读取当前时间
BCDtoASCII(CURDATE[6],s_cur_date + 2); //年 ,00~10
BCDtoASCII(CURDATE[4],s_cur_date + 6); //月 ,01~12
BCDtoASCII(CURDATE[3],s_cur_date + 10); //日 ,01~31(28/30/31)
BCDtoASCII(CURDATE[2],s_cur_date + 14); //时 ,00~23
BCDtoASCII(CURDATE[1],s_cur_date + 18); //分 ,00~59
BCDtoASCII(CURDATE[0],s_cur_date + 22); //秒 ,00~59
decodeWEEK(CURDATE[5],s_cur_date + 31); //星期 ,1~7 一~日
}
/*-----------------------------------------------------------------------
delay_nms :长延时函数(GCC内部延时函数的延时过短)
输入参数: t :延时时间 ms
-----------------------------------------------------------------------*/
void delay_nms(unsigned int t)
{
while (t--)
_delay_ms(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -