📄 ds1302a.c
字号:
#include <avr/io.h>
#include <util/delay.h>
#define uchar unsigned char
#define uint unsigned int
#define T_CLK 7
#define T_IO 6
#define T_RST 5
/******************************************************************** */
#define SETBIT(x,y) (x|=(1<<y)) //set bit y in byte x
#define CLRBIT(x,y) (x&=(~(1<<y))) //clear bit y in byte x
#define CHKBIT(x,y) (x&(1<<y)) //check bit y in byte x
/******************************************************************** */
void ds1302_write(unsigned char , unsigned char);
uchar year=0;
uchar month=0;
uchar day=0;
uchar week=0;
uchar hour=0;
uchar minute=0;
uchar second=0;
unsigned char disp_table[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
/*
0x3f,
0x06,
0x5b,
0x4f,
0x66,
0x6d,
0x7d,
0x07,
0x7f,
0x6f,
0x77,
0x7c,
0x39,
0x5e,
0x79,
0x71};
*/
void nop(void)
{
char i;
for (i=0;i<1;i++)
;
}
void initialize_1302(void)
{
ds1302_write(0x8e,0x00);
ds1302_write(0x90,0xA5);
ds1302_write(0x80,0x00);
}
/********************************************************************
* 名称: ds1302_write_a_byte
* 说明:
* 功能: 往DS1302写入1Byte数据
* 调用:
* 输入: ucDa 写入的数据
* 返回值: 无
***********************************************************************/
void ds1302_write_a_byte(unsigned char ucDa)
{
unsigned char i;
for(i=8; i>0; i--)
{
CLRBIT(PORTD,T_CLK);
if (ucDa&1) SETBIT(PORTD,T_IO);
else CLRBIT(PORTD,T_IO);
SETBIT(PORTD,T_CLK);
ucDa>>=1;
}
}
/********************************************************************
*
* 名称: unsigned char ds1302_read_a_byte
* 说明:
* 功能: 从DS1302读取1Byte数据
* 调用:
* 输入:
* 返回值: t
***********************************************************************/
unsigned char ds1302_read_a_byte(void)
{
unsigned char i,t;
CLRBIT(DDRD,T_IO);
CLRBIT(PORTD,T_IO);
for(i=8; i>0; i--)
{
t>>=1;
SETBIT(PORTD,T_CLK);
nop();
CLRBIT(PORTD,T_CLK);
nop();
if(CHKBIT(PIND,T_IO)) t|=0x80;
else t&= 0x7f;
}
SETBIT(DDRD,T_IO);
return(t);
}
/********************************************************************
* 名称: write_1302
* 说明: 先写地址,后写命令/数据
* 功能: 往DS1302写入数据
* 调用: ds1302_write_a_byte()
* 输入: ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值: 无
***********************************************************************/
void ds1302_write(unsigned char ucAddr, unsigned char ucDa)
{
//DDRC=0xff;
CLRBIT(PORTD,T_RST); //T_RST=0
//;;nop();
CLRBIT(PORTD,T_CLK); //T_CLK=0;
//;;
SETBIT(PORTD,T_RST); //T_RST=1
nop();
ds1302_write_a_byte(ucAddr); /* 地址,命令 */
CLRBIT(PORTD,T_CLK);
ds1302_write_a_byte(ucDa); /* 写1Byte数据*/
SETBIT(PORTD,T_CLK); //T_CLK=1
//;;nop();
CLRBIT(PORTD,T_RST); //T_RST=0
}
/********************************************************************
* 名称: read_1302
* 说明: 先写地址,后读命令/数据
* 功能: 读取DS1302某地址的数据
* 调用: ds1302_write_a_byte() , ds1302_read_a_byte()
* 输入: ucAddr: DS1302地址
* 返回值: ucDa :读取的数据
***********************************************************************/
unsigned char ds1302_read(unsigned char ucAddr)
{
unsigned char ucDa;
CLRBIT(PORTD,T_RST);
//;;nop();
CLRBIT(PORTD,T_CLK);
//;;nop();
SETBIT(PORTD,T_RST);
ds1302_write_a_byte(ucAddr|0x01); /* 地址,命令 */
ucDa = ds1302_read_a_byte(); /* 读1Byte数据 */
SETBIT(PORTD,T_CLK);
//;;nop();
CLRBIT(PORTD,T_RST);
//;;nop();
return(ucDa);
}
/********************************************************************
* 名称: v_BurstW1302T
* 说明: 先写地址,后写数据(时钟多字节方式)
* 功能: 往DS1302写入时钟数据(多字节方式)
* 调用: ds1302_write_a_byte()
* 输入: pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
* 8Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 1B
* 返回值: 无
***********************************************************************/
void v_BurstW1302T(unsigned char *pSecDa)
{
unsigned char i;
ds1302_write(0x8e,0x00); // 控制命令,WP=0,写操作?
CLRBIT(PORTD,T_RST);
CLRBIT(PORTD,T_CLK);
SETBIT(PORTD,T_RST);
ds1302_write_a_byte(0xbe); //0xbe:时钟多字节写命令
for (i=8;i>0;i--) //8Byte = 7Byte 时钟数据 + 1Byte 控制
{
ds1302_write_a_byte(*pSecDa);//写1Byte数据
pSecDa++;
}
SETBIT(PORTD,T_CLK);
CLRBIT(PORTD,T_RST);
}
/********************************************************************
* 名称: v_BurstR1302T
* 说明: 先写地址,后读命令/数据(时钟多字节方式)
* 功能: 读取DS1302时钟数据
* 调用: ds1302_write_a_byte() , ds1302_read_a_byte()
* 输入: pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值: ucDa :读取的数据
***********************************************************************/
void v_BurstR1302T(unsigned char *pSecDa)
{
unsigned char i;
//DDRC=0xff;
CLRBIT(PORTD,T_RST);
CLRBIT(PORTD,T_CLK);
SETBIT(PORTD,T_RST);
ds1302_write_a_byte(0xbf); // 0xbf:时钟多字节读命令
for (i=8; i>0; i--)
{
*pSecDa = ds1302_read_a_byte(); // 读1Byte数据
pSecDa++;
}
//DDRC=0xff;
SETBIT(PORTD,T_CLK);
CLRBIT(PORTD,T_RST);
}
/********************************************************************
* 名称: v_BurstW1302R
* 说明: 先写地址,后写数据(寄存器多字节方式)
* 功能: 往DS1302寄存器数写入数据(多字节方式)
* 调用: ds1302_write_a_byte()
* 输入: pReDa: 寄存器数据地址
* 返回值: 无
***********************************************************************/
void v_BurstW1302R(unsigned char *pReDa)
{
unsigned char i;
ds1302_write(0x8e,0x00); // 控制命令,WP=0,写操作?
CLRBIT(PORTD,T_RST);
CLRBIT(PORTD,T_CLK);
SETBIT(PORTD,T_RST);
ds1302_write_a_byte(0xfe); //0xfe:寄存器多字节写命令
for (i=31;i>0;i--) //31Byte 寄存器数据
{
ds1302_write_a_byte(*pReDa); //写1Byte数据
pReDa++;
}
SETBIT(PORTD,T_CLK);
CLRBIT(PORTD,T_RST);
}
/********************************************************************
* 名称: v_BurstR1302R
* 说明: 先写地址,后读命令/数据(寄存器多字节方式)
* 功能: 读取DS1302寄存器数据
* 调用: ds1302_write_a_byte() , ds1302_read_a_byte()
* 输入: pReDa: 寄存器数据地址
* 返回值: 无
***********************************************************************/
void v_BurstR1302R(unsigned char *pReDa)
{
unsigned char i;
//DDRC=0xff;
CLRBIT(PORTD,T_RST);
CLRBIT(PORTD,T_CLK);
SETBIT(PORTD,T_RST);
ds1302_write_a_byte(0xff); // 0xff:寄存器多字节读命令
for (i=31; i>0; i--) //31Byte 寄存器数据
{
*pReDa = ds1302_read_a_byte(); //读1Byte数据
pReDa++;
}
//DDRC=0xff;
SETBIT(PORTD,T_CLK);
CLRBIT(PORTD,T_RST);
}
uchar check_ds1302(void)
{
ds1302_write(0x8e,0x80);
if(ds1302_read(0x8e)==0x80) return 1;
return 0;
}
void ds1302_read_time(void)
{ uchar a,b,c,d;int i;
year=ds1302_read(0x8c); //年
month=ds1302_read(0x88);//月
day=ds1302_read(0x86); //日
week=ds1302_read(0x8a); //周
hour=ds1302_read(0x84); //时
minute=ds1302_read(0x82); //分
second=ds1302_read(0x80); //秒
// 第一排LED全灭
// 第二排LED全亮
//write728x(0x02,0xa4);
//write728x(0x03,0xb0);
//PORTB=0xff;
a=(second & 0x0f);
//send_byte(disp_table[a]);
write728x(0x00,disp_table[a]);
//PORTB=0xfe;
for(i=0;i<100;i++) //拉低 500us
{
_delay_us(50);
}
//PORTB=0xff;
b=(second >> 4);
write728x(0x01,disp_table[b]);
// send_byte(disp_table[b]);
//PORTB=0xfd;
for(i=0;i<100;i++) //拉低 500us
{
_delay_us(50);
}
//PORTB=0xff;
b=(minute & 0x0f);
write728x(0x01,disp_table[b]);
//send_byte(disp_table[b]);
//PORTB=0xfb;
for(i=0;i<100;i++) //拉低 500us
{
_delay_us(50);
}
// PORTB=0xff;
b=(minute >> 4);
write728x(0x01,disp_table[b]);
// send_byte(disp_table[b]);
// PORTB=0xf7;
for(i=0;i<100;i++) //拉低 500us
{
_delay_us(50);
}
//PORTC|=(1<<4);
}
void ds1302_write_time(void)
{
ds1302_write(0x8e,0x00); //关闭写保护
ds1302_write(0x80,0x80); //暂停
ds1302_write(0x90,0xa9); //涓流充电
ds1302_write(0x8c,0x08); //年
ds1302_write(0x88,0x05); //月
ds1302_write(0x86,0x03); //日
ds1302_write(0x8a,0x06); //周
ds1302_write(0x84,0x10); //时
ds1302_write(0x82,0x40); //分
ds1302_write(0x80,0x25); //秒
ds1302_write(0x8e,0x80); //打开写保护
}
// ***********************************************************
// * 写入BC728X, 第一个参数为目标寄存器地址, 第二个参数为要写入的数据 *
// ***********************************************************
void write728x(unsigned char reg_add, unsigned char write_data)
{
send_byte(reg_add); // 发送寄存器地址
send_byte(write_data); // 发送数据字节
}
// ***********************************************************
// * 向 BC728X 发送一个字节 *
// ***********************************************************
void send_byte(unsigned char send_byte)
{
unsigned char bit_counter;
PORTB&=~(1<<PB0); // 产生一 clk 脉冲
// delay_1us();
PORTB|=(1<<PB0);
// delay_1us();
while (PINB&(1<<PB2)); // 等待 BC728X 输出 dat 低电平响应
//delay_us(3);
PORTB&=~(1<<PB0); // 再次输出一 clk 脉冲
//delay_1us();
PORTB|=(1<<PB0);
//delay_1us();
while (!(PINB&(1<<PB2))); // 等待 BC728X 进入接收状态
// delay_us(2);
for (bit_counter=0;bit_counter<8;bit_counter++)
{ // 发送 8 个比特
if ((send_byte&0x80)==0)
{
DDRB=0x05;
// 设置I/O口B.7和B.5为输出,其余为输入
PORTB&=~(1<<PB2);
// 如果待发bit为0, 置 dat 为 0
// delay_1us();
}
else
{
PORTB|=(1<<PB2); // 反之置为 1
}
//delay_1us();
send_byte=send_byte*2; // send_byte 左移一位
// delay_us(1);
PORTB&=~(1<<PB0); // 输出一 clk 脉冲
// delay_1us();
PORTB|=(1<<PB0);
_delay_us(3); // 短暂延时
}
DDRB=0x01;
_delay_us(5); // 恢复I/O口B5为输出B.7为输入
}
/*
void send_byte(uchar x) //以下为显示程序
{
uchar i;
for(i=0;i<8;i++)
{
PORTC&=~(1<<5); // PC5为底 为164提供时钟信号
if(x&(1<<(7-i)))//判断每位数据的电平,及小数点判断
PORTC|=(1<<4); //若为高着PC4输出高电平
else
PORTC&=~(1<<4); //若为低着输出低电平
PORTC|=(1<<5); //PC5 提供时钟信号
}
//PORTC|=((1<<0)|(1<<1)|(1<<2));
}
*/
void main()
{
DDRB=0x01; // 设置I/O口B.5为输出
PORTB=0x00;
//PORTC = 0xff; //m103 output only
//DDRC = 0xFF;
PORTD = 0xFF;
DDRD = 0xff;
initialize_1302();
check_ds1302() ;
ds1302_write_time();
_delay_us(100); // 等待 BC728x 完成复位
write728x(0x12,0x84); // 初始化BC728x为164模式,KMS=1
while(1)
{
ds1302_read_time();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -