一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 11537|回复: 34

[其他综合] 想用DS3231做一个准一点VFD的时钟,求个DS3231的驱动

 火.. [复制链接]
发表于 2012-5-22 23:48 | 显示全部楼层 |阅读模式
用DS1302搞过不少,大都误差较大,因此想试一下DS3231,求各位达人帮忙啊
发表于 2012-5-23 09:09 | 显示全部楼层
DS3231的驱动很难弄啊~网上的例程很少,曾经我也想过弄一个,可惜最后放弃了
回复

使用道具 举报

发表于 2012-5-23 09:45 | 显示全部楼层
我的vfd安装贴中的代码包中就有,你可以移植一下
回复

使用道具 举报

发表于 2012-5-23 11:28 | 显示全部楼层
不要迷信DS3231,我测试的结果也很一般,建议用温补晶震试一下
回复

使用道具 举报

发表于 2012-5-23 11:52 | 显示全部楼层
3231市面上有大量假货,有翻新的,有国产改字的,精度有的很离谱。但如果是原装的,精度还是能保证的,基本是10天在1-2秒误差。
回复

使用道具 举报

发表于 2012-5-23 12:48 | 显示全部楼层
我就是直接申请美信样片的,也一般
回复

使用道具 举报

发表于 2012-5-23 13:22 | 显示全部楼层
本帖最后由 ayumi7 于 2012-5-23 13:25 编辑

我申请的 美信的样片  DS32C35  和DS3231 用法驱动一样的  走时很准的啊   我很早做了一个时钟  等下找找程序啊
A1.jpg A2.jpg

用了2年了  很准  基本不需要调时间
回复

使用道具 举报

发表于 2012-5-23 13:27 | 显示全部楼层
#include <at89x52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define OP_WRITE 0xD0   // DS32C35器件地址以及写入操作
#define OP_READ  0xD1   // DS32C35器件地址以及读取操作

uchar TAB[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf,0x8e,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uchar flag;
uchar Min,Max,Change_Num,Change,Set_Flag=0;
uchar *DS_Data;
float Tem;
/*--------------------------------------------------------------*/
//定义时间类型

unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
uchar Tem_H;
uchar Tem_L;

// 数码管驱动相关接口
sbit  SDATA_595 = P1^3 ;     // /串行数据输入14DS*/  
sbit  SCLK_595  = P1^2;      // /*移位时钟脉冲11SCH*/
sbit  RCK_595   = P1^1;     // /*输出锁存器控制脉冲12STCP*/
sbit  EN_595   = P1^0;     // /*使能*/


//* 定义设置时钟键
sbit Key_Set=P2^4;
sbit Key_Add=P2^5;
sbit Key_Dec=P2^6;
sbit Key_Ok=P2^7;

//* 定义设置时钟键
sbit INT   = P3^6;
sbit scl   = P3^5;
sbit sda   = P3^4;

delay(uint count)
{
        uint x,y;
        for(x=0;x<count;x++)
                for(y=0;y<12;y++);
}

//--------------------------------------------//
//              数据转换函数
//--------------------------------------------//

BCD_D(uchar num)
{
        uchar L;
L=(num/16)*10+(num%16);
        return L;
}

//十进制转BCD
D_BCD(uchar num)
{
        uchar L;
        L=(num/10)*16+(num%10);       
        return L;
}

//--------------------------------------------//
//                                        模拟IIC读写32C35驱动           //
//--------------------------------------------//
void delay1()
{ ; ;}

void start()  //开始信号
{       
        sda=1;
        delay1();
        scl=1;
        delay1();
        sda=0;
        delay1();
}

void stop()   //停止
{
        sda=0;
        delay1();
        scl=1;
        delay1();
        sda=1;
        delay1();
}

void ack()  //应答
{
        uchar i;
        scl=1;
        delay1();
        delay1();
        while((sda==1)&&(i<250))i++;
        scl=0;
        delay1();
}

//--------------------------------------------
//                                        写字节
//--------------------------------------------
void write_byte(uchar date)
{
        uchar i,temp;
        temp=date;
        for(i=0;i<8;i++)
        {
                temp=temp<<1;
                scl=0;
           delay1();
                sda=CY;
                delay1();
                scl=1;
                delay1();
        }
        scl=0;
        delay1();
        sda=1;
        delay1();
}

//--------------------------------------------
//                                        读字节
//--------------------------------------------
uchar read_byte()
{
        uchar i,k;
        scl=0;
        delay1();
        sda=1;
        delay1();
        for(i=0;i<8;i++)
        {
                scl=1;
                delay1();       
                k=(k<<1)|sda;
                scl=0;
                delay1();       
        }
        return k;
}

//--------------------------------------------
//                                        给DS32C35写数据
//--------------------------------------------

void write_add(uchar address,uchar date)
{
        start();
        write_byte(OP_WRITE);
        ack();
        write_byte(address);
        ack();
        write_byte(date);
        ack();
        stop();
}

//--------------------------------------------
//                                        读DS32C35的数据
//--------------------------------------------
uchar read_add(uchar address)
{
        uchar date;
        start();
        write_byte(OP_WRITE);
        ack();
        write_byte(address);
        ack();
        start();
        write_byte(OP_READ);
        ack();
        date=read_byte();
        stop();
        return date;
}
//--------------------------------------------//
//                                 写入DS32C35数据                      //
//--------------------------------------------//
write32c35()
{
        write_add(0x00,Second);   //设定秒钟初值   
        write_add(0x01,Minute);   //设定分钟初值   
        write_add(0x02,Hour);   //设定时钟初值   
        write_add(0x04,Day);   //设定日初值   
        write_add(0x05,Month);   //设定月初值   
        write_add(0x06,Year);   //设定年初值          
}



//--------------------------------------------//
//                                 读取DS32C35并且处理数据                      //
//--------------------------------------------//

void read32c35()
{
        Year         = read_add(0x06);
        Month    = read_add(0x05);
        Day     = read_add(0x04);
//        Week = read_add(0x03);

        Hour= read_add(0x02);
        Minute         = read_add(0x01);
        Second         = read_add(0x00);
}

//--------------------------------------------//
//                                        DS32C35读温度并处理数据               //
//--------------------------------------------//
void readtemp()
{
        uint Tem_suf;//缓冲数据变量
        write_add(0x0e,0x20); //采集温度
        Tem_H=read_add(0x11);//读取温度高位
        Tem_L=read_add(0x12);//读取温度低位
        if(!(Tem_H&0x80))//正温度
        {
        Tem_suf=Tem_H;//高位赋给Tem_suf
        Tem_suf<<=2;//Tem_suf右移两位
        Tem_suf|=(Tem_L>>6);//Tem_L右移6位并放于Tem_suf的低两位
                Tem=Tem_suf;
        Tem*=0.25;//温度实际值
        Tem+=0.5;//温度四舍五入
        Tem*=10;//温度放大10倍
                if(Tem>=100)
                {
                Tem_H=Tem/100;//温度十位
                        Tem_L=(uint)Tem/10%10;//温度个位
                }
                if(Tem<100)
                {
                Tem_H=(uint)Tem/10%10;//温度个位
                        Tem_H+=0x0c;//显示小数点的数字表位置
                        Tem_L=(uint)Tem%10;//温度十分位
                }
    }
    else//负温度
    {
        Tem_suf=(Tem_H&0x7f);//Tem_H高位标志位置0并赋给Tem_suf
        Tem_suf<<=2;//Tem_suf右移两位
        Tem_suf|=(Tem_L>>6);//Tem_L右移6位并放于Tem_suf的低两位
        Tem_suf=(~Tem_suf)+1;//取反加一,将补码转换为原码
                Tem=Tem_suf;
        Tem*=0.25;//温度实际值
        Tem+=0.5;//温度四舍五入
        Tem*=10;//温度放大10倍
        Tem_H=Tem/100;//温度十位
        Tem_L=(uint)Tem/10 %10;//温度各位
//        Tem_D=Tem%10;//温度十分位
        if(Tem_H)//温度超过零下9度时
        {
            Tem_H=0x00;//显示"O"符号 overflow溢出
            Tem_L=0x0b;//显示"F"符号
        }
        else
        {
            Tem_H=0x0a;//显示"-"符号
            Tem_L=(uint)Tem/10%10;//显示温度
        }
    }  
}


void WR_595(unsigned char data num2 )//写
{
   unsigned char data count1;   
   for(count1=0;count1<=7;count1++)
   {
     if((num2&0x80)==0x80)  //*最高位为1,则向SDATA_595发送1*/
        SDATA_595=1;        //*发出数据的最高位*/
     else  
        SDATA_595=0;
     
     num2<<=1;         //*右移位*/
     SCLK_595=0;       //*产生上生沿*/
     SCLK_595=1;   
    }   
}
/*-------------------------------------------------------------------------------
                     打开锁存,更新74595输出子程序
---------------------------------------------------------------------------------*/
void Out_595(void)
{
   RCK_595=0;
   _nop_();
   _nop_();
   RCK_595=1;  /*上升沿锁存数据*/

}
/*-------------------------------------------------------------------------------
                  74HC138移位子程序
---------------------------------------------------------------------------------*/
WR_138(unsigned char count)
{
        switch(count)
        {
        case 0x00:{P1_4=0;P1_5=0;P1_6=0;}break;
        case 0x01:{P1_4=0;P1_5=0;P1_6=1;}break;
        case 0x02:{P1_4=0;P1_5=1;P1_6=0;}break;
        case 0x03:{P1_4=0;P1_5=1;P1_6=1;}break;
        case 0x04:{P1_4=1;P1_5=0;P1_6=0;}break;
        case 0x05:{P1_4=1;P1_5=0;P1_6=1;}break;       
        default:{P1_4=1;P1_5=1;P1_6=1;}
        }       
}
                  //                             显示                                                                          //
/*--------------------------------------------------------------------*/
void disp(void)
{

WR_595(TAB[0]); //
WR_595(TAB[Hour/16]); //写数码管的段 小时(十位)
WR_595(TAB[2]); //写数码管的段 年(千位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x00);  //138译码器 00010000  
delay(20);

WR_595(TAB[0]); //
WR_595(TAB[Hour%16]); //写数码管的段 小时(个位)
WR_595(TAB[0]); //写数码管的段年(百位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x01);  //138译码器 00100000
delay(20);

WR_595(TAB[Tem_H]); //写数码管的段 温度(十位)
WR_595(TAB[Minute/16]); //写数码管的段 分钟(十位)
WR_595(TAB[Year/16]); //写数码管的段年 (十位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x02);  //138译码器 00110000
delay(20);

WR_595(TAB[Tem_L]); //写数码管的段温度(个位)
WR_595(TAB[Minute%16]); //写数码管的段 分钟(个位)
WR_595(TAB[Year%16]); //写数码管的段 年(个位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x03);  //138译码器 01000000
delay(20);

WR_595(TAB[Day/16]); // 写数码管的段日 (十位)
WR_595(TAB[Second/16]); //写数码管的段秒 (十位)
WR_595(TAB[Month/16]); //写数码管的段 月(十位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x04);  //138译码器 01010000
delay(20);

WR_595(TAB[Day%16]); //写数码管的段日(个位)
WR_595(TAB[Second%16]); //写数码管的段秒 (个位)
WR_595(TAB[Month%16]); //写数码管的段 月(个位)
WR_138(0x07);        //关闭138译码器
Out_595();        //打开锁存,更新74595输出
WR_138(0x05);  //138译码器 01100000
}

void init_ds32C35()
{
        write_add(0x00,D_BCD(50));   //设定秒钟初值   
        write_add(0x01,D_BCD(59));   //设定分钟初值   
        write_add(0x02,D_BCD(23));   //设定时钟初值   
        write_add(0x03,D_BCD(7));   //设定星期初值   
       
        write_add(0x04,D_BCD(31));   //设定日初值   
        write_add(0x05,D_BCD(1));   //设定月初值   
        write_add(0x06,D_BCD(10));   //设定年初值   
       
//        write_add(0x0E,D_BCD(0x20));  //设置DS32C35温度闹钟等参数
//        write_add(0x0F,D_BCD(0x0f));  //设置DS32C35输出32KHZ
}

Set()//时间设置
{
        uchar Buffer;
                *DS_Data=BCD_D(*DS_Data);//BCD码转十进制
                if(!Key_Add)        //加
                {
                        delay(30);
                        while(!Key_Add);
                        if((*DS_Data)<Max)
                                (*DS_Data)++;
                        else  
                                (*DS_Data)=Min;
                }
                if(!Key_Dec)                //减
                {
                        delay(30);
                        while(!Key_Dec);                       
                        if((*DS_Data)>Min)
                                (*DS_Data)--;
                        else  
                                (*DS_Data)=Max;
                }
                if(Change) //显示“——”
                {       
                        Buffer=*DS_Data;
                        *DS_Data=0xaa;
                        disp();       
                        *DS_Data=Buffer;
                        *DS_Data=D_BCD(*DS_Data);               
                }            
                if(!Change)
                {
                        *DS_Data=D_BCD(*DS_Data);
                        disp();
                }       
                if(!Key_Set)       
                {
                        delay(30);
                        while(!Key_Set);
                        if(Set_Flag==6)
                        {
                                Set_Flag=0;
                                write32c35();
                        }
                        else
                        {
                                Set_Flag++;
                        }
                }
                if(!Key_Ok)
                {
                        delay(30);
                        while(!Key_Ok);
                        Set_Flag=0;
                        write32c35();

                }
        }

/*--------------------------------------------------------------*/
//主函数
void main(void)
{
//        init_ds32C35();
        EN_595=0;         
        while(1)
        {
                if(Set_Flag==0)//设置键未按下时候
                {
                        read32c35();//时钟更新               
                        if(!Second)//60秒更新一次温度(0秒时更新)
                                readtemp();//温度更新
                        disp();
                }
       

                if(!Key_Set)
                {
                        delay(50);
                        while(!Key_Set);
                        Set_Flag++;
                }               

                if(Set_Flag==1)//设置"年"
                {
                        Min=10;
                        Max=20;
                        DS_Data=&Year;
                        Set();
                }
                if(Set_Flag==2)//设置"月"
                {
                        Min=1;
                        Max=12;
                        DS_Data=&Month;
                        Set();
                }
                if(Set_Flag==3)//设置"日"
                {
                        Min=1;
                        if((Month==1)|(Month==3)|(Month==5)|(Month==7)|(Month==8)|(Month==10)|(Month==12))// 1、3、5、7、9、10、12月为31天
                                Max=31;
                        if((Month==4)|(Month==6)|(Month==9)|(Month==11))//4// 4、6、9、11月为30天
                                Max=30;
                        if((BCD_D(Year)%4!=0)&&(Month==2))//非闰年的2月为28天
                                Max=28;
                        if((BCD_D(Year)%4==0)&&(Month==2))//闰年的2月为29天       
                                Max=29;
                        DS_Data=&Day;
                        Set();
                }
                if(Set_Flag==4)//设置"小时"
                {
                        Min=0;
                        Max=23;
                        DS_Data=&Hour;
                        Set();
                }
                if(Set_Flag==5)//设置"分"
                {
                        Min=0;
                        Max=59;
                        DS_Data=&Minute;
                        Set();
                }
                if(Set_Flag==6)//设置"秒"
                {
                        Min=0;
                        Max=59;
                        DS_Data=&Second;
                        Set();
                }
                if(Set_Flag)//显示切换条件
                {
                        Change_Num++;
                        if(Change_Num==20)
                                Change=0;
                        if(Change_Num==40)
                        {
                                Change=1;
                                Change_Num=0;       
                        }
                }
        }
}         


                                                                                                                          



自己提取  驱动吧
回复

使用道具 举报

发表于 2012-5-23 14:01 | 显示全部楼层
嗯,这个这么一般的IC,就别玩了。楼主还是回家吧。
回复

使用道具 举报

发表于 2012-5-23 14:32 | 显示全部楼层
12887也不错啊,论坛还有程序。几天才一秒左右。但是找不到用1602的12887的程序。自己也不会整。
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-11-2 00:42 , Processed in 0.042355 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表