专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

LCD1602,LCD1640液晶4位总线模式编程成功

作者:佚名   来源:本站原创   点击数:  更新时间:2010年05月22日   【字体:
//由于2051的IO不够用,必须省出IO口,迫不得已,又根据大量资料对程序进行了修改
//得到如下能够成功运行的程序。本程序在STC89C51RC@12MHz 4位总线模式下通过data image CM1640液晶模块
//yusung W-1602A液晶模块,广州捷胜 1602A V1.0模块的测试,均可正常写入。

#include < reg51.h>
sbit rs=P3^5;//指令数据选择
sbit rw=P2^7;//读写选择
sbit clk=P3^4;//使能脉冲
unsigned char code Logo_text1[]="[China O Soft!] ";//文字数组
unsigned char code Logo_text2[]="Soldering iron. ";//文字数组
unsigned char code Logo_text3[]={'V','o','l','t',':','2','0','V',' ','S','e','t','3','0','0',0xdf};//文字数组
unsigned char code Logo_text4[]={'P','o','w','e','r',':','2','0','W',' ','C','T','2','9','5',0xdf};//文字数组
unsigned char m;//辅助寻址指针变量
sbit clear = P3^2;//清屏按钮
sbit key1 = P3^4;//写第一行按钮
sbit key2 = P3^5;//写第二行按钮
sbit key3 = P3^6;//显示模式变更测试按钮

void delay2ms()//2064周期延时
{
unsigned char temP0;
while(--temp1);
while(--temp1);
while(--temp1);
while(--temp1);
}

void delay()
  {
  unsigned char temp1,temp2;
  temp1=50;
  while(--temp1)
    while(--temp2);
  }

void check_busy()//忙检测
  {
  unsigned char busy;//临时字节
  do
  {
  rs=0;//选择寄存器
  rw=1;//读取
  clk=1;//LCD将数据放到总线
  busy=P0;//读入总线数据
  clk=0;//关闭总线
  busy=busy&0x80;//保留最高位
  }while(busy);//判断是否为忙
  }

void instructions(unsigned char INS)//写指令函数
  {
  check_busy();//写之前检测忙
  rs=0;//选择指令寄存器
  rw=0;//写操作
  clk=1;//准备下降沿
  P0=INS;//数据放到总线上
  clk=0;//下降沿,数据写入LCD

  clk=1;//准备下降沿
  P0=INS<<4;//数据放到总线上
  clk=0;//下降沿,数据写入LCD
  }


void write_data(unsigned char dat)//写数据函数
  {
  check_busy();//写之前检测忙
  rs=1;//选择数据寄存器
  rw=0;//写操作
  clk=1;//准备下降沿
  P0=dat;//数据放到总线上
  clk=0;//下降沿,数据写入LCD

  clk=1;//准备下降沿
  P0=dat<<4;//数据放到总线上
  clk=0;//下降沿,数据写入LCD
  }
void lcd_clear()//清除显示函数
  {
  instructions(0x01);//清除显示
  delay2ms();//清屏后,按手册至少应延时1.53ms
  }
void set_4bit_mode()
  {
  check_busy();//写之前检测忙
  rs=0;//选择指令寄存器
  rw=0;//写操作
  clk=1;//准备下降沿
  P0=0x2f;//4位总线控制字
  clk=0;//下降沿,数据写入LCD
  }
void lcd_init()
  {
  rw=0;//写操作
  set_4bit_mode();//设置成4位总线模式.
  delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
  instructions(0x0f);//设置输入模式为8位数据总线,光标增量移动,显示不移位
  delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
  instructions(0x06);//开显示,关闭光标,不闪烁
  delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
  lcd_clear();//调用清屏函数

  instructions(0x80+0x00);//写入显示缓冲区起始地址为1行1列
  delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
  for(m=0;m<16;m++)//将预先定义好的字符连续发送到LCD
    {
 write_data(Logo_text1);//通过辅助变量查询数组并写入LCD
 delay();
 }

  instructions(0x80+0x40);//写入显示缓冲区起始地址为2行1列
  delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
  for(m=0;m<16;m++)//将预先定义好的字符连续发送到LCD
    {
 write_data(Logo_text2);//通过辅助变量查询数组并写入LCD
 delay();
 }
  }

void main()
{
lcd_init();//LCD初始化
while(1)
  {
  if(!key1)//判断按键是否按下
    {
 instructions(0x80+0x10);//写入显示缓冲区起始地址为1行1列
    delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
 for(m=0;m<16;m++)//将预先定义好的字符连续发送到LCD
   {
   write_data(Logo_text3);//通过辅助变量查询数组并写入LCD
   }
 }
  if(!key2)//判断按键是否按下
    {
 instructions(0x80+0x50);//写入显示缓冲区起始地址为2行1列
    delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
 for(m=0;m<16;m++)//将预先定义好的字符连续发送到LCD
   {
   write_data(Logo_text4);//通过辅助变量查询数组并写入LCD
   }
 }
  if(!clear)//判断按键是否按下
    {
 lcd_clear();//调用清屏函数
 }
  if(!key3)//判断按键是否按下
    {
 instructions(0x0c);//改变显示模式
    delay2ms();//按手册应至少延时39us,但由于执行次数不多,统一使用2ms延时
 }
  }
}

关闭窗口

相关文章