lcd 12864液晶

来源:互联网 发布:大乐透组合软件 编辑:程序博客网 时间:2024/05/01 07:00

前一段时间想搞一下点阵LCD,于是就到本网站上寻找,找到了好多资料,xiaotanlan朋友的资料很好,http: //www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=468165&bbs_page_no=1&sub_kind_id=2065&bbs_id=1000
但是看了已后,觉得自已做的时候还是有很多要注意的地方.于是就写了下面的内容:

LCD12864液晶说明(个人跟椐datasheet的理解):
  lcd12864分为左半屏和右半屏,每半个屏幕竖着排列着64(0~63)个字节,每个字节最低位在最上面,高位在最下面,一个字节的8位构成了lcd12864一页中一列的8个点,而它共有8页,即在y方向有8*8=64个点.如下图:

画点的重点:
    1,通过x坐标所属的左右半屏.
    2,通过y坐标算出点所属的页,及一页内y坐标(即一个字节中一位的位置).
    3,读出原来要画点位字节内容,再设要画的点(否则会擦除原来画的点).
程序如下:
环境:ATmega8L, WinAVR GCC, LCD12864, Proteus6.7
/*
        ATmega8L LCD12864
        作者:zhb2000
*/
#include <avr/io.h>
#define uchar unsigned char
#define uint  unsigned int
#define bool  unsigned char
#define true  1
#define false 0
#define setbit(sfr,bit) (sfr|=(1<<bit))
#define clrbit(sfr,bit) (sfr&=~(1<<bit))
#define RS   0
#define RW   1
#define CS1  2
#define CS2  3
#define E    4
#define RST  5
#define DATA PORTB
#define CTRL PORTC

void init(void);
uchar getState(void);                        //得到LCD状态字
bool lcdBusy(void);
void lcdCommand(uchar command);                //发送命令字
void lcdOpen(void);                                //打开LCD
void lcdStartLine(uchar line);                //设置起始行
void lcdSetPage(uchar page);                        //设置页地址
void lcdSetRow(uchar row);                                //设置列地址
void lcdWrite(uchar dat,uchar cs);                                        //写显示数据,注'0'亮'1'暗
uchar lcdRead(uchar cs);                                                        //读数据
void pixel(uchar x,uchar y);                                        //画点
int main(void)
{
        init();
        lcdOpen();
        lcdStartLine(0);
        lcdSetPage(0);
        lcdSetRow(0);
        pixel(30,30);
        pixel(100,50);
        pixel(15,40);
        while(1)
        {
        }
        return 0;
}

void init()
{
        PORTB=0xff;
        DDRB=0xff;
        PORTC=0xff;
        DDRC=0xff;
        PORTD=0xff;
        DDRD=0xff;
}

uchar getState()
{
        PORTB=0xff;
        DDRB=0x0;
        clrbit(CTRL,CS1);
        clrbit(CTRL,CS2);
        clrbit(CTRL,RS);
        setbit(CTRL,RW);
        setbit(CTRL,E);                        //下降沿
        clrbit(CTRL,E);
        return PINB;
}

bool lcdBusy()
{
        uchar state=0;
        state=getState();
        if(state&0x80)
        {        //BUSY
                return true;
        }
        else
        {        //idle
                return false;
        }
}

void lcdCommand(uchar command)
{
        DDRB=0xff;
        clrbit(CTRL,CS1);
        clrbit(CTRL,CS2);
        clrbit(CTRL,RS);
        clrbit(CTRL,RW);
        DATA=command;
        setbit(CTRL,E);                        //下降沿
        clrbit(CTRL,E);
}

void lcdOpen()
{
        while(lcdBusy());
        lcdCommand(0x3f);
}

void lcdStartLine(uchar line)
{
        line|=0xc0;
        while(lcdBusy());
        lcdCommand(line);
}

void lcdSetPage(uchar page)
{
        page&=0x7;
        page|=0xb8;
        while(lcdBusy());
        lcdCommand(page);
}

void lcdSetRow(uchar row)
{        //设置列地址
        row&=0x3f;
        row|=0x40;
        while(lcdBusy());
        lcdCommand(row);
}

void lcdWrite(uchar dat,uchar cs)
{        //写显示数据
        while(lcdBusy());
        DDRB=0xff;
        if(cs==1)
        {        //选择左半屏
                clrbit(CTRL,CS1);
                setbit(CTRL,CS2);
        }
        else
        {        //选择右半屏
                clrbit(CTRL,CS2);
                setbit(CTRL,CS1);
        }
        setbit(CTRL,RS);
        clrbit(CTRL,RW);
        DATA=dat;
        setbit(CTRL,E);                        //下降沿
        clrbit(CTRL,E);
}

uchar lcdRead(uchar cs)
{        //读数据
        uchar dat;
        while(lcdBusy());        
        DDRB=0x00;
        PORTB=0xff;
        if(cs==1)
        {        //选择左半屏
                clrbit(CTRL,CS1);
                setbit(CTRL,CS2);
        }
        else
        {        //选择右半屏
                clrbit(CTRL,CS2);
                setbit(CTRL,CS1);
        }
        setbit(CTRL,RS);
        setbit(CTRL,RW);
        setbit(CTRL,E);                        //下降沿
        clrbit(CTRL,E);
        setbit(CTRL,E);                        //高
        dat=PINB;
        return dat;
}
        
void pixel(uchar x,uchar y)
{
        uchar page,dX,dY;
        uchar cs=2;
        uchar dot=0;
        if(x>=64)
        {
                x-=64;
        }
        else
        {
                cs=1;
        }
        dX=x;                                                                        //算出x坐标
        page=y/8;                                                        //算出页号
        dY=y%8;                                                                //算出y坐标
        lcdSetPage(page);
        lcdSetRow(dX);        
        dot=lcdRead(cs);
        clrbit(dot,dY);
        lcdSetPage(page);
        lcdSetRow(dX);        
        lcdWrite(dot,cs);
}

Proteus6.7仿真:

原程序及仿真文件:
点击此处下载armok01104632.rar

希望对想学LCD12864点阵液晶的朋友有所帮助.