lcd1602显示程序

时间:2024-09-02 09:49:08编辑:分享君

急求一个基于89C51单片机,用4*4矩阵键盘输入数据,并在LCD1602上显示出来的c语言程序。

#define LCD1602_FLAG#define LCD1602_PORT P0#include#include#define uchar unsigned charsbit lcd1602_rs=P2^0;sbit lcd1602_e=P2^2;sbit lcd1602_rw=P2^1;sbit lcd1602_busy=P0^7;uchar str[]="This is Key Test";uchar keyval,keystr[16];void delay(uchar a){uchar i;while(a--)for(i=0;i<120;i++);}/************************************** 函数名称:lcd1602_CheckBusy()* 函数功能:状态查询*************************************/void lcd1602_CheckBusy(){do{lcd1602_busy=1;lcd1602_rs=0;lcd1602_rw=1;lcd1602_e=0;lcd1602_e=1;}while(lcd1602_busy);}/***************************************** 函数名称: lcd1602_WriteCmd()* 函数功能:写命令* 入口参数:命令字* 出口参数:无****************************************/void lcd1602_WriteCmd(const uchar cmd){lcd1602_CheckBusy();lcd1602_rs=0;lcd1602_rw=0;lcd1602_e=1;LCD1602_PORT=cmd;lcd1602_e=0;}/********************************************* 函数名称:lcd1602_WriteData()* 函数功能:写数据* 入口参数:c--待写数据* 出口参数:无**********************************************/void lcd1602_WriteData(const uchar c){lcd1602_CheckBusy();lcd1602_rs=1;lcd1602_rw=0;lcd1602_e=1;LCD1602_PORT=c;lcd1602_e=0;}/************************************************* 函数名称:lcd1602_Init()* 函数功能:初始化LCD* 入口参数:无* 出口参数:无************************************************/void lcd1602_Init(){lcd1602_WriteCmd(0x38); //显示模式为8位2行5*7点阵lcd1602_WriteCmd(0x0c); //display enable,flag enable,flash enable,lcd1602_WriteCmd(0x06); //flag move to right,screen don't movelcd1602_WriteCmd(0x01); //clear screen}/************************************************** 函数名称:lcd1602_Display()* 函数功能: 字符显示* 入口参数:ptr--字符或字符串指针* 出口参数:无* 说 明:用户可通过以下方式来调用:* 1)lcd1602_Display("Hello,world!");* 2) INT8U 存储类型 txt[]="要显示的字符串";* 或者 INT8U 存储类型 txt[]={'t','x','t',..,'\0'};* INT8U *ptr;* ptr=&txt;* lcd1602_Display(ptr);* 或 lcd1602_Display(txt);* 或 lcd1602_Display(&txt);*************************************************/void lcd1602_Display(const uchar *ptr,uchar line){uchar data i=0;uchar *data q;q=ptr;switch(line){case 0:lcd1602_WriteCmd(0x80);while(q!=NULL && (*q!='\0') && i<16){lcd1602_WriteData(*q);q++;i++;}break;case 1:lcd1602_WriteCmd(0xc0);while(q!=NULL && (*q!='\0') && i<16){lcd1602_WriteData(*q);q++;i++;}break;}}uchar kbscan(void){unsigned char sccode,recode;P3=0x0f; //发0扫描,列线输入if ((P3 & 0x0f) != 0x0f) //有键按下{delay(20); //延时去抖动if ((P3&0x0f)!= 0x0f){sccode = 0xef; //逐行扫描初值while((sccode&0x01)!=0){P3=sccode;if((P3&0x0f)!=0x0f){recode=(P3&0x0f)|0xf0;while((P3&0x0f)!=0x0f);//等待键抬起return((~sccode)+(~recode));}elsesccode=(sccode<<1)|0x01;}}}return 0; //无键按下,返回0}uchar getkey(void){uchar key;key=kbscan();if(key==0){keyval=0xff;return(0);}switch(key){case 0x11:keyval=7;break;case 0x12:keyval=4;break;case 0x14:keyval=1;break;case 0x18:keyval=10;break;case 0x21:keyval=8;break;case 0x22:keyval=5;break;case 0x24:keyval=2;break;case 0x28:keyval=0;break;case 0x41:keyval=9;break;case 0x42:keyval=6;break;case 0x44:keyval=3;break;case 0x48:keyval=11;break;case 0x81:keyval=12;break;case 0x82:keyval=13;break;case 0x84:keyval=14;break;case 0x88:keyval=15;break;default:keyval=0xff;break;}if(keyval!=0xff)return(1);else return(0);}main(){uchar num;lcd1602_Init();lcd1602_Display(str,0);while(1){if(getkey()){keystr[num]=keyval+0x30;lcd1602_Display(keystr,1);num++;num%=16;}}}

如何利用51单片机4*4矩阵键盘和1602液晶实现四位(或者多位)的显示问题?

//按4X4键盘的F键 进入设定状态
//E D 键是前后移动键
//C按键是调整数值按键
#include "reg52.h"
#define uchar unsigned char
sbit RW=P2^1;
sbit RS=P2^0;
sbit E=P2^2;
bit at=0;
uchar code shen[]={"CLOCK!"};
uchar code word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x20};
uchar dispbuf[8],h,m,s,counter;
void delay()
{
uchar i;
for(i=0;i<255;i++);
}



/*******写命令**********/
void lcd_wmc(uchar i)
{

P0=i;
RS=0;
RW=0;
E=0;
delay();
E=1;
}



/*******写数据***********/

void lcd_wmd(uchar i)
{

P0=i;
RS=1;
RW=0;
E=0;
delay();
E=1;
}




/*******初始化液晶*******/
void lcd_init()
{
uchar i;
lcd_wmc(0x01);
lcd_wmc(0x38);
lcd_wmc(0x0c);
lcd_wmc(0x06);
lcd_wmc(0xc9);
for(i=0;i<6;i++)
lcd_wmd(shen[i]);
lcd_wmc(0xc0);
}





/*******更新缓冲区子程序*******/
void newbuf()
{
dispbuf[0]=s%10;
dispbuf[1]=s/10;
dispbuf[3]=m%10;
dispbuf[4]=m/10;
dispbuf[6]=h%10;
dispbuf[7]=h/10;
}



/*******显示子程序**********/
void disp(uchar dispadd)
{
uchar tmp;
lcd_wmc(dispadd);
tmp=dispbuf[7];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[6];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[5];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[4];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[3];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[2];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[1];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[0];
tmp=word[tmp];
lcd_wmd(tmp);
}





/*********************键盘子程序***********************/

uchar keypro(void)
{
uchar scanl,scanh;
P1=0x0f;//先将所有行线拉低
if((P1&0x0f)!=0x0f) //如果列线有变化
{
delay();//延迟一段时间。
if((P1&0x0f)!=0x0f)//如果此时此刻列线还有变化,说明确实有按键按下
{
scanl=0xfe;
while((scanl&0x10)!=0)
{
P1=scanl; //给P1口赋扫描码,每次只拉低一行
if((P1&0xf0)!=0xf0) //如果判断为真,则说明找到了按键按下的行
{
scanh=(P1&0xf0)|0x0f; //计算识别码
return (~scanh)+(~scanl);
}
else scanl=(scanl<<1)|0x01; //否则依次将第二,第三,第四行拉低

}
}
}
return 0;//没有按键 按下 返回0
}


/********************时间调整子程序********************/
void adjustime()
{
uchar k;
static uchar add;
k=keypro();
switch(k)
{
case 0x88: if(!at){add=0xc1;EA=0;lcd_wmc(0xc1);lcd_wmc(0x0f);at=1;}
else {lcd_wmc(0xc0);lcd_wmc(0x0c);at=0;EA=1;} break;

case 0x48: if(at)
{
if(add==0xc1){add=0xc7; lcd_wmc(add);}
else {add=add-3;lcd_wmc(add);}
}
break;

case 0x28: if(at)
{
if(add==0xc7) {add=0xc1;lcd_wmc(add);}
else {add=add+3;lcd_wmc(add);}
}
break;

case 0x18: if(at)
{
if(add==0xc1) h++;
if(h==24)
h=0;
if(add==0xc4) m++;
if(m==60)
m=0;
if(add==0xc7) s++;
if(s==60)
s=0;
newbuf();
disp(0xc0);
lcd_wmc(add);
}
break;
default: break;
}
if(k!=0)
{
while((P1&0xf0)!=0xf0)
P1=0xf0;
}

}







/*********************初始化子程序**********************/
void init()
{

TMOD=0x01;
TH0=0x4c;
TL0=0x00;
EA=1;
ET0=1;
TR0=1;
counter=0;
h=12;m=0;s=0;
dispbuf[2]=10;
dispbuf[5]=10;
}







/***************************主程序************************/

void main(void)
{
init();
lcd_init();

while(1)
{
adjustime();
if(!at)
{
//闪烁
if(counter<10)
{
dispbuf[2]=10;
dispbuf[5]=10;
}
else
{
dispbuf[2]=11;
dispbuf[5]=11;
}
//更新显示缓冲区及调用显示程序
if(counter==0)
{
newbuf();
disp(0xc0);
}
else if(counter==10)
disp(0xc0);
}
}
}








/*************************定时器0的中断**********************/
void Time0() interrupt 1 using 2 //再次强调中断子程序执行时间越短越好
{
TH0=(65536-46075)/256;
TL0=(65536-46075)%256;
counter++;
if(counter==20)
{
s++;
counter=0;
if(s==60)
{
m++;
s=0;
if(m==60)
{
h++;
m=0;
if(h==24)
h=0;
}
}

}
}
这是一个数字时钟的程序,用矩阵键盘调时


单片机与DS18B20并用LCD1602显示 c程序 这个问题中你的问答里的头文件DS18B20_3.H,能把代码发来吗

/* DS18B20_3.H*/
sbit DQ = P3^3; // 定义DQ引脚为P3.3

/******************************* 延时函数 ********************************
* 功能:在11.059MHz的晶振条件下调用本函数需要24μs ,然后每次计数需16μs
**************************************************************************/
void DS18_delay(int useconds) {
int s;
for (s=0; s<useconds;s++);
}


/******************************* 复位函数 *******************************
* 功能:完成单总线的复位操作。
* 复位时间为480μs,因此延时时间为(480-24)/16 = 28.5,取29μs。
* 经过70μs之后检测存在脉冲,因此延时时间为(70-24)/16 = 2.875,取3μs。
**************************************************************************/
unsigned char ow_reset(void) {
unsigned char presence;
DQ = 0; // 将 DQ 线拉低
DS18_delay(29); // 保持 480μs
DQ = 1; // DQ返回高电平
DS18_delay(3); // 等待存在脉冲
presence = DQ; // 获得存在信号
DS18_delay(25); // 等待时间隙结束
return(presence); // 返回存在信号,0 = 器件存在, 1 = 无器件
}


/****************************** 位写入函数 *******************************
* 功能:向单总线写入1位值:bitval
*************************************************************************/
void write_bit(char bitval) {
DQ = 0; // 将DQ 拉低开始写时间隙
if(bitval==1) DQ =1; // 如果写1,DQ 返回高电平
DS18_delay(5); // 在时间隙内保持电平值,
DQ = 1; // DS18_delay函数每次循环延时16μs,因此DS18_delay(5) = 104μs
}


/**************************** 字节写入函数 *******************************
* 功能:向单总线写入一个字节值:val
*************************************************************************/
void ds18write_byte(char val) {
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++) { // 写入字节, 每次写入一位
temp = val>>i;
temp &= 0x01;
write_bit(temp);
}
DS18_delay(5);
}

/**************************** 位读取函数 ********************************
* 功能:从单总线上读取一位信号,所需延时时间为15μs,因此无法调用前面定义
* 的DS18_delay()函数,而采用一个for()循环来实现延时。
* ***********************************************************************/
unsigned char read_bit(void) {
unsigned char i;
DQ = 0; //将DQ 拉低开始读时间隙
DQ = 1; // then return high
for (i=0; i<3; i++); // 延时15μs
return(DQ); // 返回 DQ 线上的电平值
}

/**************************** 字节读取函数 *******************************
* 功能:从单总线读取一个字节的值
*************************************************************************/
unsigned char DSread_byte(void) {
unsigned char i;
unsigned char value = 0;
for (i=0;i<8;i++) { // 读取字节,每次读取一个字节
if(read_bit()) value|=0x01<<i; // 然后将其左移
DS18_delay(6);
}
return(value);
}


/******************************* 读取温度函数 *****************************
* 功能:如果单总线节点上只有一个器件则可以直接掉用本函数。如果节点上有多个器
* 件,为了避免数据冲突,应使用Match ROM函数来选中特定器件。
* 注: 本函数是根据DS1820的温度数据格式编写的,若用于DS18B20,必须根据
* DS18B20的温度数据格式作适当修改。
**************************************************************************/unsigned
int ReadTemperature(void) {
unsigned char get[10];
unsigned char temp_lsb,temp_msb;
unsigned int t;
unsigned char k;
ow_reset();
ds18write_byte(0xCC); // 跳过 ROM
ds18write_byte(0x44); // 启动温度转换
DS18_delay(5);
ow_reset();
ds18write_byte(0xCC); // 跳过 ROM
ds18write_byte(0xBE); // 读暂存器
for (k=0;k<2;k++){get[k]=DSread_byte();}

temp_msb = get[1]; // Sign byte + lsbit
temp_lsb = get[0]; // Temp data plus lsb

t=temp_msb*256+temp_lsb;
t=t&0x0ff0;
if(t0xf0)
t=(-1)*t;
return t>>4;
//temp_f = (((int)temp_c)* 9)/5 + 32;
// 输出华氏温度值

}


上一篇:晏婴二桃杀三士

下一篇:积玉桥租房