1602液晶驱动

/***************************************************
            指令集
[1] RS RW = 0 0
    +    00000001 : 清屏                  1.64us
    +    0000001* : 归位                      1.64us
        
    +    000001AB : 输入方式设置          40us
    +    A=0 位置-1        A=1 位置+1
    +    B=0 画面不动   B=0 画面平移
        
    +    00001ABC : 显示开关设置             40us
    +    A=0 显示关     A=1 显示开
    +    B=0 光标关        B=1 光标开
    +    C=0 闪烁关     C=1 闪烁开
        
    +    0001AB** : 光标画面位移         40us
    +    A=0 光标平移   A=1 画面平移
    +    B=0 左移       B=1 右移
        
    +    001ABC** : 功能设置                40us
    +    A=0 4位数据     A=1 8位数据
    +    B=0 一行显示    B=1 两行显示
    +    C=0 5X7点阵     C=1 5X10点阵
        
    +    01ABCDEF : CGRAM 设置            40us
    +    A~F=0~3FH

      +    1ABCDEFG : DDRAM 设置            40us
    +   一行显示 0~4FH
    +    两行显示 0~2FH 40H~67H
                                 
[2] RS RW = 0 1                              40us
    +    XA~G : 读BF及AC值
    +    X=0 准备好   X=1 忙
    +    AC只为最近一次地址设置


[3] RS RW = 0 1                              40us
    +    A~H :写数据

[4] RS RW = 1 1                             40us
    +    A~H :读数据

******************************************************/

#include <intrins.h>
#define LCD_IO P0  //IO端口
typedef unsigned char uchar;
typedef unsigned int uint;
typedef bit bool;


sbit rs    = P2^4; //复位端
sbit rw = P2^5; //写数据端
sbit ep = P2^6;    //使能端

void delayms(uint ms);
bool lcd_busy(void);
void lcd_wcmd(uint cmd)    ;
void lcd_wdat(uchar dat);
void lcd_pos(uint pos);
void lcd_init(void);
void lcd_setxy(uint x,uint y);


/*******************延时函数********************/
void delayms(uint ms)
{                            
    uint i;
    while(ms--)
    {
        for(i = 0; i< 250; i++)
        {
            _nop_();
            _nop_(); //空执行消耗CPU时间达到等待的效果
            _nop_();
            _nop_();
        }
    }
}

/*******************LCD侧忙函数********************/
bool lcd_busy(void)
{                        
    bool result;
    rs = 0;
    rw = 1;
    ep = 1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    result = (bool)(P0 & 0x80); //检测P0最高位是否为1
    ep = 0;
    return result;//返回侧忙结果    
}

void lcd_wcmd(uint cmd)
{                            // 写入指令数据到LCD
    while(lcd_busy());
    rs = 0;
    rw = 0;
    ep = 0;
    _nop_();
    _nop_();    
    P0 = cmd; //将8位指令通过P0口传给1602
    _nop_();
    _nop_();//用于产生一个脉冲宽度
    _nop_();
    _nop_();
    ep = 1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    ep = 0;        
}

void lcd_pos(uint pos)
{                            //设定显示位置
    lcd_wcmd(pos | 0x80);
}

void lcd_setxy(uint x,uint y)
{


 lcd_wcmd( 0x80 | ((y-1) ? 0x39+x : x-1));

}


void lcd_wdat(uchar dat)    
{                            //写入字符显示数据到LCD
    while(lcd_busy());
    rs = 1;
    rw = 0;
    ep = 0;
    P0 = dat;//将8位数据通过P0口传给1602 
    _nop_();
    _nop_();
    _nop_(); //用于产生一个脉冲宽度
    _nop_();
    ep = 1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    ep = 0;    
}

void lcd_init(void)
{                      //LCD初始化设定
    lcd_wcmd(0x38);      ////16*2显示,5*7点阵,8位数据
    delayms(1);
    lcd_wcmd(0x0c);      //显示开,关光标
    delayms(1);
    lcd_wcmd(0x06);      //移动光标
    delayms(1);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delayms(1);
}

 

posted @ 2012-06-28 20:15  sky1991  阅读(255)  评论(0编辑  收藏  举报