论坛风格切换切换到宽版
  • 3742阅读
  • 4回复

相关LCD1602显示请帮忙 [复制链接]

上一主题 下一主题
离线lim1234
 
只看楼主 倒序阅读 0楼 发表于: 2008-03-24
我为了节省io口,通过74ls164扩展到1602的8个数据口,此法不能进行忙检测,听前辈说忙检测可以用延迟代替,可是我的板依然没能显示.
控制器为89s52,
p0口加上拉4.7k排阻,
p06接164的1和2脚,
p07接164的8脚,
164的3,4,5,6,10,11,12,13分别接1602的7至14脚,即1602的d0到d7数据口,

帮忙看一下接法有无错误或程序有没有问题,测试程序如下:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit r_s=p0^3;
sbit r_w=p0^4;
sbit e=p0^5;
sbit sda=p0^6;
sbit clk=p0^7;
//***************************************************************
void shift164(uchar d) //74ls164移位
{
    uchar i=0;
    while(i<8)
    {
    if(d&0x80!=0)
      sda=1;
    else
      sda=0;
    clk=0;clk=1;
    d<<=1;
    i++;
    }
}
//***************************************************************
void delay(uint time)
{
  while(time--);
}
//***************************************************************      
void write_order(uchar order) // 写命令
{
           
     r_s=0;       // 数据:1 命令:0
     r_w=0;       // 读写选择端 读:1   写:0
     e=1;       // 模块使能端
  shift164(order);
     delay(5000);//延迟代替忙检测

     e=0;               //下降沿把数据送进去
}
//***************************************************************
void write_dat(uchar dat)//写数据
{
           
     r_s=1;       // 数据:1 命令:0
     r_w=0;       // 读写选择端 读:1   写:0
    e=1;       // 模块使能端
     shift164(dat);
    delay(5000);//延迟代替忙检测
     e=0;               //下降沿把数据送进去
}
//***************************************************************
void lcd_position(uchar pos)
{
  write_order(pos|0x80);
}
//***************************************************************
void display_char(uchar x,uchar dat)
{
lcd_position(x);      //发送地址码
write_dat(dat);      //发送数据
}
//***************************************************************
void lcd_init()     //lcd初始化
{
     write_order(0x38);delay(1000);
     write_order(0x0f);      //整体显示,0x0f为开光标,闪烁,0x0c为关光标,不闪烁
     write_order(0x06); //设定输入方式,增量移位
     write_order(0x01);      //清除显示
}
//***************************************************************
main()
{

     lcd_init();
        while(1)
        {
        display_char(0x03,Ƈ');//第一行第四格显1
          display_char(0x43,'a');//第二行第四格显a
          }
}
离线lim1234
只看该作者 1楼 发表于: 2008-03-24
怀疑忙检测问题,于是把d7和qh断开,单独把d7接单片机的另一个口进行忙检测还是不行,
bit lcd_busy()
{

  rs=0;
  rw=1;
  e=1;
  _nop_();_nop_();
  _nop_();_nop_();
  d7=p3^0;
  e=0;
  return d7;
}      
在每次送入164后把d7位单独写入,
shift164(order);//shift164(dat);//
d7=order&0x80;//d7=dat&0x80;//
不知道这样写对不对,用164扩展到底如何解决,请高手指点啊!
离线hui1011
发帖
18
只看该作者 2楼 发表于: 2008-03-25
164我没用过,不过驱动1602只需用6口,判忙可用适当的延迟就可以解决,清屏的延迟可能要40ms,用四线驱动就可以省口,如果是想学164如何的话那再慢慢调
离线1a2b3c
发帖
204
只看该作者 3楼 发表于: 2008-03-25
如果用164的话,就只用3根线就好了,一根接164dat,一根接164clk,一根接en,rs与164的dat复用,因为时间先后不同,dat在移位164后就无用了,只要clk不变,那么dat此时就可以作为lcd的rs信号了,但作为164的dat时,因为lcd的en,没有变化,所以此时不会影响lcd.
我早就这样用了,
大概浏览了一下楼主的没什么大问题,你先检测一下164的移位是否正确,确保正确后,那么就看lcd的时序,把en信号在所有信号后单独进行一个脉冲,

哦,看到了,可能你这里有问题:
void write_dat(uchar dat)//写数据
{

r_s=1; // 数据:1 命令:0
r_w=0; // 读写选择端 读:1 写:0
e=1; // 模块使能端
shift164(dat);
delay(5000);//延迟代替忙检测
e=0; //下降沿把数据送进去
}


这样改:
void write_dat(uchar dat)//写数据
{

r_s=1; // 数据:1 命令:0
r_w=0; // 读写选择端 读:1 写:0
shift164(dat);
e=1; // 模块使能端
delay(10);
e=0; //下降沿把数据送进去
delay(5000);//延迟代替忙检测

}
离线lim1234
只看该作者 4楼 发表于: 2008-03-25
谢谢大家帮忙,我已经发现了错误所在,就是
void shift164(uchar d) //74ls164移位
{
uchar i=0;
while(i<8)
{
if(d&0x80!=0)
sda=1;
else
sda=0;
clk=0;clk=1;
d<<=1;
i++;
}
}
164移位中if(d&0x80!=0)
!=的优先级比&高,改成if((d&0x80)!=0)就有显示了.
1a2b3c 说的方法也试了一下,就是只用三个口就可以做到,受教了.非常感谢.