跪求51单片机控制1602液晶显示时钟的protues原理图及c语言程序,请各位大侠帮忙啊 5
#define uchar unsigned char
#define uint unsigned int
uchar code table[11]={0xc0,0xf9,0xa4,0xb0,0x99, 0x92, 0x82 ,0XD8,0x80,0x90,0xFF};
//不带小数点的显示段码表
uchar code table0[11]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10, 0xFF};
//带小数点的的显示段码表
uchar dis[3]={0x00,0x00,0x00}; //定义一个显示缓冲数组
void add(); //加函数
void reduce(); //减函数
void delay(uint t); //延时函数
void display(); //显示函数
void adc(); //AD转换函数
void change(); //比较调整输出函数
void init(); //显示值赋值函数
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_0=P3^0;
sbit P3_1=P3^1;
sbit P3_2=P3^2;
sbit wr=P3^3;
sbit intr=P3^6;
sbit rd=P3^7;
uchar var=0;
int var2;
uchar num,out=0;
void display()
{
P3_0=1;
P0=table[dis[0]];
delay(1);
P3_0=0;
P3_1=1;
P0=table[dis[1]];
delay(1);
P3_1=0;
P3_2=1;
P0=table0[dis[2]];
delay(1);
P3_2=0;
}
void init()
{
var2=var*1.95;
dis[0]=var2%10; //个位
dis[1]=var2/10%10; //十位
dis[2]=var2/100%10; //百位
}
void main()
{
P2=0;
var=200; //预设初始值
P3_0=0;
P3_1=0;
P3_2=0;
init();
if(P3_4==1 && P3_5==1)
display();
while(1)
{
adc();
change();
if (P3_4==0)
{
add();
while(!P3_4) ;
}
if(P3_5==0)
{
reduce();
while(!P3_5);
}
if(P3_4==1 && P3_5==1)
display();
}
}
void add()
{ var++;
delay(1);
init();
}
void reduce()
{ var--;
if(var==0xff)
{var=0;}
delay(1);
init();
}
void adc()
{
wr=1;
wr=0;
delay(10);
wr=1;
while(intr==0)
{}
rd=0;
delay(10);
num=P1;
}
void change()
{
if(var<num)
{ if((num-var)>=10)
{ if(out>=10)
{ out=out-10;
P2=out;
}
}
else if (out>=1)
{ out--;
P2=out;
}
}
if(var>num)
{ if( (var-num)>=10)
{ if(out<=245)
{ out=out+10;
P2=out;
}
}
else if (out<=254)
{out++;
P2=out;
}
}
}
void delay (uint t)
{ uint i,j;
for (i=0;i<t;i++)
for (j=0;j<120;j++)
;
}
运行结果图:
运行结果不复制不过来,有什么问题可以找我,我再给你发到邮箱什么的都可以。
/**************************************************************************
THE REAL TIMER DS1302 DRIVER LIB
COPYRIGHT (c) 2005 BY JJJ.
-- ALL RIGHTS RESERVED --
File Name: DS1302.h
Author: Jiang Jian Jun
Created: 2003/7/21
Modified: NO
Revision: 1.0
***************************************************************************/
#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 地址的宏
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 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
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,0x10);
else
Write1302(0x8E,0x00);
}
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->DateString[8] = '\0';
}
void Initial_DS1302(void)
{
unsigned char Second=Read1302(DS1302_SECOND);
if(Second&0x80)
DS1302_SetTime(DS1302_SECOND,0);
}
/********************************************************************************
void BurstWrite1302(unsigned char *pWClock) //往DS1302写入时钟数据(多字节方式)
{
unsigned char i;
Write1302(0x8e,0x00); // 控制命令,WP=0,写操作?
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(0xbe); // 0xbe:时钟多字节写命令
for (i = 8; i>0; i--) //8Byte = 7Byte 时钟数据 + 1Byte 控制
{
DS1302InputByte(*pWClock); // 写1Byte数据
pWClock++;
}
DS1302_CLK = 1;
DS1302_RST = 0;
}
void BurstRead1302(unsigned char *pRClock) //读取DS1302时钟数据(时钟多字节方式)
{
unsigned char i;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(0xbf); // 0xbf:时钟多字节读命令
for (i=8; i>0; i--)
{
*pRClock = DS1302OutputByte(); // 读1Byte数据
pRClock++;
}
DS1302_CLK = 1;
DS1302_RST = 0;
}
void DS1302_TimeStop(bit flag) // 是否将时钟停止
{
unsigned char Data;
Data=Read1302(DS1302_SECOND);
DS1302_SetProtect(0);
if(flag)
Write1302(DS1302_SECOND, Data|0x80);
else
Write1302(DS1302_SECOND, Data&0x7F);
}
********************************************************************************/
#endif
以下是头文件:
/**************************************************************************
THE 1602 CHAR LCD LIB
COPYRIGHT (c) 2005 BY JJJ.
-- ALL RIGHTS RESERVED --
File Name: LCD.h
Author: Jiang Jian Jun
Created: 2005/4/3
Modified: NO
Revision: 1.0
***************************************************************************/
#ifndef LCD_CHAR_1602_2005_4_9
#define LCD_CHAR_1602_2005_4_9
#include <intrins.h>
//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_();
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
如果条是不成功,留个地址,我把整个工程都发给你!