lcd1602有时候单片机下程序能显示有时不能显示是什么原因求助!谢谢!

lcd1602有时候单片机下程序能显示有时不能显示是什么原因求助!谢谢!,第1张

1硬件连接接触不良、虚焊。

2LCD初始化函数写的不好,偶尔上电后初始化失败,就不能显示。建议上电延时一段时间,待LCD稳定后在执行初始化函数。

3程序上要注意读写时序,加入适当的延时时间。

4调节LCD第三脚V0的电压,调节到一个合适的值才可以显示。

先查硬件,确定没问题再在软件上找原因,只要细心,没有什么解决不了!祝你好运!

首先延时函数不能忘 那么你说加了延时也不行,回头看看你的代码。那么问题来了,你P0端如果全是低电平他怎么发送数据,单片机接收的都是全被拉低的数据吧,也就是还是低电平,加一个P0=0xff看看;还有一个问题就是你的代码里面e引脚多了一条(个人建议)e为底电平的时候才读高电平就不读 所以byte = P0;return byte;这两条要紧跟在在e=0后面。不然一旦e=1 P0就不是读出来的数据了。 头一次认真回答问题,也刚研究1602这个功能,帮助到你的话希望采纳下,谢谢

unsigned char Read_Lcd_Data()

{

unsigned char byte;

Busy_Test();

P0 = 0xff;       //防止低电平干扰拉低数据位

Lcd_RW = 1;

Lcd_RS = 1;

delay();        //写个延时程序 为什么加延时请看时序图

Lcd_E = 0;

byte = P0;

return byte;

Lcd_E = 1;

}

你把这两个程序合起来改下就差不多咯!时间忙 只能把自己以前学的子程序给你咯

; :1602显示

LCD_RS EQU P20

LCD_RW EQU P21

LCD_EN EQU P22

LCD_DATA EQU P0

;

ORG 0000H

AJMP MAIN

ORG 0030H

;

MAIN:

MOV SP,#60H

ACALL LCD_INIT ;LCD初始化

MAIN1:

ACALL CLR_LCD ;清LCD

MOV A,#90H ;在第一行第17列的位置

ACALL LCD_CMD

MOV DPTR,#LINE1 ;第一行字符串的起始地址送入DPTR。

ACALL WRITE

MOV A,#0D0H ;在第二行第17列的位置

ACALL LCD_CMD

MOV DPTR,#LINE2 ;第二行字符串的起始地址送入DPTR。

ACALL WRITE

MOV R3,#10H ;向左移动16格

LOOPA:

MOV A,#18H ;字符同时左移一格

ACALL LCD_CMD

MOV R5,#03H ;延时375MS

ACALL DELAY125MS

DJNZ R3,LOOPA

ACALL DELAY4 ;延时16s

ACALL DELAY4

MOV R4,#02H ;设置闪烁次数

ACALL FLASH ;开始闪烁

AJMP MAIN1

LINE1:

DB "YALONG:",00H

LINE2:

DB "welcome you!",00H

;

;LCD初始化设定子程序

;

LCD_INIT:

ACALL DELAY5MS ;延时15MS

ACALL DELAY5MS ;等待LCD电源稳定

ACALL DELAY5MS

MOV A,#38H ;162显示,57点阵,8位数据

ACALL LCD_CMD_NC ;不进行LCD忙检测

ACALL DELAY5MS

MOV A,#38H ;162显示,57点阵,8位数据

ACALL LCD_CMD_NC ;不进行LCD忙检测

ACALL DELAY5MS

MOV A,#38H ;162显示,57点阵,8位数据

ACALL LCD_CMD_NC ;不进行LCD忙检测

ACALL DELAY5MS

MOV A,#08H ;显示关

ACALL LCD_CMD ;进行LCD忙检测

MOV A,#01H ;清除屏幕

ACALL LCD_CMD ;进行LCD忙检测

MOV A,#0CH ;显示开,关光标

ACALL LCD_CMD ;进行LCD忙检测

RET

;

;清LCD子程序

;

CLR_LCD:

MOV A,#01H ;清除屏幕

ACALL LCD_CMD ;进行LCD忙检测

RET

;

;写指令数据到LCD

;RS=L,RW=L,D0-D7=指令码,E=高脉冲

;

LCD_CMD:

CALL CHECKBUSY

LCD_CMD_NC:

CLR LCD_RS

CLR LCD_RW

MOV LCD_DATA,A

SETB LCD_EN

NOP

NOP

NOP

NOP

CLR LCD_EN

RET

;

;写显示数据到LCD

;RS=H,RW=L,D0-D7=数据,E=高脉冲

;

LCD_WDATA:

ACALL CHECKBUSY

SETB LCD_RS

CLR LCD_RW

MOV LCD_DATA,A

SETB LCD_EN

NOP

NOP

NOP

NOP

CLR LCD_EN

RET

;

;检测LCD控制器忙状态

;读数据

;RS=L,RW=H,E=H,输出:D0-D7=数据

;LCD_DATA7=1,LCD忙,等待。LCD_DATA7=0,LCD闲,可以进行读写 *** 作。

;

CHECKBUSY:

PUSH ACC

MOV LCD_DATA,#0FFH

CLR LCD_RS

SETB LCD_RW

SETB LCD_EN

BUSYLOOP:

NOP

JB LCD_DATA7,BUSYLOOP

CLR LCD_EN

POP ACC

RET

;

; 发送字符串子程序

;

WRITE:

PUSH ACC

WRITE1:

CLR A

MOVC A,@A+DPTR

JZ WRITE2

INC DPTR

ACALL LCD_WDATA

JMP WRITE1

WRITE2:

POP ACC

RET

;

;闪烁子程序

;

FLASH:

MOV A,#08H ;关闭显示

ACALL LCD_CMD

ACALL DELAY4

MOV A,#0CH ;开显示,关闭光标

ACALL LCD_CMD

ACALL DELAY4

DJNZ R4,FLASH

RET

;

;延时5MS子程序

;LCD初始化使用

;

DELAY5MS:

MOV R6,#10

DL1:

MOV R7,#249

DL2:

DJNZ R7,DL2

DJNZ R6,DL1

RET

;

;延时125MS子程序

;字符串移动时使用

;

DELAY125MS:

DL3:

MOV R6,#250

DL4:

MOV R7,#249

DL5:

DJNZ R7,DL5

DJNZ R6,DL4

DJNZ R5,DL3

RET

;

;延时800MS子程序

;闪烁时使用

;

DELAY4:

MOV R5,#40

DL6:

MOV R6,#100

DL7:

MOV R7,#100

DL8:

DJNZ R7,DL8

DJNZ R6,DL7

DJNZ R5,DL6

RET

;

ENd

; ADC0809子程序

; 引脚定义

ADC_EOC EQU P20

ADC_CS EQU P21

ADC_RD EQU P22

ADC_WR EQU P23

ADC_DATA EQU P0

ORG 0000H

AJMP MAIN

ORG 0030H

MAIN:

SETB ADC_EOC

SETB ADC_WR

SETB ADC_RD

SETB ADC_CS

CLR ADC_CS ;START and ALE is H

CLR ADC_WR

NOP

NOP

NOP

SETB ADC_WR

SETB ADC_CS

NOP

JB ADC_EOC,$ ; JNB ADC_EOC,$

CLR ADC_CS

CLR ADC_RD

MOV ADC_DATA,#0FFH

MOV A,ADC_DATA

SETB ADC_RD

SETB ADC_CS

CJNE A,#00H,BELL

INC A

BELL:

MOV R5,A

BELL1: ACALL DELAY

DJNZ R5,BELL1

CPL P27

AJMP MAIN

DELAY:

MOV R7,#02H

D1:

MOV R6,#0FFH

DJNZ R6,$

DJNZ R7,D1

RET

END

module LCD_Driver(clk,rst,lcd_rs,lcd_en,lcd_rw,lcd_data,f0,f1,f2,d0,d1,d2,sel);

input clk,rst;//时钟、复位

input [3:0] f0 ;//频率、占空比、档位输入

input [3:0] f1 ;

input [3:0] f2 ;

input [3:0] d0 ;

input [3:0] d1 ;

input [3:0] d2 ;

input [3:0] sel ;

output lcd_rs,lcd_en,lcd_rw;//指令/数据控制、片选、读写控制、背光控制

output [7:0] lcd_data;//数据线

reg lcd_rs;//指令/数据控制

reg [7:0] lcd_data;//数据线

reg [7:0] current_state;//当前状态

reg [1:0] state_counter;//状态计数

reg en_temp;//使能标志

reg [15:0] clk_counter;//时钟计数

reg clk_en;//时钟使能

//reg [7:0] ps_datain_temp;

assign lcd_rw=1'b0;//一直为写状态

/状态编码/

parameter set0=8'b0000_0000,

set1=8'b0000_0001,

set2=8'b0000_0011,

set3=8'b0000_0100,

set4=8'b0000_0101,

set5=8'b0000_0110,

data1=8'b0000_1000,

data2=8'b0000_1001,

data3=8'b0000_1010,

data4=8'b0000_1011,

data5=8'b0000_1100,

data6=8'b0000_1101,

data7=8'b0000_1110,

data8=8'b0000_1111,

data9=8'b0001_0000,

data10=8'b0001_0001,

data11=8'b0001_0010,

data12=8'b0001_0011,

data13=8'b0001_0100,

data14=8'b0001_0101,

data15=8'b0001_0110,

data16=8'b0001_0111,

data17=8'b0001_1000,

data18=8'b0001_1001,

data19=8'b0001_1010,

data20=8'b0001_1011,

data21=8'b0001_1100,

data22=8'b0001_1101,

data23=8'b0001_1110,

data24=8'b0001_1111,

data25=8'b0010_0001,

data26=8'b0010_0010,

data27=8'b0010_0011,

data28=8'b0010_0100,

data29=8'b0010_0101,

data30=8'b0010_0110,

data31=8'b0010_0111,

data32=8'b0010_1000,

stop=8'b1111_1111;

/状态转换时钟/

always @(posedge clk)

begin

if(clk_counter==16'h6000)

begin

clk_counter<=16'h0;

clk_en<=~clk_en;

end

else

clk_counter<=clk_counter+1'b1;

end

/状态转换///

always @(posedge clk_en or negedge rst)

begin

if(!rst)

begin

current_state<=set0;

end

else

begin

case (current_state)

//

set0:begin lcd_rs<=1'b0;lcd_data<=8'h38;current_state<=set1; end//显示模式设置

set1:begin lcd_rs<=1'b0;lcd_data<=8'h0c;current_state<=set2; end//显示开及光标设置

set2:begin lcd_rs<=1'b0;lcd_data<=8'h06;current_state<=set3; end//显示光标移动设置

set3:begin lcd_rs<=1'b0;lcd_data<=8'h01;current_state<=set4; end//显示清屏

set4:begin lcd_rs<=1'b0;lcd_data<=8'h80;current_state<=data1; end//设置第一行地址

//

data1:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data2; end//显示第1个字符

data2:begin lcd_rs<=1'b1;lcd_data<="F";current_state<=data3; end//显示第2个字符

data3:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data4; end//显示第3个字符

data4:begin lcd_rs<=1'b1;lcd_data<="=";current_state<=data5; end//显示第4个字符

data5:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data6; end//显示第5个字符

data6:begin lcd_rs<=1'b1;lcd_data<=f0+"0";current_state<=data7; end//显示第6个字符

data7:begin lcd_rs<=1'b1;lcd_data<=f1+"0";current_state<=data8; end//显示第7个字符

data8:begin lcd_rs<=1'b1;lcd_data<=f2+"0";current_state<=data9; end//显示第8个字符

data9:begin lcd_rs<=1'b1;lcd_data<="x";current_state<=data10; end//显示第1个字符

data10:begin lcd_rs<=1'b1;if(sel[3])lcd_data<="1";else lcd_data<="0";current_state<=data11; end//显示第2个字符

data11:begin lcd_rs<=1'b1;if(sel[2])lcd_data<="1";else lcd_data<="0";current_state<=data12; end//显示第3个字符

data12:begin lcd_rs<=1'b1;if(sel[1])lcd_data<="1";else lcd_data<="0";current_state<=data13; end//显示第4个字符

data13:begin lcd_rs<=1'b1;if(sel[0])lcd_data<="1";else lcd_data<="0";current_state<=data14; end//显示第5个字符

data14:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data15; end//显示第6个字符

data15:begin lcd_rs<=1'b1;lcd_data<="H";current_state<=data16; end//显示第7个字符

data16:begin lcd_rs<=1'b1;lcd_data<="Z";current_state<=set5; end//显示第8个字符

set5:begin lcd_rs<=1'b0;lcd_data<=8'hc0;current_state<=data17; end//设置第2行地址

data17:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data18; end//显示第1个字符

data18:begin lcd_rs<=1'b1;lcd_data<="D";current_state<=data19; end//显示第2个字符

data19:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data20; end//显示第3个字符

data20:begin lcd_rs<=1'b1;lcd_data<="=";current_state<=data21; end//显示第4个字符

data21:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data22; end//显示第5个字符

data22:begin lcd_rs<=1'b1;lcd_data<=d0+"0";current_state<=data23; end//显示第6个字符

data23:begin lcd_rs<=1'b1;lcd_data<=d1+"0";current_state<=data24; end//显示第7个字符

data24:begin lcd_rs<=1'b1;lcd_data<=d2+"0";current_state<=data25; end//显示第8个字符

data25:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data26; end//显示第二个字符

data26:begin lcd_rs<=1'b1;lcd_data<="%";current_state<=data27; end//显示第四个字符

data27:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data28; end//显示第五个字符

data28:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data29; end//显示第六个字符

data29:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data30; end//显示第七个字符

data30:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data31; end//显示第八个字符

data31:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=data32; end//显示第九个字符

data32:begin lcd_rs<=1'b1;lcd_data<=" ";current_state<=stop; end//显示第九个字符

//

stop:begin //控制指令与数据写入的次数

lcd_rs<=1'b0;

lcd_data<=8'b0000_0000;

if(state_counter!=2'b10)

begin

en_temp<=1'b0;

current_state<=set4;

state_counter<=state_counter+1'b1;

end

else

begin

current_state<=set4;

en_temp<=1'b0;//最后数据写入完成后将lcd_en线拉高

end

end

default: current_state<=set0;

endcase

end

end

assign lcd_en=clk_en|en_temp;//lcd_en为‘1’有效

endmodule

写的PWM,如果实时显示就要状态机一直循环,并且给模块定义一个数据输入变量

你这程序中有两个程序注释掉了,也不能倒计时了。给你的程序进行简化,修改如下,增加了写字符串和变量的子程序和语句。你可以参考这个程序写出倒计时的程序。

#include<reg51h>

unsigned int num=123;

void delay(unsigned int xms)

{

unsigned int x,y;

for(x=xms;x>0;x--)

for(y=110;y>0;y--);

}

sbit LCD_EN =P2^5;

sbit LCD_RS =P1^0;

sbit LCD_RW =P1^1;

void write_com(unsigned char com)

{

LCD_RS=0;

LCD_EN=0;

P0=com;

delay(5);

LCD_EN=1;

LCD_EN=0;

}

void write_Data(unsigned char Data)

{

LCD_RS=1;

LCD_EN=0;

P0=Data;

delay(5);

LCD_EN=1;

LCD_EN=0;

}

void LCD_init(void)

{

LCD_RW=0;

LCD_RS=0;

LCD_EN=0;

write_com(0x38);

write_com(0x0c);

write_com(0x06);

write_com(0x01);

}

//写字符串子函数

void disp(unsigned char sp)

{

while(sp!='\0')

{

write_Data(sp);

sp++;

}

}

void main()

{

LCD_init();

write_com(0x80);

write_Data('1');

write_com(0xc0);

disp("time:");//写字符串

write_Data(num/100+48);  //写变量百位

write_Data(num/10%10+48);//写变量十位

write_Data(num%10+48);   //写变量个位

while(1);

}

说明,你的程序只适合于仿真,对于实物是不行的。仿真结果如下图所示。

你仿照这个程序改改你的显示

#include<reg52h>

#include <intrinsh>

#include <mathh>

#include <stdioh>

#define uchar unsigned char

#define uint unsigned int

#define LCD_DATA P0

sbit lcd_flag=P0^7;

sbit LCD_RS=P3^0;

sbit LCD_RW=P3^1;

sbit LCD_E=P3^3;

sbit p32=P3^2;

sbit ST=P2^3;

sbit OE=P2^4;

sbit EOC=P2^5;

static long int counter;

static long float f;

float Vbuf=0,xy,tmp,flag=0;

void lcd_delay(int ms) //延时函数

{

uchar i;

while(ms--)

{

for(i=0;i<250;i++)

{

_nop_();_nop_();_nop_();_nop_();

}

}

}

bit lcd_busy() //判断是否忙碌 RS=Low,RW=High,E=High:读状态

{

bit flag;

LCD_RS=0; //寄存器为Low

LCD_RW=1; //是否读写为High

LCD_E=1; //使能端为High

if (lcd_flag==1) flag=1;

else flag=0;

LCD_E=0;

return flag; //返回标志,判断是否LCD忙碌

}

write_command(uchar command) //写指令时序

{ while(lcd_busy());

LCD_RS=0;

LCD_RW=0;

LCD_E=0;

LCD_DATA=command;

//delay_1ms(5);

LCD_E=1;

LCD_E=0;

}

write_data(uchar da) //写数据时序

{ while(lcd_busy());

LCD_RS=1;

LCD_RW=0;

LCD_E=0;

// delay_1ms(5);

LCD_DATA=da;

LCD_E=1;

LCD_E=0;

}

void LCD_INIT(void)

{ write_command(0x38); lcd_delay(1); //LCD为2行,5×7字

write_command(0x0c); lcd_delay(1); //打开显示,显示光标,光标不闪

write_command(0x06); lcd_delay(1); //每次右移一字符

}

void main()

{

uchar i,j,n;

uchar buff[16],buf[16];

LCD_INIT();

P2 &=0xf8;

while(1)

{

flag++;

if(flag >= 10)

{

ST = 0;

OE = 0;

ST = 1;

ST = 0;

if(EOC == 1)

{

OE = 1;

xy = P1;

OE =0;

if(xy > tmp)

{

tmp = xy;

Vbuf = xy10/50;

}

}

}

if(flag < 10)

{

TMOD=0X09;

TH0=0;

TL0=0;

while(p32==1);

TR0=1;

while(p32==0);

while(p32==1);

TR0=0;

}

counter=TH0256+TL0;

while(counter<=500) /判断是否分频及计算分频次数/

{

P2++;

i++;

counter=counter10;

if(i==2)

{

P2 &= 0xf8;

break;

}

}

f=(18432000/(2counter))pow(10,i);

sprintf(buf," V=%42fv",Vbuf);

//if(f<1500) f = f / 13123;

if(f<1000)

{

sprintf(buff,"f=%42fHZ",f);

}

else if(f<1000000)

{

f=f/1000;

sprintf(buff,"f=%42fkHZ",f);

}

write_command(0x80);

for( j=0;j<16&&buf[j] != '\0';j++)

{

write_data(buf[j]) ;

}

write_command(0xc0);

for(n=0;n<16&&buff[n]!='\0';n++)

{

write_data(buff[n]);

}

}

}

以上就是关于lcd1602有时候单片机下程序能显示有时不能显示是什么原因求助!谢谢!全部的内容,包括:lcd1602有时候单片机下程序能显示有时不能显示是什么原因求助!谢谢!、单片机怎么从lcd1602读取数据、51单片机+ADC0809+LCD1602用汇编语言编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/10171010.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-06
下一篇2023-05-06

发表评论

登录后才能评论

评论列表(0条)

    保存