51驱动1602液晶显示器的程序

//1602.h
#include <reg52.h>

//数据类型定义
typedef unsigned char uchar;
typedef unsigned int uint;

//1602指令定义
//屏幕初始化
#define SCREEN_INIT 0x38 //屏幕设置:16*2行,5*7点阵,8位数据接口
//光标及屏幕显示设置
#define SHOW_SCREEN 0x0C //屏幕显示
#define HIDE_SCREEN 0x08 //屏幕不显示
#define SHOW_CURSOR 0x02 //显示光标
#define FLASH_CURSOR    0x01 //光标闪烁
//地址指针及滚动设置
#define DPTR_INC    0x06 //读/写一个字节地址指针+1,光标+1
#define DPTR_DEC    0x04 //读/写一个字节地址指针-1,光标-1
#define SCREEN_SCR  0x01 //写一个字符,整屏左移/右移
//ADDR设置
#define ADDR_LINE1  0x80 //第一行
#define ADDR_LINE2  0xC0 //第二行
#define LINE1_END   0x10
#define LINE2_END   0x50
//忙碌状态
#define BUSY        0x80
//清屏
#define CLR_SCR     0x01 //清屏
//DPTR清零
#define CLR_DPTR    0x02 //数据指针清零
//1602.c
#include <reg52.h>
#include <intrins.h>

#include "1602.h"

//女孩不哭
//2012-10-25
//ts=sts=sw=4

//以下是端口定义,自行修改
sbit RS = P0^0; //数据/指令选择
sbit RW = P0^1; //读/写控制
sbit E = P0^2;  //使能
#define DATA P2 //数据端口 P[0~7] -> DATA[0~7] 

/*
    函数:微秒延时
    参数:
        us[uchar]:微秒
    返回:(无)
*/
void delay_us(uchar us)
{
    for(; us>0; us--)
        _nop_();
}

/*
    函数:10毫秒延时
    参数:
        ms10[uint]:10毫秒
    返回:(无)
*/
void delay_10ms(uint ms10)
{
    uchar x,y,z;
    while(ms10--){
        for(x=5; x>0; x--);
        for(y=4; y>0; y--);
        for(z=248; z>0; z--);
    }
}
/*
    函数:读取1602状态
    参数:(无)
    返回:(无)
    说明:最高位为忙碌状态位,1代表忙碌
*/
uchar read_state(void)
{
    DATA = 0xff;
    RW = 1;
    RS = 0;
    E = 1;
    return DATA;
}

/*
    函数:执行一条命令
    参数:
        cmd[uchar]:命令
    返回:(无)
*/
void do_cmd(uchar cmd)
{
    while(read_state()&BUSY)
        _nop_();
    RS = 0;
    RW = 0;
    DATA = cmd;    
    E = 1;
    delay_us(50);
    E = 0;
    delay_us(50);
}

/*
    函数:1602初始化
    参数:(无)
    返回:(无)
*/
void init_lcd(void)
{
    do_cmd(CLR_SCR);//清屏
    do_cmd(SCREEN_INIT);//显示模式设置
    do_cmd(SHOW_SCREEN|SHOW_CURSOR/*|FLASH_CURSOR*/);
    do_cmd(DPTR_INC);
}

/*
    函数:写一个字节到显存
    参数:
        ch[uchar]:显示字符ASCII码
    返回:(无)
*/
void write(uchar ch)
{
    uchar addr;
    while(read_state()&BUSY)
        ;
    //换行处理
    addr = read_state()&~BUSY;
    if(addr == LINE1_END)
        do_cmd(ADDR_LINE2);
    else if(addr == LINE2_END)
        do_cmd(ADDR_LINE1);
    RW = 0;
    RS = 1;
    DATA = ch;
    E = 1;
    delay_us(50);
    E = 0;
    delay_us(50);
}

void write_str(uchar line, uchar pos, uchar* str)
{
    uchar addr;
    uchar* ptr;
    if(line!=1 && line!=2)
        return;//只能是第1,2行
    if(pos>16)
        return;//只能是第 1~16 个字符
    //pos=0表示从当前位置开始写,忽略行
    if(pos){
        addr = (line==1?ADDR_LINE1:ADDR_LINE2)+pos-1;
        do_cmd(addr);
    }
    for(ptr=str; *ptr; ptr++){
        write(*ptr);
        delay_10ms(80);
    }
}

#if 0
void main(void)
{   
    uchar str[16] = {0};
    uchar x;
    delay_10ms(10);
    init_lcd();
    write_str(1,1,"012345671");
    delay_10ms(200);
    write_str(2,1,"AbCdEfGhIjK");
    delay_10ms(200);
    write_str(1,1,"Nv Hai Bu Ku!");
    delay_10ms(200);
    do_cmd(CLR_SCR);
    do_cmd(SHOW_SCREEN|FLASH_CURSOR);
    write_str(1,1,"this is a very very very long string!");
    for(x=0; x<4; x++){
        do_cmd(HIDE_SCREEN);
        delay_10ms(300);
        do_cmd(SHOW_SCREEN);
        delay_10ms(300);
    }
    do_cmd(SHOW_SCREEN);
    delay_10ms(200);
    do_cmd(CLR_SCR);
    write_str(1,1,"Screen will now Scroll....");
    delay_10ms(300);
    do_cmd(DPTR_INC|SCREEN_SCR);
    write_str(1,0,"Screen Scrolling");
    do_cmd(DPTR_DEC|SCREEN_SCR);
    write_str(1,0,"Screen Scrolling");
    do_cmd(DPTR_INC);
    delay_10ms(200);
    do_cmd(CLR_SCR);
    for(x=0x20; x<0xdf; x++){
        write(x);
        delay_10ms(80);
    }
    delay_10ms(200);
    do_cmd(CLR_SCR);
    write_str(2,1," ... what??");
    for(;;){
    }
}
#endif

女孩不哭(QQ:191035066) @ 2012-11-09 20:02:49 @ http://www.cnblogs.com/nbsofer

posted @ 2012-11-09 20:03  女孩不哭  阅读(7155)  评论(1编辑  收藏  举报