单片机AT89C51+DS1302+LED怎么做时钟?最好有C语言程序、硬件接线图,请发邮箱845699187@qq.com

LED是八位的,这个时钟用在出租车计价器上,不用闹铃功能
2024-12-31 18:03:41
推荐回答(2个)
回答1:

//主程序

#include 

#include "LCD1602.h"

#include "DS1302.h"

void Delay1ms(unsigned int count)

{

unsigned int i,j;

for(i=0;i

for(j=0;j<120;j++);

}

main()

{

SYSTEMTIME CurrentTime;

LCD_Initial();

Initial_DS1302();

GotoXY(0,0);

Print("Date: ");

GotoXY(0,1);

Print("Time: ");

while(1)

{

DS1302_GetTime(&CurrentTime);

DateToStr(&CurrentTime);

TimeToStr(&CurrentTime);

GotoXY(6,0);

Print(CurrentTime.DateString);

GotoXY(6,1);

Print(CurrentTime.TimeString);

Delay1ms(300);

}

}

//19602程序

#ifndef LCD_CHAR_1602_2005_4_9

#define LCD_CHAR_1602_2005_4_9

#include 

//Port Definitions**********************************************************

sbit LcdRs = P2^0;

sbit LcdRw = P2^1;

sbit LcdEn   = P2^2;

sfr  DBPort  = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

//内部等待函数**************************************************************************

unsigned char LCD_Wait(void)

{

LcdRs=0;

LcdRw=1; _nop_();

LcdEn=1; _nop_();

//while(DBPort&0x80);//在用Proteus仿真时,注意用屏蔽此语句,在调用GotoXY()时,会进入死循环,

 //可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80==0x80

 //实际硬件时打开此语句

LcdEn=0;

return DBPort;

}

//向LCD写入命令或数据************************************************************

#define LCD_COMMAND 0      // Command

#define LCD_DATA 1      // Data

#define LCD_CLEAR_SCREEN 0x01      // 清屏

#define LCD_HOMING   0x02      // 光标返回原点

void LCD_Write(bit style, unsigned char input)

{

LcdEn=0;

LcdRs=style;    //数据\命令

LcdRw=0; _nop_();

DBPort=input; _nop_();//注意顺序

LcdEn=1; _nop_();//注意顺序

LcdEn=0; _nop_();//E下降沿有效

LCD_Wait();

}

//设置显示模式************************************************************

#define LCD_SHOW 0x04    //显示开

#define LCD_HIDE 0x00    //显示关   

#define LCD_CURSOR 0x02  //显示光标

#define LCD_NO_CURSOR 0x00    //无光标      

#define LCD_FLASH 0x01    //光标闪动

#define LCD_NO_FLASH 0x00    //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)

{

LCD_Write(LCD_COMMAND, 0x08|DisplayMode);

}

//设置输入模式************************************************************

#define LCD_AC_UP 0x02

#define LCD_AC_DOWN 0x00      // default

#define LCD_MOVE 0x01      // 画面可平移

#define LCD_NO_MOVE 0x00      //default

void LCD_SetInput(unsigned char InputMode)

{

LCD_Write(LCD_COMMAND, 0x04|InputMode);

}

//移动光标或屏幕************************************************************

/*

#define LCD_CURSOR 0x02      

#define LCD_SCREEN 0x08

#define LCD_LEFT 0x00

#define LCD_RIGHT 0x04

void LCD_Move(unsigned char object, unsigned char direction)

{

if(object==LCD_CURSOR)

LCD_Write(LCD_COMMAND,0x10|direction);

if(object==LCD_SCREEN)

LCD_Write(LCD_COMMAND,0x18|direction);

}

*/

//初始化LCD************************************************************

void LCD_Initial()

{

LcdEn=0;

LCD_Write(LCD_COMMAND,0x38);           //8位数据端口,2行显示,5*7点阵

LCD_Write(LCD_COMMAND,0x38);

LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标

LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏

LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动

}

//************************************************************************

void GotoXY(unsigned char x, unsigned char y)

{

if(y==0)

LCD_Write(LCD_COMMAND,0x80|x);

if(y==1)

LCD_Write(LCD_COMMAND,0x80|(x-0x40));

}

void Print(unsigned char *str)

{

while(*str!='\0')

{

LCD_Write(LCD_DATA,*str);

str++;

}

}

/*

void LCD_LoadChar(unsigned char user[8], unsigned char place)

{

unsigned char i;

LCD_Write(LCD_COMMAND,0x40|(place*8));

for(i=0; i<8; i++)

LCD_Write(LCD_DATA,user[i]);

}

*/

//************************************************************************

#endif

//1302程序

#ifndef _REAL_TIMER_DS1302_2003_7_21_

#define _REAL_TIMER_DS1302_2003_7_21_

sbit  DS1302_CLK = P1^6;              //实时时钟时钟线引脚 

sbit  DS1302_IO  = P1^7;              //实时时钟数据线引脚 

sbit  DS1302_RST = P1^5;              //实时时钟复位线引脚

sbit  ACC0 = ACC^0;

sbit  ACC7 = ACC^7;

typedef struct __SYSTEMTIME__

{

unsigned char Second;

unsigned char Minute;

unsigned char Hour;

unsigned char Week;

unsigned char Day;

unsigned char Month;

unsigned char  Year;

unsigned char DateString[9];

unsigned char TimeString[9];

}SYSTEMTIME; //定义的时间类型

#define AM(X) X

#define PM(X) (X+12)               // 转成24小时制

#define DS1302_SECOND 0x80

#define DS1302_MINUTE 0x82

#define DS1302_HOUR 0x84 

#define DS1302_WEEK 0x8A

#define DS1302_DAY 0x86

#define DS1302_MONTH 0x88

#define DS1302_YEAR 0x8C

#define DS1302_RAM(X) (0xC0+(X)*2)    //用于计算 DS1302_RAM 地址的宏  RAM命令控制字地址:0xC0-0xFD

void DS1302InputByte(unsigned char d)  //实时时钟写入一字节(内部函数)

    unsigned char i;

    ACC = d;

    for(i=8; i>0; i--)

    {

        DS1302_IO = ACC0;            //相当于汇编中的 RRC

    DS1302_CLK = 1;

     DS1302_CLK = 0;

    ACC = ACC >> 1; 

    } 

}

unsigned char DS1302OutputByte(void)  //实时时钟读取一字节(内部函数)

    unsigned char i;

    for(i=8; i>0; i--)

    {

        ACC = ACC >>1;          //相当于汇编中的 RRC 将前一个下降沿读出的数据右移一位从而读出该次读出的数放入ACC7

        ACC7 = DS1302_IO;

    DS1302_CLK = 1;

        DS1302_CLK = 0; //SCLK下降沿读出DS1302的数

    } 

    return(ACC); 

}

void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据

{

    DS1302_RST = 0;

    DS1302_CLK = 0;

    DS1302_RST = 1;

    DS1302InputByte(ucAddr);        // 地址,命令 

    DS1302InputByte(ucDa);        // 写1Byte数据

    DS1302_CLK = 1;

    DS1302_RST = 0;

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据

{

    unsigned char ucData;

    DS1302_RST = 0;

    DS1302_CLK = 0;

    DS1302_RST = 1;

    DS1302InputByte(ucAddr|0x01);        // 地址,命令 

    ucData = DS1302OutputByte();         // 读1Byte数据    DS1302_CLK = 1;

    DS1302_RST = 0;

    return(ucData);

}

void DS1302_SetProtect(bit flag)        //是否写保护

{

if(flag)

Write1302(0x8E,0x80);  //0x8E 控制字节地址,bit7=WP WP=1 禁止数据写入DS1302

else

Write1302(0x8E,0x00);  //WP=0  允许写入DS1302

}

void DS1302_SetTime(unsigned char Address, unsigned char Value)        // 设置时间函数

{

DS1302_SetProtect(0);

Write1302(Address, ((Value/10)<<4 | (Value%10))); 

}

void DS1302_GetTime(SYSTEMTIME *Time)

{

unsigned char ReadValue;

ReadValue = Read1302(DS1302_SECOND);

Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_MINUTE);

Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_HOUR);

Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_DAY);

Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_WEEK);

Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_MONTH);

Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_YEAR);

Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

}

void DateToStr(SYSTEMTIME *Time)

{

Time->DateString[0] = Time->Year/10 + '0';

Time->DateString[1] = Time->Year%10 + '0';

Time->DateString[2] = '-';

Time->DateString[3] = Time->Month/10 + '0';

Time->DateString[4] = Time->Month%10 + '0';

Time->DateString[5] = '-';

Time->DateString[6] = Time->Day/10 + '0';

Time->DateString[7] = Time->Day%10 + '0';

Time->DateString[8] = '\0';

}

void TimeToStr(SYSTEMTIME *Time)

{

Time->TimeString[0] = Time->Hour/10 + '0';

Time->TimeString[1] = Time->Hour%10 + '0';

Time->TimeString[2] = ':';

Time->TimeString[3] = Time->Minute/10 + '0';

Time->TimeString[4] = Time->Minute%10 + '0';

Time->TimeString[5] = ':';

Time->TimeString[6] = Time->Second/10 + '0';

Time->TimeString[7] = Time->Second%10 + '0';

Time->TimeString[8] = '\0';

}

void Initial_DS1302(void)

{

unsigned char Second=Read1302(DS1302_SECOND);

if(Second&0x80)              //BIT7=CH  CH=0振荡器允许工作,CH=1,振荡器停止   

DS1302_SetTime(DS1302_SECOND,0);

}

#endif

用LED稍微改下就OK,希望对你有帮助。

回答2:

用时钟芯片了最好是用LCD显示吧,贴个图给你。一定要LEd的话自己改下吧,有问题可以  +我