⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1302a.c

📁 基于avr单片机上的ds1302实时时钟源程序
💻 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 + -