Proteus仿真STC15单片机 + DS1302 + LCD1602显示时间

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Proteus仿真STC15单片机 + DS1302 + LCD1602显示时间相关的知识,希望对你有一定的参考价值。

【Proteus仿真】STC15单片机 + DS1302 + LCD1602显示时间


  • Proteus仿真

本来想通过轮询方式读取DS1302秒时间的变化来刷新LCD1602显示的,但是这种方式在STC15上仿真会出现DS1302不走秒的情况,读DS1302时并没有开启保护。只能通过在主循环while里面添加一个1秒钟强制读取一次。好处是可以不用占用太多的cpu时间。

相关函数说明

  • 延时函数:由定时器0定时1MS作为时基,一般时间的延时基本够用。
void  delay_ms(unsigned long ms)

	unsigned long	temp = sysRunmillis ;
    while(sysRunmillis - temp < ms );

  • 预留蜂鸣器报警函数,在使用设定报警时间时可以启用。
void Buzzer_Di(void)
	Buzzer = 0;
	delay_ms(3);
	Buzzer = 1;
	delay_ms(3);

主程序代码


/*************	本程序功能说明	**************

驱动LCD1602字符屏.

显示效果为:  DS1302 + LCD1602显示时间

******************************************/
#include	"STC15Fxxxx.H"
#include "DS1302.h"

#define T1MS (65536-MAIN_Fosc/12/1000)   //12T模式1ms定时
#define  interval  1000 //设置延时时间间隔
/*************	本地变量声明	**************/
static volatile unsigned long sysRunmillis = 0;	//系统运行时间计数,保存单片机从上电复位以来运行的时间,单位是毫秒。该数值由定时器T0的中断响应子函数更新
unsigned long previousMillis = 0;
unsigned char KEY_NUM = 0;
bit Flag_KEY_Set = 0;
unsigned char KEY2_Count = 0;
sbit Buzzer = P3^7;


void Timer0Init(void);		//1毫秒@12.000MHz
void	DisplayRTC(void);
void  delay_ms(unsigned long ms);
void	Initialize_LCD(void);
void	Write_AC(u8 hang,u8 lie);
void	Write_DIS_Data(u8 DIS_Data);
void	ClearLine(u8 row);
u8		BIN_ASCII(u8 tmp);
void 	PutString(u8 row, u8 column, u8 *puts);
void	WriteChar(u8 row, u8 column, u8 dat);
void Buzzer_Di(void);

//========================================================================
// 函数: void main(void)
// 描述: 主函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void main(void)

	unsigned long currentMillis;//当前时间
	P0M1 = 0;	P0M0 = 0;	//设置为准双向口
	P1M1 = 0;	P1M0 = 0;	//设置为准双向口
	P2M1 = 0;	P2M0 = 0;	//设置为准双向口
	P3M1 = 0;	P3M0 = 0;	//设置为准双向口
	P4M1 = 0;	P4M0 = 0;	//设置为准双向口
	P5M1 = 0;	P5M0 = 0;	//设置为准双向口
	P6M1 = 0;	P6M0 = 0;	//设置为准双向口
	P7M1 = 0;	P7M0 = 0;	//设置为准双向口
	Timer0Init();	//1毫秒@12.000MHz
	Initialize_LCD();
	ClearLine(0);
	ClearLine(1);
	DS1302_Init();									//初始化DS1302
	delay_ms(500);
	DS1302_GetTime(&DS1302Buffer);//获取当前RTCC值
	while(1)
	
		DisplayRTC();				//显示实时时钟	
		currentMillis = sysRunmillis;	
	if (currentMillis - previousMillis  >= interval)//每隔1秒翻转一次
    currentMillis = sysRunmillis;
			DS1302_GetTime(&DS1302Buffer);//获取当前RTCC值
		
//	if(Flag_Time_Refresh)			//数据更新时才刷新LCD
//		
//			Flag_Time_Refresh = 0;		
//			DisplayRTC();				//显示实时时钟		
//		
//			DS1302_GetTime(&DS1302Buffer);//获取当前RTCC值
	
 

void Timer0Init(void)		//1毫秒@12.000MHz

	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = T1MS ;		//设置定时初始值
	TH0 = T1MS >>8;		//设置定时初始值
//	TL0 = 0x18;		//设置定时初始值
//	TH0 = 0xFC;		//设置定时初始值
	
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;     //enable timer0 interrupt
  EA = 1;      //open global interrupt switch


/* Timer0 interrupt routine */
void tm0_isr() interrupt 1

//	TL0 = 0x18;		//设置定时初始值
//	TH0 = 0xFC;		//设置定时初始值
    TL0 = T1MS;                     //reload timer0 low byte
    TH0 = T1MS >> 8;                //reload timer0 high byte
	sysRunmillis ++;



//========================================================================
// 函数: void  delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void  delay_ms(unsigned long ms)

	unsigned long	temp = sysRunmillis ;
    while(sysRunmillis - temp < ms );
//     unsigned int i;
//	 do
//	      i = MAIN_Fosc / 13000;
//		  while(--i)	;   //14T per loop
//     while(--ms);


//****************************************************
//显示实时时钟
//****************************************************
void	DisplayRTC(void)

	unsigned char *weeklist[7]="Sun","Mon","Tue","Wed","Thu","Fri","Sat";
	PutString(0,0,"20");
	WriteChar(0,2,DS1302Buffer.Year/10 + 0x30);	 //显示Year高位
	WriteChar(0,3,DS1302Buffer.Year%10 + 0x30);	 //显示Year低位
	WriteChar(0,4,'-');
	WriteChar(0,5,DS1302Buffer.Month/10 + 0x30);	 //显示Month高位
	WriteChar(0,6,DS1302Buffer.Month%10 + 0x30);	 //显示Month低位
	WriteChar(0,7,'-');
	WriteChar(0,8,DS1302Buffer.Day/10 + 0x30);		 //显示Day高位
	WriteChar(0,9,DS1302Buffer.Day%10 + 0x30);		 //显示Day低位

	PutString(0,13,weeklist[DS1302Buffer.Week -1]);
	if(DS1302Buffer.Hour > 9)
	WriteChar(1,0,DS1302Buffer.Hour/10 + 0x30);	 //显示Hour高位
	else			WriteChar(1,0,  0x30);
	WriteChar(1,1,DS1302Buffer.Hour%10 + 0x30);	 //显示Hour低位
	WriteChar(1,2,':');
	WriteChar(1,3,DS1302Buffer.Minute/10 + 0x30);	 //显示Minute高位
	WriteChar(1,4,DS1302Buffer.Minute%10 + 0x30);	 //显示Minute低位
	WriteChar(1,5,':');
	WriteChar(1,6,DS1302Buffer.Second/10 + 0x30);	 //显示Second高位
	WriteChar(1,7,DS1302Buffer.Second%10 + 0x30);	 //显示Second低位	



/************* LCD1602相关程序	*****************************************************/
//8位数据访问方式	LCD1602		标准程序	梁工编写	2014-2-21

#define LineLength	16		//16x2

/*************	Pin define	*****************************************************/

sfr		LCD_BUS = 0x80;	//P0--0x80, P1--0x90, P2--0xA0, P3--0xB0

sbit	LCD_B7  = LCD_BUS^7;	//D7 -- Pin 14		LED- -- Pin 16 
sbit	LCD_B6  = LCD_BUS^6;	//D6 -- Pin 13		LED+ -- Pin 15
sbit	LCD_B5  = LCD_BUS^5;	//D5 -- Pin 12		Vo   -- Pin 3
sbit	LCD_B4  = LCD_BUS^4;	//D4 -- Pin 11		VDD  -- Pin 2
sbit	LCD_B3  = LCD_BUS^3;	//D3 -- Pin 10		VSS  -- Pin 1
sbit	LCD_B2  = LCD_BUS^2;	//D2 -- Pin  9
sbit	LCD_B1  = LCD_BUS^1;	//D1 -- Pin  8
sbit	LCD_B0  = LCD_BUS^0;	//D0 -- Pin  7

sbit	LCD_ENA	= P2^2;	//Pin 6
sbit	LCD_RW	= P2^1;	//Pin 5	//LCD_RS   R/W   DB7--DB0        FOUNCTION
sbit	LCD_RS	= P2^0;	//Pin 4	//	0		0	  INPUT      write the command to LCD model
								//	0		1     OUTPUT     read BF and AC pointer from LCD model
								//	1		0     INPUT      write the data to LCD  model
								//	1		1     OUTPUT     read the data from LCD model
/*
total 2 lines, 16x2= 32
first line address:  0~15
second line address: 64~79

*/

#define C_CLEAR			0x01		//clear LCD
#define C_HOME 			0x02		//cursor go home
#define C_CUR_L			0x04		//cursor shift left after input
#define C_RIGHT			0x05		//picture shift right after input
#define C_CUR_R			0x06		//cursor shift right after input
#define C_LEFT 			0x07		//picture shift left after input
#define C_OFF  			0x08		//turn off LCD
#define C_ON   			0x0C		//turn on  LCD
#define C_FLASH			0x0D		//turn on  LCD, flash 
#define C_CURSOR		0x0E		//turn on  LCD and cursor
#define C_FLASH_ALL		0x0F		//turn on  LCD and cursor, flash
#define C_CURSOR_LEFT	0x10		//single cursor shift left
#define C_CURSOR_RIGHT	0x10		//single cursor shift right
#define C_PICTURE_LEFT	0x10		//single picture shift left
#define C_PICTURE_RIGHT	0x10		//single picture shift right
#define C_BIT8			0x30		//set the data is 8 bits
#define C_BIT4			0x20		//set the data is 4 bits
#define C_L1DOT7		0x30		//8 bits,one line 5*7  dots
#define C_L1DOT10		0x34		//8 bits,one line 5*10 dots
#define C_L2DOT7		0x38		//8 bits,tow lines 5*7 dots
#define C_4bitL2DOT7	0x28		//4 bits,tow lines 5*7 dots
#define C_CGADDRESS0	0x40		//CGRAM address0 (addr=40H+x)
#define C_DDADDRESS0	0x80		//DDRAM address0 (addr=80H+x)


#define	LCD_DelayNop()	NOP(15)

#define		LCD_BusData(dat)	LCD_BUS = dat


//========================================================================
// 函数: void	CheckBusy(void)
// 描述: 检测忙函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void	CheckBusy(void)

	u16	i;
	for(i=0; i<5000; i++)	if(!LCD_B7)	break;		//check the LCD busy or not. With time out
//	while(LCD_B7);			//check the LCD busy or not. Without time out


//========================================================================
// 函数: void IniSendCMD(u8 cmd)
// 描述: 初始化写命令(不检测忙)
// 参数: cmd: 要写的命令.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void IniSendCMD(u8 cmd)

	LCD_RW = 0;
	LCD_BusData(cmd);
	LCD_DelayNop();
	LCD_ENA = 1;
	LCD_DelayNop();
	LCD_ENA = 0;
	LCD_BusData(0xff);


//========================================================================
// 函数: void Write_CMD(u8 cmd)
// 描述: 写命令(检测忙)
// 参数: cmd: 要写的命令.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void Write_CMD(u8 cmd)

	LCD_RS  = 0;
	LCD_RW = 1;
	LCD_BusData(0xff);
	LCD_DelayNop();
	LCD_ENA = 1;
	CheckBusy();			//check the LCD busy or not.
	LCD_ENA = 0;
	LCD_RW = 0;
	
	LCD_BusData(cmd);
	LCD_DelayNop();
	LCD_ENA = 1;
	LCD_DelayNop();
	LCD_ENA = 0;
	LCD_BusData(0xff);


//========================================================================
// 函数: void Write_DIS_Data(u8 dat)
// 描述: 写显示数据(检测忙)
// 参数: dat: 要写的数据.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void Write_DIS_Data(u8 dat)

	LCD_RS = 0;
	LCD_RW = 1;

	LCD_BusData(0xff);
	LCD_DelayNop();
	LCD_ENA = 1;
	CheckBusy();			//check the LCD busy or not.
	LCD_ENA = 0;
	LCD_RW = 0;
	LCD_RS  = 1;

	LCD_BusData(dat);
	LCD_DelayNop();
	LCD_ENA = 1;
	LCD_DelayNop();
	LCD_ENA = 0;
	LCD_BusData(0xff);



//========================================================================
// 函数: void Initialize_LCD(void)
// 描述: 初始化函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void Initialize_LCD(void)

	LCD_ENA = 0;
	LCD_RS  = 0;
	LCD_RW = 0;

	delay_ms(100);
	IniSendCMD(C_BIT8);		//set the data is 8 bits

	delay_ms(10);
	Write_CMD(C_L2DOT7);		//tow lines 5*7 dots

	delay_ms(6);
	Write_CMD(C_CLEAR);		//clear LCD RAM
	Write_CMD(C_CUR_R);		//Curror Shift Right
	Write_CMD(C_ON);		//turn on  LCD




//========================================================================
// 函数: void ClearLine(u8 row)
// 描述: 清除1行
// 参数: row: 行(0或1)
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void ClearLine(u8 row)

	u8 i;
	Write_CMD(((row & 1) << 6) | 0x80);
	for(i=0; i<LineLength; i++)	Write_DIS_Data(' ');


//========================================================================
// 函数: void	WriteChar(u8 row, u8 column, u8 dat)
// 描述: 指定行、列和字符, 写一个字符
// 参数: row: 行(0或1),  column: 第几个字符(0~15),  dat: 要写的字符.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//==============================================================&#

以上是关于Proteus仿真STC15单片机 + DS1302 + LCD1602显示时间的主要内容,如果未能解决你的问题,请参考以下文章

Proteus8.12无法仿真STC15系列单片机解决办法

STC15单片机跑流水灯Proteus仿真

Proteus仿真基于STC15单片机简易数码管定时器时钟

STC15单片机可设置倒计时(0~9999)报警器+Proteus仿真

Proteus仿真51单片机+DS1302+LCD1602+按键时间调整

Proteus仿真STC51单片机流水灯注意事项