
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用汇编语言编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)