搜索
bottom↓
回复: 12

DS1302做的万年历-1602C液晶显示(atmega16-ICC)

[复制链接]

出0入0汤圆

发表于 2008-4-12 12:03:00 | 显示全部楼层 |阅读模式

接线电路图 (原文件名:未命名.JPG)


//========================================================
/*接线图如下:
_______________           ______________
               |      --1|GND           |
               |      --2|+5V           |
               |      --3|V0            |
               |         |              |
            PD5|--------4|RS            |
            PD6|--------5|RW            |
            PD7|--------6|E             |
CPU           |         |              |
ATmmega16L PA0|--------7|D0  LCD20x4   |
            PA1|--------8|D1            |
            PA2|--------9|D2            |
            PA3|-------10|D3            |
            PA4|-------11|D4            |
            PA5|-------12|D5            |
            PA6|-------13|D6            |
            PA7|-------14|D7            |
               |         |              |
               |     --15|+LED          |
               |     --16|-LED          |
_______________|         |______________| */
//========================================================
#include<iom16v.h> //CPU_ATmmega16L
#include <macros.h>
#define RS_H    asm("sbi 0x12,5")  //RS设为高电平
#define RS_L    asm("cbi 0x12,5")  //RS设为低电平
#define RW_H    asm("sbi 0x12,6")  //RW设为高电平
#define RW_L    asm("cbi 0x12,6")  //RW设为低电平
#define E_H     asm("sbi 0x12,7")  //E设为高电平
#define E_L     asm("cbi 0x12,7")  //E设为低电平

//=======================================================
//微秒级延时程序
void delay_us(int time)
{ char i;
   while(time--)
   {
   for(i=0;i<8;i++);
   }
}
//=======================================================
//毫秒级延时程序
void delay_ms(unsigned int time)
{
    while(time != 0)
    {                 
        delay_us(1000);
        time--;
    }
}

//=======================================================
//读取lcd是否内部操作(忙碌)状态
char Lcd_Busy()
{
    char r;
    DDRA = 0x00;       //端口A栉淙敕绞?
    E_L;RS_L;RW_H;     //E=0(致能),RS=0(命令),RW=1(读)
    delay_us(2);       //液晶延时子程序
    E_H;
    delay_us(2);       //液晶延时子程序
    r = PINA & 0x80;   //读取lcd_data第八位
    E_L;
    DDRA=0xff;         //端口A设为输出方式
    return r;          //读取结果返回 */
       
       
}

//=======================================================
//向Lcd发送命令程序
void Lcd_Command(unsigned char Command)
{  

    while(Lcd_Busy()); //判断lcd是否内部操作状态
    E_L;RS_L;RW_L;     //E=0(致能),RS=0(命令),RW=0(写)
    delay_us(2);       //液晶延时子程序
    E_H;
        DDRA = 0xff;
    PORTA = Command;   //向Lcd发送命令
    delay_us(2);       //液晶延时子程序
    E_L;
   
}

//=======================================================
//向lcd写入一个字符程序
void Lcd_Write(unsigned char Data)
{
    while(Lcd_Busy()); //判断lcd是否内部操作状态
    E_L;
        RS_H;
        RW_L;     //E=0(致能),RS=1(数据),RW=0(写)
    delay_us(2);       //液晶延时子程序
    E_H;
        DDRA = 0xff;
    PORTA =  Data;     //向lcd写入一个字符
  delay_us(2);       //液晶延时子程序
    E_L;
}


/*=======================================================
LCD第1行显示地址1~20(0x80~0x8f)
LCD第2行显示地址1~20(0xc0~0xcf)


=======================================================*/
//初始化LCD_8位接口,2行x16字符的工作方式
void Lcd_Init()
{
    DDRA = 0xff;       //端口A设为输出方式
    DDRD = 0xff;       //端口D设为输出方式
    Lcd_Command(0x38); //
        delay_ms(5);
    Lcd_Command(0x38); //
        delay_ms(5);
    Lcd_Command(0x38); //
        delay_ms(5);
    Lcd_Command(0x38); //
    Lcd_Command(0x08); //令显示器off
    Lcd_Command(0x01); //清除显示器
    Lcd_Command(0x06); //令LCD每接收到1Byte数据后,AC自动加1
    Lcd_Command(0x0c); //令光标,0x0c=不显示,0x0d=显示闪动.  
}

//=======================================================
//写ASCII字符串程序
void asc_tran(unsigned char *asc)
{
    while((*asc) != 0)   //判断字是否结束
    {
        Lcd_Write(*asc); //向lcd写入字符串
        asc++;           //移下一个字符
    }
}

//=======================================================
//测试主LCD主程序
/* void main()
{
    Lcd_Init(); //初始化LCD
    while(1)
    {
       Lcd_Command(0x80);               //设置显示位址
                //asc_tran("harbingongchengdaxue");
        asc_tran("I Love Gao Yan");      //显示字符串
        Lcd_Command(0xc0);               //设置显示位址
                asc_tran("maybe I can't");      //显示字符串
        delay_ms(600);                  //延迟1秒
        Lcd_Command(0x01);               //清除显示器

        Lcd_Command(0x80);               //设置显示位址
        asc_tran("-----^_^------");      //显示字符串
        Lcd_Command(0xc0);               //设置显示位址
        asc_tran("www.baidu.com"); //显示字符串
        delay_ms(600);                  //延迟
        Lcd_Command(0x01);               //清除显示器
               
               
        Lcd_Command(0x80);               //设置显示位址
        asc_tran("-----__@------");      //显示字符串
        Lcd_Command(0xc0);               //设置显示位址
        asc_tran("08-03-30-Sunday"); //显示字符串
        delay_ms(600);                  //延迟
        Lcd_Command(0x01);               //清除显示器
    }
}*/

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

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2008-4-12 12:03:34 | 显示全部楼层
//ICC-AVR application builder
// Target : M16
// Crystal: 7.3728Mhz

#include <iom16v.h>
#include <macros.h>
unsigned char buffer3[7]={0x45,0x00,0x55,0x00,0x66,0x00,0x00};
void port_init(void)
{
PORTA = 0xFF;
DDRA  = 0x00;
PORTB = 0xFF;
DDRB  = 0x00;
PORTC = 0xff; //m103 output only
DDRC  = 0xFF;
PORTD = 0xFF;
DDRD  = 0x00;
}

//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();

MCUCR = 0x00;
GICR  = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialised
}

/*********************************************************************/
/* 实时时钟模块 时钟芯片型号:DS1302 */
/*********************************************************************/
#define        T_CLK 0
#define        T_IO  1
#define        T_RST 7
/******************************************************************** */

#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 nop(void)
{
char i;
for (i=0;i<1;i++)
  ;
}

void initialize_1302(void)
{
write_1302(0x8e,0x00);//写允许
write_1302(0x90,0xA5);//
write_1302(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(PORTC,T_CLK);
                if (ucDa&1) SETBIT(PORTC,T_IO);
                    else CLRBIT(PORTC,T_IO);
                SETBIT(PORTC,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(DDRC,T_IO);
        CLRBIT(PORTC,T_IO);
    for(i=8; i>0; i--)
    {
        t>>=1;
                SETBIT(PORTC,T_CLK);
                nop();
                CLRBIT(PORTC,T_CLK);
                nop();
                if(CHKBIT(PINC,T_IO))t|=0x80;
        }
    SETBIT(DDRC,T_IO);
        return(t);
}


/********************************************************************
* 名称: write_1302
* 说明: 先写地址,后写命令/数据
* 功能: 往DS1302写入数据
* 调用: ds1302_write_a_byte()
* 输入: ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值: 无
***********************************************************************/
void write_1302(unsigned char ucAddr, unsigned char ucDa)
{
    //DDRC=0xff;
    CLRBIT(PORTC,T_RST);     //T_RST=0
        //;;nop();
        CLRBIT(PORTC,T_CLK);         //T_CLK=0;
        //;;nop();
        SETBIT(PORTC,T_RST);         //T_RST=1

    ds1302_write_a_byte(ucAddr); /* 地址,命令 */
        CLRBIT(PORTC,T_CLK);
    ds1302_write_a_byte(ucDa); /* 写1Byte数据*/
        CLRBIT(PORTC,T_CLK);      //T_CLK=1
        //;;nop();
        CLRBIT(PORTC,T_RST);          //T_RST=0
}

/********************************************************************
* 名称: read_1302
* 说明: 先写地址,后读命令/数据
* 功能: 读取DS1302某地址的数据
* 调用: ds1302_write_a_byte() , ds1302_read_a_byte()
* 输入: ucAddr: DS1302地址
* 返回值: ucDa :读取的数据
***********************************************************************/
unsigned char read_1302(unsigned char ucAddr)
{
    unsigned char ucDa;
        CLRBIT(PORTC,T_RST);
        //;;nop();
        CLRBIT(PORTC,T_CLK);
        //;;nop();
        SETBIT(PORTC,T_RST);


    ds1302_write_a_byte(ucAddr); /* 地址,命令 */
    ucDa = ds1302_read_a_byte(); /* 读1Byte数据 */
        CLRBIT(PORTC,T_CLK);
        //;;nop();
        CLRBIT(PORTC,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;
    write_1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
        CLRBIT(PORTC,T_RST);
        CLRBIT(PORTC,T_CLK);
        SETBIT(PORTC,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(PORTC,T_CLK);
        CLRBIT(PORTC,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(PORTC,T_RST);
        CLRBIT(PORTC,T_CLK);
        SETBIT(PORTC,T_RST);
    ds1302_write_a_byte(0xbf); /* 0xbf:时钟多字节读命令 */
    for (i=8; i>0; i--)
    {
        *pSecDa = ds1302_read_a_byte(); /* 读1Byte数据 */
        pSecDa++;
    }
        //DDRC=0xff;
        SETBIT(PORTC,T_CLK);
        CLRBIT(PORTC,T_RST);
}

/********************************************************************
* 名称: v_BurstW1302R
* 说明: 先写地址,后写数据(寄存器多字节方式)
* 功能: 往DS1302寄存器数写入数据(多字节方式)
* 调用: ds1302_write_a_byte()
* 输入: pReDa: 寄存器数据地址
* 返回值: 无
***********************************************************************/
void v_BurstW1302R(unsigned char *pReDa)
{
    unsigned char i;
    write_1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
        CLRBIT(PORTC,T_RST);
        CLRBIT(PORTC,T_CLK);
        SETBIT(PORTC,T_RST);
    ds1302_write_a_byte(0xfe); /* 0xfe:寄存器多字节写命令 */
    for (i=31;i>0;i--) /*31Byte 寄存器数据 */
    {
        ds1302_write_a_byte(*pReDa); /* 写1Byte数据*/
        pReDa++;
    }
        SETBIT(PORTC,T_CLK);
        CLRBIT(PORTC,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(PORTC,T_RST);
        CLRBIT(PORTC,T_CLK);
        SETBIT(PORTC,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(PORTC,T_CLK);
        CLRBIT(PORTC,T_RST);
}

/********************************************************************
* 名称: v_Set1302
* 说明:
* 功能: 设置初始时间
* 调用: write_1302()
* 输入: pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值: 无
//////IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
***********************************************************************/
void v_Set1302(unsigned char *pSecDa)
{
    unsigned char i;
    //unsigned char ucAddr = 0x80;
        unsigned char ucAddr = 0x8C;
    write_1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
    for(i =7;i>0;i--)
    {
        write_1302(ucAddr,*pSecDa); /* 秒 分 时 日 月 星期 年 */

        pSecDa++;
       // ucAddr +=2;
           ucAddr -=2;
    }
    write_1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/
}
////IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
/********************************************************************
* 名称: v_Get1302
* 说明:
* 功能: 读取DS1302当前时间
* 调用: read_1302()
* 输入: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
* 返回值: 无
***********************************************************************/
void v_Get1302(unsigned char ucCurtime[])
{
    unsigned char i;
    //unsigned char ucAddr = 0x81;
        unsigned char ucAddr = 0x8D;
    for (i=0;i<7;i++)
    {
        ucCurtime = read_1302(ucAddr);/*格式为: 秒 分 时 日 月
        星期 年 */
        ucAddr -= 2;
    }
        CLRBIT(PORTC,T_CLK);
}

/*  enable power charge of 1302  */

void LCD_1302(void)
{
   int i,j,k;
   for(i=0;i<7;i++)
   {
   j=buffer3/16;
   k=buffer3%16;
   Lcd_Write(j+48);
   Lcd_Write(k+48);
   }
}

const unsigned char WeekTab[] = {
        //闰年月星期表
  (3 << 5) + 31,///1月
  (6 << 5) + 29,///2月
  (0 << 5) + 31,///3月
  (3 << 5) + 30,///4月
  (5 << 5) + 31,//5月
  (1 << 5) + 30,//6月
  (3 << 5) + 31,//7月
  (6 << 5) + 31,//8月
  (1 << 5) + 30,//9月
  (4 << 5) + 31,//10月
  (0 << 5) + 30,//11月
  (2 << 5) + 31 //12月
};

/*!------------------------------------------------------------------------------
                                2000年~2099年星期算法
-------------------------------------------------------------------------------*/
unsigned char WeekDay20(unsigned char y, unsigned char m, unsigned char d)
{
unsigned char week, day;
  day = WeekTab[m - 1];///月表
  week = day >> 5;///月星期数
  day &= 0x1f;//月天数
  if ((m < 3) && (y & 0x03))
                {///平年
    if (m == 2) day--;///平年月天数
    week++;///平年月表+1
  }
  y = y + (y >> 2);//年+年/4
  week = (week +  y + d + 2) % 7;///(星期=年+年/4+月表+2日)%7
  return week;///返回星期
}
unsigned char BcdToBin(unsigned char val)
  {
  val = (val >> 4) *10+(val &0x0f); ///将BCD码转换为10进制数
  return val; ///返回10进制数
  }

unsigned char BinToBcd(unsigned char val)
  {
  return ((val / 10) *16+val % 10);
  }

void main()
{
//unsigned char buffer2[7]={0x45,0x07,0x20,0x11,0x04,0x5,0x08}; //初始数秒,分,时,日,
//月,星期,年
unsigned char buffer2[7]={0x08,0x7,0x12,0x31,0x23,0x59,0x57}; //初始数秒,分,时,日,
//月,星期,年
buffer2[1]=WeekDay20(BcdToBin(buffer2[0]),BcdToBin(buffer2[2]),BcdToBin(buffer2[3]));

init_devices();
Lcd_Init(); //初始化LCD
initialize_1302();
v_Set1302(buffer2);



while(1)
{
  Lcd_Command(0x80);               //设置显示位址
//asc_tran("2008-04-10-19-11");
v_Get1302(buffer3);
LCD_1302();
}
}

出0入0汤圆

 楼主| 发表于 2008-4-12 12:06:05 | 显示全部楼层
说明:
液晶的ADJ端接50K的电位器,调整液晶的背光
有什么问题 Q:767085002

出0入0汤圆

 楼主| 发表于 2008-4-12 12:08:48 | 显示全部楼层
非原创,移值+自己修改
菜鸟一个,多多指教

出0入0汤圆

 楼主| 发表于 2008-4-12 12:12:17 | 显示全部楼层
在DS1302的8脚接电池供电,可以保证在单片机掉电的情况下时钟正常工作

出0入0汤圆

发表于 2008-4-12 13:30:58 | 显示全部楼层
没有按键??我最近也在做这个

出0入0汤圆

发表于 2008-4-12 18:17:21 | 显示全部楼层
共同学习了,没有按键有点遗憾

出0入0汤圆

发表于 2008-4-12 22:39:52 | 显示全部楼层
看下思路也不错。

出0入0汤圆

 楼主| 发表于 2008-4-13 19:12:22 | 显示全部楼层
自己做着玩,提醒一句:DS1302的供电电压不是5V
5V时钟跑飞
3.3-4V

出0入0汤圆

发表于 2013-12-13 14:25:52 | 显示全部楼层

出0入0汤圆

发表于 2014-4-20 13:43:17 | 显示全部楼层

出0入0汤圆

发表于 2014-4-28 16:56:05 | 显示全部楼层
语言也是C语言,和单片机有点类似

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-8-27 02:45

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

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