最简单的是
把这8行内容放到一个二维数组里,unsigned char Word[8][];
定义个变量char DisWordLine = 0;
然后主程序循环显示DisPlay(Word, DisWordLine);//显示函数
扫描按键,按上移时DisWordLine++,按下移时DisWordLine--;
复杂点的可以参考“一个占用内存极少的菜单系统的实现”
#include<reg52h>
#define uint unsigned int
#define uchar unsigned char
sbit ACC_7=ACC^7; //位寻址寄存器定义
sbit rs=P3^5;
sbit en=P3^4;
sbit sclk=P2^0;
sbit io=P2^5;
sbit ce=P2^4;
sbit wd18b20=P2^7;
sbit beep=P1^7;
sbit led=P3^7;
sbit s1=P1^0;
sbit s2=P1^1;
sbit s3=P1^2;
sbit s4=P1^3;
sbit s5=P1^4;
char yue,ri,shi,fen,miao;
uchar s1num=0,a=0; //a是s1num所对应的结果
uchar b=0x80+0x40;
uchar code table1[5]={
0x56,0x34,0x12,0x22,0x02};
void delay(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=114;j>0;j--);
}
void write_com(uchar com) //1602写命令
{
rs=0;
en=0;
P0=com;
delay(5);
en=1;
delay(5);
en=0;
}
void write_data(uchar dat) //1602写数据
{
rs=1;
en=0;
P0=dat;
delay(5);
en=1;
delay(5);
en=0;
}
void w1302(uchar dz,uchar sj) //1302写,先地址,后数据
{
uchar i,j;
ce=0;
sclk=0;
ce=1;
for(i=8;i>0;i--)
{
sclk=0;
j=dz;
io=(bit)(j&0x01);
dz>>=1;
sclk=1;
}
for(i=8;i>0;i--)
{
sclk=0;
j=sj;
io=(bit)(j&0x01);
dz>>=1;
sclk=1;
}
ce=0;
}
uchar r1302(uchar dz) //读取数据函数
{
uchar i,j,sj1,sj2;
ce=0;
sclk=0;
ce=1;
for(i=8;i>0;i--)
{
sclk=0;
j=dz;
io=(bit)(j&0x01);
dz>>=1;
sclk=1;
}
for(i=8;i>0;i--)
{
ACC_7=io;
sclk=1;
ACC>>=1;
sclk=0;
}
ce=0;
sj1=ACC;
sj2=sj1/16;
sj1=sj1%16;
sj1=sj1+sj210;
return(sj1);
}
void init() //初始化函数
{
uchar a,b=0x80;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01); //1602初始化
write_com(0x80+0x40+2);
write_data('/');
write_com(0x80+0x40+5);
write_data('-');
write_com(0x80+0x40+8);
write_data(':');
write_com(0x80+0x40+11);
write_data(':');
w1302(0x8e,0x00); //1302初始化
for(a=0;a<5;a++)
{
w1302(b,table1[a]);
b+=2;
}
w1302(0x8e,0x80);
}
void shuax(uchar dz1602,uchar dz1302) //刷新时间函数
{
uchar sj,shi,ge;
sj=dz1302;
shi=sj/10;
ge=sj%10;
write_com(dz1602);
write_data(0x30+shi);
write_data(0x30+ge);
}
void keyscan()
{
if(s1==0)
{
delay(5);
if(s1==0)
{
s1num++;
while(!s1);
switch(s1num)
{
case 1:a=1;
write_com(0x80);
write_data('y');
break;
case 2:s1num=0;
a=0;
write_com(0x0c);
write_com(0x80);
write_data(' ');
w1302(0x8e,0x00);
w1302(0x80,miao);
w1302(0x82,fen);
w1302(0x84,shi);
w1302(0x86,ri);
w1302(0x88,yue);
w1302(0x8e,0x80);
break;
}
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
b=b+3;
write_com(b);
write_com(0x0f);
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
b=b-3;
write_com(b);
write_com(0x0f);
}
}
if(s4==0)
{
delay(5);
if(s4==0)
{
while(!s4);
switch(b)
{
case 0x80+0x40:yue++;
if(yue==13)
yue=1;
w1302(0x8e,0x00);
w1302(0x88,yue);
w1302(0x8e,0x80);
shuax(0x80+0x40,yue);
break;
case 0x80+0x40+3:ri++;
if(ri==32)
ri=1;
w1302(0x8e,0x00);
w1302(0x86,ri);
w1302(0x8e,0x80);
shuax(0x80+0x40+3,ri);
break;
case 0x80+0x40+6:shi++;
if(shi==24)
shi=0;
w1302(0x8e,0x00);
w1302(0x84,shi);
w1302(0x8e,0x80);
shuax(0x80+0x40+6,shi);
break;
case 0x80+0x40+9:fen++;
if(fen==60)
fen=0;
w1302(0x8e,0x00);
w1302(0x82,fen);
w1302(0x8e,0x80);
shuax(0x80+0x40+9,fen);
break;
case 0x80+0x40+12:miao++;
if(miao==60)
miao=0;
w1302(0x8e,0x00);
w1302(0x80,miao);
w1302(0x8e,0x80);
shuax(0x80+0x40+12,miao);
break;
}
}
}
if(s5==0)
{
delay(5);
if(s5==0)
{
while(!s5);
switch(b)
{
case 0x80+0x40:yue--;
if(yue==0)
yue=12;
shuax(0x80+0x40,yue);
break;
case 0x80+0x40+3:ri--;
if(ri==0)
ri=31;
shuax(0x80+0x40+3,ri);
break;
case 0x80+0x40+6:shi--;
if(shi==-1)
shi=23;
shuax(0x80+0x40+6,shi);
break;
case 0x80+0x40+9:fen--;
if(fen==-1)
fen=59;
shuax(0x80+0x40+9,fen);
break;
case 0x80+0x40+12:miao--;
if(miao==-1)
miao=59;
shuax(0x80+0x40+12,miao);
break;
}
}
}
}
}
void main()
{
init();
while(1)
{
yue=r1302(0x89);
ri=r1302(0x87);
shi=r1302(0x85);
fen=r1302(0x83);
miao=r1302(0x81);
keyscan();
shuax(0x80+0x40,yue);
shuax(0x80+0x40+3,ri);
shuax(0x80+0x40+6,shi);
shuax(0x80+0x40+9,fen);
shuax(0x80+0x40+12,miao);
}
}
1602液晶的程序我有,要做数字锁的话其实用到液晶也不多。
因为你显示密码是时候不应该都是现实吗?
你只需把键盘写入的数据存在一个数组中,然后跟密码数组对比就好了。
还有就是值得注意的是数据类型问题。
输入的键值看你处理的方式而定,密码存放的格式,还有输出显示的是ascll码。注意转换。
下面附带一段51的1602LCD的C程序,自己仔细琢磨。
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
uchar table[16]="abcdefghijklmnyz";
uchar table1[16]="0123456789abcdef";
sbit lcden=P2^0;
sbit lcdrs=P2^1;
sbit dula=P2^6;
sbit wela=P2^7;
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{ wela=0;
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)
{ wela=0;
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);
write_com(0x0e);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void main()
{
init();
for(num=0;num<16;num++)
{
write_data(table[num]);
delay(20);
}
write_com(1);
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_data(table1[num]);
delay(20);
}
while(1);
}
会加的,减的也就不难了
设置计数器工作模式,然后反复读取计数器的值即可
TMOD=0X05;//定时器0为16位计数模式
TH0=0;
TL0=0;
TR0=1;//启动计数器
while(1)
{
delay_ms(10);//如果液晶显示,可加大延时时间,如果数码管显示,可不要此延时
//但数码管显示程序中间要有驻留延时
a=TH0256+TL0;//读取计数器的值
b=10000-a;//假设减1计数的初值为10000
if (key==0) display(1,0,a);//显示从第一行第一列起
else display(1,0,b);//也可改成display(2,0,b)
}
液晶显示函数附件里有,可干脆将else去掉,第一行递增显示,第二行递减显示
//液晶显示温度
#include "AT89X52H"
#define Ddata P0
sbit RS=P3^5; //命令数据控制端
sbit RW=P3^6; //读写选择端
sbit LCDE=P3^7; //液晶使能端
sbit DQ=P1^0; //ds18b20与单片机连接口
#define uchar unsigned char
#define uint unsigned int
unsigned char hour=0,min=0,sec=0; //定义初值
unsigned int count=0;
unsigned char line1[16]={"
temp: "}; //16个字符
unsigned char line2[16]={" time: 00:00:00"}; //16个字符
unsigned char tab[]={'0','1','2','3','4','5','6','7','8','9'}; //数组
uchar
data disdata[5];
uint tvalue; //温度值
uchar tflag; //温度正负标志
void time();
/lcd1602程序/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{
unsigned
int i,j;
for(i=0;i<ms;i++)
for(j=0;j<110;j++);
}
void delay5ms()//延时5毫秒(不够精确的)
{
unsigned
int i;
for (i=0;i<1000;i++);
}
void delay50us()
{
register
int i;
for (i=0;i<20;i++);
}
void delay()
{unsigned char m,n;
for(m=255;m>0;m--)
for(n=255;n>0;n--);
}
void wr_com(unsigned char comm)
//写控制字符程序 E=1 RS=0
RW=0//
{
LCDE=0; //使能端
RS=0;
//RS寄存器选择输入端,当RS=0;当进行写模块 *** 作,指向指令寄存器。
RW=0;
//当RS=1,无论是读 *** 作还是写 *** 作,都是指向数据寄存器。
LCDE=1;
Ddata=comm;
RS=0;
RW=0;
LCDE=0;
}
void wr_data(unsigned char dat)//当前位置写字符子程序:E=1 RS=1 RW=0
{
LCDE=0;
RS=0;
//RS寄存器选择输入端,当RS=0;当进行写模块 *** 作,指向指令寄存器。
RW=0;
//当RS=1,无论是读 *** 作还是写 *** 作,都是指向数据寄存器。
RS=1;
RW=0;
LCDE=1;
Ddata=dat; //将dat赋给P0口
LCDE=0;
RS=0;
RW=0;
}
unsigned char busycheck()//忙状态检查//
{
unsigned char i;
LCDE=0;
RS=0;
RW=0;
RS=0;
RW=1;
LCDE=1;
i=Ddata;
LCDE=0;
return(i);
}
void init()//初始化程序,必须按照产品的资料介绍的过程进行//
{
wr_com(0x38); //显示模式设置必须三次,不用检测忙信号
delay5ms();
wr_com(0x38);
delay5ms();
wr_com(0x38);
delay5ms();
wr_com(0x01); ///清屏
delay5ms();
busycheck();
wr_com(0x08);
delay5ms();
busycheck();
delay5ms();
wr_com(0x06); ///光标移动设置,写一个字符后地址指针加1
delay5ms();
busycheck();
delay50us();
wr_com(0x38); ////显示模式设置
delay50us();
busycheck();
delay50us();
wr_com(0x0c); /////显示开,不显示光标
delay50us();
busycheck();
delay50us();
wr_com(0x40); //set cgram address
delay50us();
delay50us(); //这些延时可用可不用//
}
void display()
{ unsigned char i;
wr_com(0x80); //set ram address
delay50us();
busycheck();
delay50us();
for(i=0;i<6;i++)
{wr_data(line1[i]); //display(6个字符)
delay50us();
busycheck();}
busycheck();
delay50us();
wr_com(0xc0); // 0xc0=0x80+0x40
delay50us();
busycheck();
delay50us();
for(i=0;i<16;i++)
{
wr_data(line2[i]); //display
delay50us();
busycheck();
}
}
/温度传感器ds1820程序/
void delay_18B20(unsigned int i)//延时1微秒
{
while(i--);
}
void ds1820rst()/ds1820复位/
{ unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd()/读数据/
{ unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--) //读一个字节的数据函数
{ DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80; //等价于 dat =
dat | 0x80,dat和0x80做“或”的运算, 结果是最高位置1,其它位保持不变。
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/写数据/
{unsigned char i=0;
for (i=8; i>0; i--)
{ DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
//右移一位
}
}read_temp()/读取温度值并转换/
{uchar a,b;
ds1820rst(); //ds1802/初始化程序
ds1820wr(0xcc);//跳过读序列号/
ds1820wr(0x44);//启动温度转换/
ds1820rst();
ds1820wr(0xcc);//跳过读序列号/
ds1820wr(0xbe);//读取温度/
a=ds1820rd(); //读低八位
b=ds1820rd(); //读高八位
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else //“&” 是逻辑与“|” 是逻辑或if(dat & 0x01):不管dat是什么数和0x01(00000001)做了“与”的运算后,最低位保持不变,其它位均为0如果dat的最低位为1,则表达式为真,就会执行if语句中的内容。如果dat最低位为0,则表达式为假,不执行if语句,执行if语句后的下一条语句。dat |= 0x80:等价于 dat = dat | 0x80,dat和0x80做“或”的运算,意思是最高位置1,其它位保持不变。
具体的可以去参考一下C语言的相关语法。
{tvalue=~tvalue+1;
tflag=1;
}
tvalue=tvalue(0625);//温度值扩大10倍,精确到1位小数
return(tvalue);
}
//
void ds1820disp()//温度值显示
{ uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位
if(tflag==0)
flagdat=0x20;//正温度不显示符号
else
flagdat=0x2d;//负温度显示负号:-
if(disdata[0]==0x30)
{disdata[0]=0x20;//如果百位为0,不显示
if(disdata[1]==0x30)
{disdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
wr_com(0x88);
wr_data(flagdat);//显示符号位
wr_com(0x89);
wr_data(disdata[0]);//显示百位
wr_com(0x8a);
wr_data(disdata[1]);//显示十位
wr_com(0x8b);
wr_data(disdata[2]);//显示个位
wr_com(0x8c);
wr_data(0x2e);//显示小数点
wr_com(0x8d);
wr_data(disdata[3]);//显示小数位
}
void main()
{
TMOD=0X01;
EA=1;
ET0=1;
TR0=1;
TH0=(65536-4995)/256;
TL0=(65536-4995)%256;
init();
while(1)
{
read_temp();//读取温度
ds1820disp();//显示
time(); //时间程序
display();//时间显示程序
}
}
void t0(void)interrupt 1 using 0
{
TH0=(65536-4995)/256;
TL0=(65536-4995)%256;
count++;
if(count==200){count=0;sec++;}
if(sec==60){sec=0;min++;}
if(min==60){min=0;hour++;}
if(hour==24){hour=0;}
}
void time()
{
line2[15]=tab[sec%10];line2[14]=tab[sec/10];
line2[12]=tab[min%10];line2[11]=tab[min/10];
line2[9]=tab[hour%10];line2[8]=tab[hour/10];
if(!P1_2){delay();if(!P1_2){delay();sec++;if(sec==60){sec=0;}}}
if(!P1_1){delay();if(!P1_1){delay();min++;if(min==60){min=0;}}}
if(!P1_0){delay();if(!P1_0){delay();hour++;if(hour==24){hour=0;}}}
}
给你参考一下,这样才能提高哦
以上就是关于单片机+1602+按键 c语言编程全部的内容,包括:单片机+1602+按键 c语言编程、求一份用1602,AT89C52,DS1302做的时钟的C语言代码,或者求哪位大侠帮我看看这个程序有什么问题吧。。。、1602液晶显示屏显示程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)