搜索
bottom↓
回复: 8

关于avr控制ds1302

[复制链接]

出0入0汤圆

发表于 2013-4-3 15:12:17 | 显示全部楼层 |阅读模式
本帖最后由 feifeimao 于 2013-4-3 15:14 编辑

/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.5 Standard
Automatic Program Generator
?Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 2013-04-01
Author  : F4CG                           
Company : F4CG                           
Comments:


Chip type           : ATmega128
Program type        : Application
Clock frequency     : 7.372800 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 1024
*****************************************************/
#include <mega128.h>
#include "1602.c"                       //包含1602液晶函数文件
#include <delay.h>

//#define uchar unsigned char
//#define uint  unsigned int

/******************RTC常量******************/
#define RTC_CLK           PORTD.4
#define RTC_DATA          PORTD.5
#define RTC_CS            PORTD.6
        //命令
#define RD                  0x01
#define WR                  0x00
#define C_SEC                0x80        //秒
#define C_MIN                0x82        //分
#define C_HR                0x84        //时
#define C_DAY                0x86        //日
#define C_MTH                0x88        //月
#define C_WK                0x8A        //星期 DATE
#define C_YR                0x8C        //年
#define C_WP                0x8E        //控制(写保护)
#define C_CHARGE        0x90        //涓流充电
#define C_BURST                0xBE        //时钟多字节
        //配置
#define CLK_HALT                0x80        //停止时钟控制位    SECOND        bit7
#define CLK_START                0x00        //启动时钟
#define M12_24                        0x80        //12/24小时值选择位 HOUR                bit7
#define PROTECT                        0x80        //写保护控制位      CONTROL        bit7
#define UPROTECT                0x00        //写保护控制位      CONTROL        bit7
        //涓流充电控制常量
#define TC_D1R2                        0xA5        //high 1 Diode +2K Resistors  
#define TC_D2R8                        0xAB        //low  2 Diodes+8K Resistors  
#define TC_DISABLED                0x00        //Disabled(TCS<>1010 or DS=00 or RS=00)
        //RAM 命令
#define C_RAMBASE                0xC0        //RAM0~RAM30<<1 地址需左移一位


/*******************************************
函数名称: DS1302_init
功    能: 初始化DS1302的数据接口
参    数: 无
返回值  : 无
/********************************************/
void DS1302_portinit(void)                  
{
    DDRD=0x70;      //将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出
}
/*******************************************
函数名称: DS1302_writeB
功    能: 向DS1302写入一个字节数据(没有RST操作)
参    数: byte--要写入的数据
返回值  : 无
/********************************************/
void DS1302_writeB(uchar byte)
{
uchar i;
for(i=0;i<8;i++)                           //8位数据计数
{
   RTC_CLK=0;                  //拉低时钟端
   if(byte&0x01)                                  //当前位是否是1
   {
     RTC_DATA=1;          //当前位是1,拉高数据端
   }
   else                                                  
   {
     RTC_DATA=1;          //当前位是0,拉低数据端
   }  
   delay_us(10);                                  //调整时钟和脉冲宽度
   RTC_CLK=1;                  //时钟上升沿(DS1302采样数据)
   byte>>=1;                                          //数据右移1位,为送出新数据位做准备
}
}
/*******************************************
函数名称: DS1302_readB
功    能: 从DS1302读出一个字节数据(没有RST操作)
参    数: 无
返回值  : byte--读出的数据
/********************************************/
uchar DS1302_readB(void)
{
uchar i,byte=0;
DDRD=0xDF;                 //将数据端口设置为输入                  
PORTD=0xDF;                 //无上拉电阻
for(i=0;i<8;i++)                         //8位数据计数
{
   byte>>=1;                                   //保存读入的数据位
   RTC_CLK=1;                 //时钟上升沿
   delay_us(10);                                 //延时,调整时钟脉冲宽度
   RTC_CLK=0;                 //时钟下降沿,DS1302输出数据位
   delay_us(10);                                 //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
   if(PIND&PORTD.5)         //当前位是否是高电平
   {
     byte|=0x80;                         //是高电平就将返回数据的当前位置1
   }
   else
   {
     byte&=0x7F;                         //是低电平就将返回数据的当前位置0
   }
}
DDRD=0xFF;                 //最后将数据端口设置为输出
return byte;                                 //返回读出的数据
}
/*******************************************
函数名称: DS1302_writeD
功    能: 向DS1302的某个地址写入一个字节数据
参    数: addr--地址值(寄存器或RAM)
                    data--要写入的地址
返回值  : 无
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
RTC_CS=0;         //拉低片选端
RTC_CLK=0;         //拉低时钟端
delay_us(10);
RTC_CS=1;         //拉高片选端
delay_us(10);                          //调整片选脉冲
DS1302_writeB(addr);         //写入操作命令(地址)
delay_us(10);
RTC_CLK=0;         //拉低时钟端
delay_us(10);
DS1302_writeB(data);         //写入数据
RTC_CLK=0;         //拉低时钟端
delay_us(10);                         //调整片选脉冲
RTC_CS=0;         //拉低片选端
}
/*******************************************
函数名称: DS1302_readD
功    能: 从DS1302的某个地址读出一个字节数据
参    数: addr--地址值(寄存器或RAM)
返回值  : data--读出的数据
/********************************************/
uchar DS1302_readD(uchar addr)
{
uchar data;
RTC_CS=0;         //拉低片选端
RTC_CLK=0;         //拉低时钟端
delay_us(10);
RTC_CS=1;         //拉高片选端
delay_us(10);                         //调整片选脉冲
DS1302_writeB(addr);         //写入操作命令(地址)
delay_us(10);
data=DS1302_readB();         //读出数据
delay_us(10);
RTC_CLK=0;         //拉低时钟端
RTC_CS=0;         //拉低片选端
return data;                         //返回读出的数据
}
/*******************************************
函数名称: DS1302_setT
功    能: 设置DS1302的时间
参    数: ptTimeD--设置时间数组指针
返回值  : 无
/********************************************/
void DS1302_setT(uchar ptTimeD[])
{
    uchar i;
    uchar addr = 0x80;                                    //写入地址从秒寄存器开始
    DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作
        delay_ms(5);
    for(i=0;i<7;i++)
    {
        DS1302_writeD(addr|WR,ptTimeD);   // 秒 分 时 日 月 星期 年         
        addr+=2;
                delay_ms(1);
    }
    DS1302_writeD(C_WP|WR,PROTECT);                 //控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: DS1302_getT
功    能: 读取DS1302的当前时间
参    数: time[]--读取的时间数组
返回值  : 无
/********************************************/
void DS1302_getT(uchar time[])
{
    uchar i;
////////下面的是单次读写//////////////////////////       
    uchar addr = 0x80;                                                      //读取地址从秒寄存器开始
    for(i=0;i<7;i++)
    {
        time=DS1302_readD(addr|RD);    // 秒 分 时 日 月 星期 年        
        addr+=2;
    }
     RTC_CLK=0;                                           //拉低时钟端(时钟端在不操作时为低)
}

/*******************************************
函数名称: DS1302_init
功    能: 初始化DS1302
参    数: 无
返回值  : 无
/********************************************/
void DS1302_init(void)
{
DS1302_writeD(C_WP|WR,UPROTECT);                  //写入写允许命令
DS1302_writeD(C_SEC|WR,CLK_START);                //启动振荡器,DS1302开始工作
DS1302_writeD(C_WP|WR,PROTECT);                 //控制命令,WP位为1,不允许写操作          
}
/*******************************************
函数名称: BCD_ASCII
功    能: 将压缩BCD码转换成ascii码
参    数: BCD--将要转换的压缩BCD码
                    ptasc--转换后的ASCII码数组指针
返回值  : 无
/********************************************/
void BCD_ASCII(uchar BCD,uchar ptasc[])
{        
        ptasc[0]=BCD/16|0x30;        //0X58        35  38 //转换十位
        ptasc[1]=BCD&0x0F|0x30;  //转换个位
}
/*******************************************
函数名称: Disp_time
功    能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)
参    数: time[]--时间数组
返回值  : 无
/********************************************/
void Disp_time(uchar time[])
{
uchar i,asc[2];
uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
uchar line2[9]={0,0,':',0,0,':',0,0,'\0'};                  //显示第2行的字符数组
for(i=0;i<3;i++)                                                                  //为第2行的字符数组赋值
{
  BCD_ASCII(time[2-i],asc);
  line2[i*3]=asc[0];
  line2[i*3+1]=asc[1];
}
BCD_ASCII(time[6],asc);                                                     //为第1行的年赋值
line1[0]=asc[0];
line1[1]=asc[1];
BCD_ASCII(time[4],asc);                                                  //为第1行的月赋值
line1[3]=asc[0];
line1[4]=asc[1];
BCD_ASCII(time[3],asc);                                                  //为第1行的日赋值
line1[6]=asc[0];
line1[7]=asc[1];
BCD_ASCII(time[5],asc);                                                  //为第1行的星期赋值
line1[9]=asc[1];

displayROM(0X82,"20");                   //第1行从第3个位置开始显示,将07年显示为2007的形式

displayRAM(0X84,line1);

displayRAM(0X80+0X44,line2);             //第2行从第5个位置开始显示,/第2行显示
}
/*******************************************
函数名称: main
功    能: 1. 在1602液晶上显示当前时间 2.可以设置时间(M1-M9为数字0-9,M13为设置模式和显示模式选择,M14为当前设置位选择)
参    数: 无
返回值  : 无
/********************************************/
void main(void)
{
       
        //uchar setadd,setdat,shift;          //setadd指定将当前数值送入DS1302的哪个寄存器
                                                             //setdat是当前设置的数值,即被送入DS1302指定寄存器的数
                                                          //shift来实现十位和各位的设置相互独立(因为十位和个位是在一个寄存器里的)
   
        //uchar dis_x,dis_y;                          //存储1602液晶当前光标的位置
        uchar settime[7]={0x50,0x59,0x23,0x01,0x01,0x06,0x07};//设置的秒,分,时,日,月,星期,年
        uchar gettime[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//保存当前时间的数
        //初始化液晶
        PORTA=0xFF;
        DDRA=0xFF;
        PORTB=0x07;
        DDRB=0x07;
        lcd_init();

        DS1302_portinit();                        //初始化DS1302的三根数据线
        DS1302_init();                                //启动振荡器,DS1302开始工作
        DS1302_setT(settime);                //设置初始时间

        while(1)                                        //以下程序完成显示和设置时间
        {
            DS1302_getT(gettime);        //获得当前时间
             Disp_time(gettime);                //显示当前时间
   
    }
}   这个1302的子函数有问题  在proteus显示  都是0  请教下

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2013-4-8 00:27:32 | 显示全部楼层
uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
uchar line2[9]={0,0,':',0,0,':',0,0,'\0'};                  //显示第2行的字符数组

这两个移到while(1)外面定义看看

出0入0汤圆

发表于 2013-4-8 10:22:06 | 显示全部楼层
hugolulu 发表于 2013-4-8 00:27
uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
uchar line2[9]={0,0,':',0,0,' ...

打错,是定义为全局变量看看,在main(){}外面定义

出0入0汤圆

 楼主| 发表于 2013-4-8 14:09:03 | 显示全部楼层
呵呵 试过了 还是不行啊  
依然都是0

出0入0汤圆

发表于 2013-4-8 15:01:02 | 显示全部楼层
我用M8试过,开始不得,后来那两个数组定义全局变量才有显示,不然就一直类似不断复位的现象

出0入0汤圆

 楼主| 发表于 2013-4-9 20:05:03 | 显示全部楼层
我的qq::150216708
希望可以进一步聊聊
谢谢你的回复

出0入0汤圆

发表于 2013-4-9 21:36:56 | 显示全部楼层
加不了你呢,qq设置拒绝

出0入0汤圆

 楼主| 发表于 2013-4-10 09:24:27 | 显示全部楼层
哈哈哈  现在可以加我了  或者你也留下qq号码 我可以选择加你啊  

出0入0汤圆

发表于 2013-10-18 17:11:01 | 显示全部楼层
ds1302不初始化是不工作的,而且我也没这样写过程序,这是我仿写的ds1302的子程序你可以看一下
#define uchar unsigned char
#define uint  unsigned int
                        //包含1602LCD驱动程序文件包

/*******************************************************/
#define SCLK_0 PORTC&=~BIT(5)
#define SCLK_1 PORTC|=BIT(5)
#define SCLK_OUT DDRC|=BIT(5)

#define IO_0 PORTC&=~BIT(6)
#define IO_1 PORTC|=BIT(6)
#define IO_DAT PINC&BIT(6)
#define IO_IN DDRC&=~BIT(6)
#define IO_OUT DDRC|= BIT(6)

#define RST_0 PORTC&=~BIT(7)
#define RST_1 PORTC|=BIT(7)
#define RST_OUT DDRC|=BIT(7)

uint time_dat[7]={13,3,10,14,21,45,10};
uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};
uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
uchar talbe[14]={0};


void write_ds1302_byte(uchar DOT)
{
uchar i;
IO_OUT;
for(i=0;i<8;i++)
        {
        if (DOT&0x01)
        {
        IO_1;
        }
         else
        {
        IO_0;
         }
        SCLK_1;
                SCLK_0;
         DOT=DOT>>1;
        }
}

uchar read_ds1302(uchar add)
{

uchar value,i;
RST_0;
SCLK_0;
RST_1 ;
write_ds1302_byte(add);
IO_IN;
for(i=0;i<8;i++)
{
value=value>>1;
if(IO_DAT)
{
value=value|0x80;
}
SCLK_1;
SCLK_0;
}
RST_0;
return value;
}


void write_ds1302 (uchar addr,uchar tade )
{
RST_0;
SCLK_0;
RST_1;
write_ds1302_byte(addr);
write_ds1302_byte(tade);
RST_0;
}



void ini_t(void)
{

uchar i,k;
          for(i=0;i<7;i++)//将10进制转换16进制
          {
          k=time_dat[i]/10;
          time_dat[i]=time_dat[i]%10;
          time_dat[i]=time_dat[i]+k*16;
          }
write_ds1302(0x8e,0x00);
          for(i=0;i<7;i++)
          {
          write_ds1302(write_add[i],time_dat[i]);
          }
write_ds1302(0x8e,0x80);
}

//将16进制装换为10进制
uchar change16to10(uchar ata)
{
uchar ge,shi;
shi=ata/16;
ge=ata%16;
ata=shi*10+ge;
return ata;
}
//将10进制装换为16进制
uchar change10to16(uchar ata)
{
uchar shi,ge;
shi=ata/10;
ge=ata%10;
ata=shi*16+ge;
return ata;
}


void read_ds1302dat(void)
{

uchar i;
          for(i=0;i<7;i++)
          {
          time_dat[i]=read_ds1302(read_add[i]);
          }
}



void depar_dat(void)
{
talbe[0]=time_dat[0]/16;

talbe[1]=time_dat[0]%16;//年

talbe[2]=time_dat[1]%16;//星期

talbe[3]=time_dat[2]/16;
talbe[4]=time_dat[2]%16;//月

talbe[5]=time_dat[3]/16;
talbe[6]=time_dat[3]%16;//日

talbe[7]=time_dat[4]/16;

talbe[8]=time_dat[4]%16;//时

talbe[9]=time_dat[5]/16;

talbe[10]=time_dat[5]%16;//分

talbe[11]=time_dat[6]/16;

talbe[12]=time_dat[6]%16;//秒

;
}

/******************************************************/
void show_ds1302(void)
{
//SREG &=~BIT(7);//关掉中断
lcd_pos(1,3);

write_data(talbe[0]+48);
write_data(talbe[1]+48);//年
lcd_pos(2,7);
write_data(talbe[2]+48);//星期
write_data(' ');
lcd_pos(2,1);
write_data(talbe[3]+48);
write_data(talbe[4]+48);//月
lcd_pos(2,3);
write_data(talbe[5]+48);
write_data(talbe[6]+48);//日
lcd_pos(3,1);
write_data(talbe[7]+48);//时
write_data(talbe[8]+48);
lcd_pos(3,3);
write_data(talbe[9]+48);//分
write_data(talbe[10]+48);

lcd_pos(3,5);
write_data(talbe[11]+48);//秒
write_data(talbe[12]+48);


//SREG|=BIT(7);//打开中断
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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