Chinaunix首页 | 论坛 | 博客
  • 博客访问: 532723
  • 博文数量: 150
  • 博客积分: 5010
  • 博客等级: 大校
  • 技术积分: 1861
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-17 00:19
文章分类

全部博文(150)

文章存档

2011年(1)

2009年(14)

2008年(135)

我的朋友

分类: LINUX

2008-05-06 01:17:54

前 一段时间想搞一下点阵LCD,于是就到本网站上寻找,找到了好多资料,xiaotanlan朋友的资料很好,http: //
但是看了已后,觉得自已做的时候还是有很多要注意的地方.于是就写了下面的内容:

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 
#define uchar unsigned char
#define uint  unsigned int
#define bool  unsigned char
#define true  1
#define false 0
#define setbit(sfr,bit) (sfr|=(1<#define clrbit(sfr,bit) (sfr&=~(1<#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仿真:

原程序及仿真文件:


希望对想学LCD12864点阵液晶的朋友有所帮助.
-----此内容被zhb2000于2006-03-01,10:56:12编辑过
 
2006-03-01,10:40:49
邮件 编辑 删除
【1楼】 benladn911 AVR猎手

积分:1613
派别:
等级:------
来自:福建厦门
好贴,顶。
__________________________
MSN: lanbing51#hotmail.com     Email: lanbing51#126.com (把#号改成@号即可)
QQ:149910798     我的 AVR猎手的地盘 :
目前工作:Altium designer 6 现场技术支持(Protel FAE),欢迎和广大工程师交流软件的功能应用
A secret makes a man man... A wound makes a man man...
2006-03-01,12:22:37
编辑 删除
【2楼】 SKYdai 天空
积分:276
派别:
等级:------
来自:四川成都
好呀!谢谢!!
 
2006-03-01,20:24:02
编辑 删除
【3楼】 zhb2000

积分:246
派别:
等级:------
来自:
今天花了一整天时间才搞好LCD12863显示2色BMP图片(累啊 :) )。
自已还写了一个2色BMP图片到程序数组的转换小程序bmp2txt.exe
读取2色BMP图片,BMP的头结构我就不多说了,很多书上都有。
这里我们主要注意以下几个地方。
BMP文件偏移
0x0a        图像数据的开始位置
0x12        图像的宽度
0x16        图像的高度
0x1e        图像是否压缩
(这里我们只讨论不压缩的,用windows的画笔画一幅画存盘的时候选单色就行了)
    BMP的2色图像是倒着存放的,即第一个数据字节表示是的图像最后一行的前8
个点"1"表示白色,"0"表示黑色(当然也可跟椐调色板来设置)
    BMP图片数据每行要DWORD对齐,也是一行的字节数必须为4的倍数,如一行的数
据只有8个点为0xff 而BMP表示为 0xff 0x00 0x00 0x00

然后用bmp2txt.exe 将所画的2色图转为程序代码,copy到程序中编译就OK了。


关键代码:
/*
        读BMP图像 2色 未压缩
*/

#define BMP_HEIGHT 0x16
#define BMP_WIDTH  0x12
#define BMP_COMPRESSION 0x1e
#define BMP_bfOffBits 0x0a
//COMPRESSION
#define BI_RGB                                        0
#define BI_RLE8                                        1
#define BI_RLE4                                        2
#define BI_BITFIELDS                3
const unsigned char Bitmap[1070] PROGMEM={  //bmp2txt.exe生成的图像数据
 ......
};

void drawBitmap(const uchar *bmp)
{    //画图像
        signed char x,y;
        uchar bmpHeight,bmpWidth,wByte;
        uint  lpOffset;
        uchar dat;
        uchar nx=0;
        uchar i;
  uint  numb;
        lpOffset=pgm_read_byte(bmp+BMP_COMPRESSION);        //bmp[BMP_COMPRESSION];
        if(lpOffset!=0) return;                                        //只处理未压缩的图像
        bmpHeight=pgm_read_byte(bmp+BMP_HEIGHT);        //bmp[BMP_HEIGHT];
        bmpWidth=pgm_read_byte(bmp+BMP_WIDTH);                //bmp[BMP_WIDTH];
        lpOffset=pgm_read_byte(bmp+BMP_bfOffBits);        //bmp[BMP_bfOffBits] 得到图像数据的偏移量
        
        /*
                1.BMP图象为到着存放的:即最后一行的数据存放在最前面
                2.2色为一个字节表示一行中的8个像素点
        */
        if(bmpWidth%8!=0)
        {
                wByte=bmpWidth/8+1;
        }
        else
        {
                wByte=bmpWidth/8;
        }
        if(wByte%4!=0)
        {
                wByte=(wByte/4+1)*4;                //DWORD对齐
        }

  numb=0;
        for(y=(bmpHeight-1);y>=0;y--)
        {
                for(nx=0;nx                {
                        dat=pgm_read_byte(bmp+lpOffset+numb);// bmp[lpOffset+numb];
      numb++;
                        for(i=0;i<8;i++)
                        {
                                if(tstbit(dat,(7-i))==0)
                                {
                                        x=nx*8+i;
                                        if(x                                        {
            pixel(x,y);
                                        }
                                }
                        }
                }
        }
}

仿真图:


源程序&工具&说明:

 
阅读(1534) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~