论坛风格切换切换到宽版
  • 4233阅读
  • 14回复

初学C51~写了个驱动1602LCM的程序~~大家帮看看有什么问题~~ [复制链接]

上一主题 下一主题
离线kyughanum
 
发帖
99
只看楼主 倒序阅读 0楼 发表于: 2006-09-27
#include <reg52.h>
#include <intrins.h>

void check();
void writecmd();
void writedat();
void cls();
void init();
//连接
sbit rs=p3^3;
sbit rw=p3^4;
sbit e=p3^5;
sbit bf=p1^7;
bit bit01;
unsigned char cmd,dat;

void main(){
  init();
      cls();
      cmd=0x80;//设定在第一行第一个显示
      writecmd();
      dat=0x41;//设定字显示为a
      writedat();
}


void check(){
  do{
  rs=0;
      rw=1;
      e=1;
    bit01=bf;
      }while(bit01);/*不知道这个能不能这样子用?还有我这里没有延时函数,不知这个行不行?*/
}


void writecmd(){
  check();
      rs=0;
      rw=0;
      e=0;
      p1=cmd;
    e=1;
}


void writedat(){
  check();
      rs=1;
      rw=0;
      e=0;
      p1=dat;
    e=1;
}


void cls(){
  cmd=0x01;
      writecmd();
}


void init(){
  cmd=0x38;
      writecmd();
      cmd=0x0e;
      writecmd();
      cmd=0x06;
      writecmd();
}



在自学中~~请大家多多指点~
在线BG4UVR
发帖
11288
只看该作者 1楼 发表于: 2006-09-27
这个程序是否经过测试?我想大概不行,因为lcm上电后没有等待就进行了操作。
离线kyughanum
发帖
99
只看该作者 2楼 发表于: 2006-09-27
哦~~那我再写个延时~~
就是
void check(){
do{
rs=0;
rw=1;
e=1;
bit01=bf;
}while(bit01);/*不知道这个能不能这样子用?还有我这里没有延时函数,不知这个行不行?*/
}
这个能够实现吗?
在线BG4UVR
发帖
11288
只看该作者 3楼 发表于: 2006-09-27
应该不行的,你的e一直是1的状态,没有变化,所以程序不会去反复的读取lcm的数据,而不在于你那有没有延时。(以上是我猜测的,没有做实际测试)

写lcm的程序,我喜欢从一些经典的例程上改,这样出错的机会比较少。

一个经典的程序,是这样判断是否为忙状态的:


#define lcm_data p0
#define busy 0x80 //用于检测lcm状态字中的busy标识
//读状态
unsigned char readstatuslcm(void)
{
     lcm_data = 0xff;
     lcm_rs = 0;
     lcm_rw = 1;
     lcm_e = 0;
     lcm_e = 0;
     lcm_e = 1;
     while (lcm_data & busy); //检测忙信号
     return(lcm_data);
}

只有当lcm的状态变为不忙时,函数才会返回。
离线kyughanum
发帖
99
只看该作者 4楼 发表于: 2006-09-27
呵呵`~我也想我的程序主要是这个问题`~多谢这位朋友了~
在线BG4UVR
发帖
11288
只看该作者 5楼 发表于: 2006-09-27
不用客气,我也是在学习c过程中。有时碰到问题真的感觉很茫然,因为周围没人懂这个的人。大家互相交流一下也不错。
离线BG8WJ
发帖
166
只看该作者 6楼 发表于: 2006-09-28
#define lcm_data p0
#define busy 0x80 //用于检测lcm状态字中的busy标识
//读状态
unsigned char readstatuslcm(void)
{
lcm_data = 0xff;


这个函数可以说是比较经典的,但是这个函数从适用的角度说不太经济!它使用的是
unsigned 作为返回 比较下来占用空间 其实对于busy的判别最好使用 bit型返回这样效率很高!另外给你给建议作为lcm的编程,在读写时不要使用延时函数!使用busy作为判别会事半功倍。应为延时函数在还系统的时候会发生时间上的改变!现在我自己在开发基于mcs-51的芯片,使用的时钟频率已经用到90mhz,你说这个延时程序怎么写?
给你一个通用的lcm测忙例程函数:
bit check_busy()
{
 
  acc=lcd_command_port; //利用 acc 读取lcd端口返回字节;
  return(acc^7);//利用acc可以实现位寻址返回busy位;
}
一般调用格式;
void write_command(unsigned char dat)
{
     while(check_busy()==0);
      lcd_command_port= dat;
}

这样你可以用最小的空间,实现工作,这样对于比较大得程序开发时,不需要为芯片的选型,时钟频率反覆的折腾程序。这样合理的编程同样可以使你的芯片的控制效率大大提高。
















lcm_rs = 0;
lcm_rw = 1;
lcm_e = 0;
lcm_e = 0;
lcm_e = 1;
while (lcm_data & busy); //检测忙信号
return(lcm_data);
}

只有当lcm的状态变为不忙时,函数才会返回。
在线BG4UVR
发帖
11288
只看该作者 7楼 发表于: 2006-09-29
7楼说得不错,学习了。

我补充说明一下,我4楼帖的函数,它的功能可不只是判断忙,它本来的功能是读取lcm的状态,当然,是否是忙也是它状态中的一项内容。这就是为什么这个函数使用了unsigned char 的返回类型。

btw:这个函数不是我写的,是网上一位叫“明浩”(此人也是.net的注册用户哟)的网友写的。
离线kyughanum
发帖
99
只看该作者 8楼 发表于: 2006-09-29
多谢这几位朋友~~谢谢大家的热心!

我想还是用bit返回类型比较好吧~我现在找到个了方法~
bit lcd_bz()
{ // 测试lcd忙碌状态
bit result ;
rs = 0 ;
rw = 1 ;
ep = 1 ;
result = (bit)(pd & 0x80) ;
ep = 0 ;
return result ;
}

强制指定值为bit类型~感觉这样子在while中比较容易理解引用~

多谢大家了~~在这里学到了不少东西`
在线BG4UVR
发帖
11288
只看该作者 9楼 发表于: 2006-09-29
试试直接

return((bit)(pd&0x80));

可不可以。少用一个位变量,RAM,能省一点是一点 :d
离线kyughanum
发帖
99
只看该作者 10楼 发表于: 2006-09-29
好主意~~我现在就试一下~
离线kyughanum
发帖
99
只看该作者 11楼 发表于: 2006-09-29
呵呵~~不行哦~~编译通过~~但是上机时没显示啊~~我想是没有读取到pd中的状态吧~~
在线BG4UVR
发帖
11288
只看该作者 12楼 发表于: 2006-09-30
改成这样:

rs=0;
rw=0;
ep=0;
ep=1;
return((bool)(pd&0x80));

编译正常,只能说明编程的语句没有什么问题,但逻辑性错误,编译器是发现不了的。
比如这次出错的原因,应该是你读取的时序不对(如果改成我上面的语句就可以了的话)。
离线BG8WJ
发帖
166
只看该作者 13楼 发表于: 2006-10-03
嘻嘻,这个就是keil 集成环境的特点,对于逻辑上的问题是不会检测的。在做系统开发的话必须自己熟悉选型用的器件的特点,datasheet必须随时在手边翻查。
真喜欢这样的讨论,其实mcs51的单片机功能是很强的,并且指令体系和x86的很接近。很容易上手。最关键的是价格便宜容易买到啊。^_^ 前几天买到的winband的双串口的mcu价格是89s52的价钱,每一条指令的速度比c51快2-3倍。
离线BG6QAM
发帖
13993
只看该作者 14楼 发表于: 2006-10-04