STC12C2052 and LCD1602 LCD screen those things


1. Introduction

  In order to further understand the STC series of single-chip microcomputers, we will learn from the 1602 LCD display case of Du Yang's studio. This article introduces the reproduction of its 1602 LCD screen clock source program.
Experimental result graph

2. Hardware preparation

1. List of components

Product name model Quantity
Single chip microcomputer STC12C2052 1
Display screen LCD1602 1
USB to TTL CH340G 1
Potentiometer B10K 1
Breadboard MB-102 1
Crystal oscillator 12MHZ 1
capacitance 30pf 2

2. Pin wiring

Insert picture description here
  The wiring method is slightly different from the above picture, in fact, a potentiometer is added to the V0 port to control the gray scale of the screen.

STC12C2052 LCD1602 Potentiometer
P1.0—P1.7 D0—D7 *
GND LED_K *
VCC VCC *
INT0/P3.2 RS *
INT1/P3.3 RW *
P3.4 E *
* VSS 1
* V0 2

Three, software preparation

  At present, the clock implemented by this program is fixed. If you want to further change it to real-time, you need to add another DS1302 clock chip for assistance, or add the compilation date and time to keil by using the _DATE_ and _TIME_ macros. In the C51 program, but this method has not been verified yet, and interested friends can verify and communicate by themselves.

/********************************************************************************************
程序名:    1602液晶屏时钟程序
编写人:    杜洋 
编写时间:  2009年7月6日
硬件支持:  LCD1602液晶屏  STC12C2052 外部12MHZ晶振 
说明备注:    使用2402液晶屏程序,与1602液晶屏程序完全兼容
/********************************************************************************************/
#include <AT89X52.h>						// 包含头文件 //
#include <REGX52.H>

/********************************************************************************************/
typedef unsigned char      uint8;          // 无符号8位整型变量 //

/********************************************************************************************
// 引脚定义 // (使用者根据实际更改)
/********************************************************************************************/
#define		LCM2402_DB0_DB7		P1			// 定义LCM2402的数据总线
sbit LCM2402_RS   = P3 ^ 2;					// 定义LCM2402的RS控制线
sbit LCM2402_RW   = P3 ^ 3;					// 定义LCM2402的RW控制线
sbit LCM2402_E    = P3 ^ 4;					// 定义LCM2402的E控制线
sbit LCM2402_Busy = P1 ^ 7;					// 定义LCM2402的测忙线(与LCM2402_DB0_DB7关联)
data unsigned char TIME_DD,TIME_MO,TIME_YY,TIME_WW,TIME_HH,TIME_MM,TIME_SS;//设置日、月、年、周、时、分、秒和温度存放区
data bit DAY_BIT = 0;//天数增加标志位(用于日期进位的启动)
data unsigned char DIS_BIT = 0; //多种信息的切换显示
data unsigned char cou  = 0;     // 软计数器,对10ms时基信号累加到1s 
/********************************************************************************************
// 定义LCM2402指令集 // (详细请见技术手册)
/********************************************************************************************/
#define			CMD_clear		0x01             // 清除屏幕
#define			CMD_back		0x02             // DDRAM回零位
#define			CMD_dec1		0x04             // 读入后AC(指针)减1,向左写
#define			CMD_add1		0x06             // 读入后AC(指针)加1,向右写
#define			CMD_dis_gb1		0x0f             // 开显示_开光标_开光标闪烁
#define			CMD_dis_gb2		0x0e             // 开显示_开光标_关光标闪烁
#define			CMD_dis_gb3		0x0c             // 开显示_关光标_关光标闪烁
#define			CMD_OFF_dis		0x08             // 关显示_关光标_关光标闪烁
#define			CMD_set82		0x38             // 8位总线_2行显示
#define			CMD_set81		0x30             // 8位总线_1行显示(上边行)
#define			CMD_set42		0x28             // 4位总线_2行显示
#define			CMD_set41		0x20             // 4位总线_1行显示(上边行)
#define			lin_1			0x80             // 4位总线_1行显示(上边行)
#define			lin_2			0xc0             // 4位总线_1行显示(上边行)

/********************************************************************************************
// 读LCM忙程序 [底层协议] // (所有底层协议都无需关注)
// LCM2402测忙,若LCM2402处于忙状态,本函数将等待至非忙状态 //
/********************************************************************************************/
void LCM2402_TestBusy(void){
    
    
   	LCM2402_DB0_DB7 = 0xff;		//设备读状态
   	LCM2402_RS = 0;
   	LCM2402_RW = 1;
   	LCM2402_E = 1;
   	while(LCM2402_Busy);		//等待LCM不忙
   	LCM2402_E = 0;				//
}
/********************************************************************************************
// 写指令程序 //
// 向LCM2402写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCM2402_WriteCMD(uint8 LCM2402_command) {
    
     
  	LCM2402_TestBusy();
  	LCM2402_DB0_DB7 = LCM2402_command;
  	LCM2402_RS = 0;
  	LCM2402_RW = 0;
  	LCM2402_E = 1;
  	LCM2402_E = 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCM2402写数据 //
/********************************************************************************************/
void LCM2402_WriteData(uint8 LCM2402_data){
    
     
    LCM2402_TestBusy();
	LCM2402_DB0_DB7 = LCM2402_data;
  	LCM2402_RS = 1;
  	LCM2402_RW = 0;
  	LCM2402_E = 1;
  	LCM2402_E = 0;
}
/********************************************************************************************
// 打印字符串程序 // (本函数调用指针函数)
// 向LCM发送一个字符串,长度48字符之内 
// 第一行位置 0x00~0x17  第二行位置 0x40~0x57 
// 应用举例:print(0x80,"doyoung.net"); //在第一行第一位处从左向右打印doyoung.net字符串
/********************************************************************************************/
void print(uint8 a,uint8 *str){
    
    
	LCM2402_WriteCMD(a | 0x80);
	while(*str != '\0'){
    
    
		LCM2402_WriteData(*str++);
	}
	*str = 0;
}
/********************************************************************************************
// 打印单字符程序 // 
// 第一行位置 0x00~0x17  第二行位置 0x40~0x57 
// 向LCM发送一个字符,以十六进制(0x00)表示 
// 应用举例:print(0xc0,0x30); //在第二行第一位处打印字符“0”
/********************************************************************************************/
void print2(uint8 a,uint8 t){
    
    
		LCM2402_WriteCMD(a | 0x80);
		LCM2402_WriteData(t);
}
/********************************************************************************************
// 定义小汉字 //
// 可写入8个自字义字符,写入后可用其CGRAM代码直接提取显示。
// 字符定义方法请参考技术手册 
/********************************************************************************************/
uint8 code Xword[]={
    
    
    0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00,        //℃,代码 0x00
    0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,        //一,代码 0x01
    0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00,        //二,代码 0x02
    0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00,        //三,代码 0x03
    0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00,        //四,代码 0x04
    0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00,        //五,代码 0x05
    0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00,        //六,代码 0x06
    0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00,        //日,代码 0x07
};
void CgramWrite(void) {
    
    	// 装入CGRAM //
    uint8 i;
	LCM2402_WriteCMD(0x06);			// CGRAM地址自动加1
	LCM2402_WriteCMD(0x40);			// CGRAM地址设为00处
    for(i=0;i<64;i++) {
    
    
    	LCM2402_WriteData(Xword[i]);// 按数组写入数据
    }
}
/********************************************************************************************
// LCM2402初始化 //(使用者可自定义,加 * 号程序行必须保留但可修改)
/********************************************************************************************/
void LCM2402_Init(void){
    
    
  	LCM2402_WriteCMD(CMD_set82);	//* 显示模式设置:显示2行,每个字符为5*7个像素
  	LCM2402_WriteCMD(CMD_clear);	//  显示清屏
  	LCM2402_WriteCMD(CMD_back);		//* 数据指针指向第1行第1个字符位置
  	LCM2402_WriteCMD(CMD_add1);		//  显示光标移动设置:文字不动,光标右移
  	LCM2402_WriteCMD(CMD_dis_gb3); 	//  显示开及光标设置:显示开,光标开,闪烁开
	CgramWrite();					//  向CGRAM写入自定义字符
}
/********************************************************************************************/
//			以上是LCM2402驱动程序			//
/*********************************************************************************************/

/*********************************************************************************************/
bit IsLeapYear(void){
    
        //计算本年是否是润年 
	unsigned int a;
	a = 2000+TIME_YY;//加2000表示成完整的年
	if((a%4==0 && a%100!=0)||(a%400==0)){
    
     //润年的计算公式
			return 1;//是润年返回1 
		}else{
    
     
 			return 0;//不是润年返回0 
		}
} 
/**********************************************************************************************/	
void month_day(void){
    
      
	unsigned char mon_day[]={
    
    31,28,31,30,31,30,31,31,30,31,30,31};
	TIME_DD++;//天加1
	TIME_WW++;//星期值加1
	if(TIME_WW > 7){
    
    
		TIME_WW = 1;//时期值限定
	}
	if(TIME_DD > mon_day[TIME_MO-1]){
    
    //检查天是否大于当月的最大值
		if(IsLeapYear()&&TIME_MO==2){
    
     //计算本月是否是润年的2月份 
			TIME_DD = 29;//如果是润年又是2月,则天为29
		}else{
    
    
			TIME_DD = 1; //否则就等于1
			TIME_MO++;//月加1
			if(TIME_MO > 12){
    
    
				TIME_MO = 1; //如果月大于12则月等于1
				TIME_YY++;//年加1 (公历年无限积加)
			}
		}
	}
} 
/**********************************************************************************************/	
void init (void){
    
     //上电初始化
	TMOD = 0x11;         // 定时/计数器0,1工作于方式1   
    TH0 = 0x3c;          // 预置产生50ms时基信号   
    TL0 = 0xb0;   
    EA = 1;              // 开总中断   
    ET0 = 1;             // 定时/计数器0允许中断   
    TR0 = 1;             // 开闭定时/计数器0   

	TIME_DD = 22; //时间在首次使用的值,之后会在EEPROM自动记录上一天的值
	TIME_MO	= 3; //初始时间:2009年5月18日周一,20时13分40秒
	TIME_YY = 21;
	TIME_WW = 5;
	TIME_HH	= 0;
	TIME_MM = 0;
	TIME_SS = 0;
}
/********************************************************************************************
//显示项目 时间部分 在第一行全行显示时间
*********************************************************************************************/    
void RealTime_Display(void){
    
    
	    print(0x80,"20");
	    print2(0x82,TIME_YY/10+0x30);
	    print2(0x83,TIME_YY%10+0x30);
		print(0x84,"/");            // 显示年
		//
	    print2(0x85,TIME_MO/10+0x30);
	    print2(0x86,TIME_MO%10+0x30);
		print(0x87,"/");            // 显示月
		//
	    print2(0x88,TIME_DD/10+0x30);
	    print2(0x89,TIME_DD%10+0x30);

		print(0x8b,"[");            // 显示[
		print2(0x8c,TIME_WW%10); //星期
		print(0x8d,"]");            // 显示]

	    print2(0x40,TIME_HH/10+0x30);//小时
	    print2(0x41,TIME_HH%10+0x30);
		print(0x42,":");            // 显示cgram第一个字模":"
		//
	    print2(0x43,TIME_MM/10+0x30);//分钟
	    print2(0x44,TIME_MM%10+0x30);
		print(0x45,".");            // 显示cgram第一个字模"."
		//
	    print2(0x46,TIME_SS/10+0x30);//秒
	    print2(0x47,TIME_SS%10+0x30);
		//
}
/********************************************************************************************/
// 测试用函数 //
void main (void){
    
    
	init();//初始化                           
	LCM2402_Init();//LCM2402初始化                           
	while(1){
    
     //主线程// 
		RealTime_Display();    	
		//print(0x80,"DoYoung Studio"); //在第一行第一位处从左向右打印doyoung.net字符串
		//print(0x40,"www.DoYoung.net"); //在第一行第一位处从左向右打印doyoung.net字符串

		if(DAY_BIT == 1){
    
     //检查天数是否更新,是则计算公历
			month_day();//计算公历日期	
			DAY_BIT = 0;//计算完成后将日期变更标志位置0
		}
	}
}
/********************************************************************************************/    
void tiem0(void) interrupt 1{
    
       // T/C0中断服务程序(产生50ms时基信号)   
    cou++;                      // 软计数器加1   
    if(cou > 19){
    
                     // 计数值到100(1s)   
        cou = 0;               // 软计数器清零   
        TIME_SS++;                 // 秒计数器加1(进位10ms*100=1s)   
        if(TIME_SS > 59){
    
              // 秒计数值到60   
           
            TIME_SS = 0;           // 秒计数器清零   
            TIME_MM++;             // 分计数器加1(进位60s=1m)  
            if(TIME_MM > 59){
    
          // 分计数到60   
                TIME_MM = 0;       // 分计数器清零   
                TIME_HH++;         // 时计数器加1(进位60m=1h)   
                if(TIME_HH > 23){
    
      // 时计数到23   
                    TIME_HH = 0;   // 时计数器清零
					DAY_BIT = 1;	//天增加标志位 
				}  
            }   
        }   
    }   
    TH0 = 0x3c;                // 重置定时常数   
    TL0 = 0xb0;   
}
/*********************************************************************************************/

/*************************************************************
* 杜洋工作室 DoYoung Studio
* 与电子爱好者同行 www.DoYoung.net
/*************************************************************/

Fourth, the problems encountered

1. The black block on the display covers the display content

  This is actually caused by the low bias voltage of the LCD display. You only need to connect a potentiometer to the V0 port for adjustment. It is also possible to add a grounding resistance, but it is not certain how much resistance is suitable, so it is more convenient to connect a potentiometer. .
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_41071754/article/details/115081967