基于AT89C52单片机的1602液晶显示程序
1602液晶显示
1.keyscan.c
2.boardinit.c
3.delay.c
4.clock.c
5.74hc595.c
6.1602led.c
#include<reg52.h>
#include "boardinit.h"
#include "keyscan.h"
#include "1602led.h"
#include "delay.h"
#include "74hc595.h"
#include "clock.h"
#define uchar unsigned char
#define uint unsigned int
uchar time=0;
uchar shi,fen,miao;
void write_data_160238(uchar data_1602);
void main()
{
TMOD=0x10;
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;
ET1=1;
TR1=1;
EA=1;
boardinit(); //板卡初始化
lcdinit_1602(); //1602初始化
Disp_1602(1,1," 2019-05-20 ",16);
Disp_1602(1,2," 00:00:00 ",16);
while(1)
{
keyscan();
clock();
}
}
void zd() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
time++;
}
##### keyscan.c
#include <reg52.h>
#include "keyscan.h"
#include "74hc595.h"
#include "1602led.h"
#include "delay.h"
sbit s1 = P3^7; //设置按键
sbit s2 = P3^4; //时间- 按键
sbit s3 = P3^5; //时间+ 按键
sbit s4 = P3^0;
uchar num,moshi;
void keyscan()
{
s4=0;
if(s1==0)
{
delay(1);
if(s1==0)
{
while(!s1);
moshi++;
if(moshi==1)
{
write_order_1602(0x80+0x40+0x0b);
write_order_1602(0x0f);
TR1=0;
}
if(moshi==2)
{
write_order_1602(0x0f);
write_order_1602(0x80+0x40+0x08);
TR1=0;
}
if(moshi==3)
{
write_order_1602(0x0f);
write_order_1602(0x80+0x40+0x05);
TR1=0;
}
if(moshi==4)
{
write_order_1602(0x0c);
TR1=1;
if(moshi==4)
{
moshi=0;
}
}
}
}
if (moshi==1)
{
if(s2==0)
{
delay(1);
if(s2==0)
{
while(!s2);
miao++;
if(miao==60)
{
miao=0;
}
write_twoline_1602(11,miao);
write_order_1602(0x80+0x40+0x0b);
}
}
if(s3==0)
{
delay(1);
if(s3==0)
{
while(!s3);
miao--;
if(miao==(-1))
{
miao=59;
}
write_twoline_1602(11,miao);
write_order_1602(0x80+0x40+0x0b);
}
}
}
if (moshi==2)
{
if(s2==0)
{
delay(1);
if(s2==0)
{
while(!s2);
fen++;
if(fen==60)
{
fen=0;
}
write_twoline_1602(8,fen);
write_order_1602(0x80+0x40+0x08);
}
}
if(s3==0)
{
delay(1);
if(s3==0)
{
while(!s3);
fen--;
if(fen==(-1))
{
fen=59;
}
write_twoline_1602(8,fen);
write_order_1602(0x80+0x40+0x08);
}
}
}
if (moshi==3)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
shi++;
if(shi==24)
{
shi=0;
}
write_twoline_1602(5,shi);
write_order_1602(0x80+0x40+0x05);
}
}
if(s3==0)
{
delay(1);
if(s3==0)
{
while(!s3);
shi--;
if(shi==(-1))
{
shi=24;
}
write_twoline_1602(5,shi);
write_order_1602(0x80+0x40+0x05);
}
}
}
}
##### boardinit.c
/*晶振11.0592MHz
*/
#include <reg52.h>
#include "74hc595.h"
#include "boardinit.h"
sbit duanxuan=P2^5; // 数码管,的段选使能,1 通 0关
sbit weixuan=P2^6; // 数码管,的位选使能,1 通 0关
void boardinit()
{
duanxuan=1; // 数码管,的段选使能,1 通 0关
weixuan=1; //数码管,的位选使能,1 通 0关
P0=0x00; //P0口送清零,关LED数码管的必要数据准备。
duanxuan=0; // 数码管,的段选使能,1 通 0关
weixuan=0; //数码管,的位选使能,1 通 0关
write_byte_74hc595(0x40); //选通8位发光二极管控制芯片u6(74HC573)锁存器的使能端
P1=0xff; //P1口送全1,关8位发光二极管的必要数据准备。//写完此句理论上8个发光二级管都会熄灭,因74HC595数据口复用了P1.0故P1.0的二极管可能不能被熄灭。
write_byte_74hc595(0x00); //关闭8位发光二极管控制芯片u6(74HC573)锁存器的使能端,把P1口数据保存(既关发光二极管)。
}
##### delay.c
#include "delay.h"
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*
void delay_ds18b20(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<1;j++);
}*/
##### clock.c
#include "1602led.h"
#include "clock.h"
void clock()
{
if(time==19)
{
time=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_twoline_1602(5,shi);
}
write_twoline_1602(8,fen);
}
write_twoline_1602(11,miao);
}
}
##### 74hc595.c
#include <reg52.h>
#include "74hc595.h"
#include "delay.h"
sbit data_595si =P1^0; //595数据输入口
sbit clk_595srck =P1^4; //595数据写进移位寄存器时钟输入口
sbit e_595rck =P2^3; //595移位寄存器,数据送输出的时钟
void write_byte_74hc595(uchar dat) //74hc164芯片写一字节数据函数
{
uchar i;
e_595rck=0; //给595RCK低电平
for(i=0;i<8;i++)
{
clk_595srck=0; //给595SRCK低电平
data_595si=(dat<<i)&0x80; //把我们要使用的数据进行左移处理,保证最终输出的数据与 我们 uchar dat 对应
clk_595srck=1; //给595SRCK高电平
}
e_595rck=1; //给595SRCK高电平,既把 DAT数据数据送到输出
data_595si=1;//因该数据口和别的电路共用,因此当74hc595使用完后,置“1”解除冲突
}
##### 1602led.c
#include <reg52.h>
#include "1602led.h"
#include "delay.h"
#include "74hc595.h"
sbit rs_1602=P2^5; //1602rs信号
sbit rw_1602=P2^6; //1602rw信号
sbit e=P2^4;
/*
void write_zl(uchar zl)
{
rs=0;
P0=zl;
delay(5);
e=1;
delay(5);
e=0;
}
void write_sj(uchar sj)
{
rs=1;
P0=sj;
delay(5);
e=1;
delay(5);
e=0;
} */
void write_order_1602(uchar order_data)
{
e=0;
rs_1602=0;
P0=order_data;
e=1;
delay(1);
e=0;
}
void write_data_1602(uchar data_1602)
{
e=0;
rs_1602=1;
P0=data_1602;
e=1;
delay(1);
e=0;
}
//功能:按指定位置显示一串字符
//输入:列显示地址x_1602(取值范围1-16) 行显示地址y_1602(取值范围1-2), 指定字符串指针*p_1602,要显示的字符个数count_1602 (取值范围1-16)
// 子函数使用例子: Disp_1602(1,1," TEMP: . ",16); //在1602第一行第一列写16个字符,既字符串数据
void Disp_1602(unsigned char x_1602,unsigned char y_1602,unsigned char *p_1602,unsigned char count_1602)
{
unsigned char i;
for(i=0;i<count_1602;i++)
{
if (1 == y_1602)
x_1602 |= 0x80; //当要显示第一行时地址码+0x80;
else x_1602 |= 0xC0; //在第二行显示是地址码+0xC0;
write_order_1602(x_1602-1);
write_data_1602(*p_1602);
x_1602++;
p_1602++;
}
}
void write_oneline_1602(uchar add_1602,uint date_1602)
{
uchar ge,shi;
shi=date_1602/10;
ge=date_1602%10;
write_order_1602(0x80+add_1602-1);
write_data_1602(0x30+shi);
write_order_1602(0x80+add_1602);
write_data_1602(0x30+ge);
//在1602上写时间函数 即在1602第二行指定位置上写显示
}
void write_twoline_1602(uchar add_1602,uint date_1602)
{
uchar shi,ge;
shi=date_1602/10;
ge=date_1602%10;
write_order_1602(0x80+0x40+add_1602-1);
write_data_1602(0x30+shi);
write_order_1602(0x80+0x40+add_1602);
write_data_1602(0x30+ge); //在1602上写时间函数 即在1602第二行指定位
}
void lcdinit_1602()
{
rw_1602=0;
e=0;
write_byte_74hc595(0X02);//关流水灯使能 关蜂鸣器 光继电器 打开1602背光打开
write_order_1602(0x38); //液晶设置不判忙模式
write_order_1602(0x0c); //开显示 不显示光标
write_order_1602(0x06); //当写一个字符是,地址指针加 1
write_order_1602(0x01); //显示清屏
}
这些项目的实现都通过本人亲自测试运行,也是自己学习中知识的一点一点积累,整理不易,希望能帮到大家,不足之处大家多多交流。
QQ:1678957377
邮箱:1678957377@qq.com