LCD显示

今天在写LCD的显示,用的是51单片机和Proteus仿真,但是Proteus中没有以前写的LCD5110所以只能用库中的HDG12864F-1,后来才发现这个好像是写LCM的,搞了一晚上总算是弄出来了一下贴出代码

每一个LCD驱动都要有命令和数据的写入首先是这两个代码

//CE 片选信号
//LCD_CE_OL     置低,表示选中芯片   
//LCD_CE_OH     置高,表示未选中芯片
//DC 数据命令选择
//LCD_DC_OL     置低:数据   
//LCD_DC_OH     置高:数据 
//SCLK 时钟 每个时钟的上升沿写入数据
void LCD_WrDat(uint8_t dat)
{
    uint8_t i = 8;
    LCD_CE_OL;//片选信号置低,表示选中芯片   
    LCD_DC_OH;//数据命令 置高:数据  
    LCD_SCLK_OL;
    while (i --)
    {
        if (dat & 0x80)
        {
            LCD_SDIN_OH;
        }
        else
        {
            LCD_SDIN_OL;
        }
        LCD_SCLK_OH; 
        LCD_SCLK_OL;    
        dat <<= 1;    
    }
    LCD_CE_OH;
}

void LCD_WrCmd(uint8_t cmd)
{
    uint8_t i = 8;
    LCD_CE_OL;
    LCD_DC_OL;
    LCD_SCLK_OL;
    while (i --)
    {
        if (cmd & 0x80)
        {
            LCD_SDIN_OH;
        }
        else
        {
            LCD_SDIN_OL;
        }
        LCD_SCLK_OH; 
        LCD_SCLK_OL;    
        cmd <<= 1;    
    }
    LCD_CE_OH;  
}       

其次,设定要写的位置,位置要根据芯片手册确定LCD5110和HDG12864F-1的是不一样的,一开始怎么都不对,后来看了芯片手册才发现原来就不一样

void LCD_Set_XY(uint8_t X, uint8_t Y)
{
     LCD_WrCmd(Y | 0xB0);
     LCD_WrCmd(0x10|((0xf0 & X) >> 4));//设定列地址高4位为0
     LCD_WrCmd(0x00|(0x0f & X));    //设定列地址低4位为0

}

然后是清屏函数,这个没什么大问题,只要把所有的格格写入0就可以了

void LCD_Clear(void)
{
     uint8_t t,k;
     LCD_Set_XY(0,0);
     for(t = 0; t < (HEIGHT >> 3); t++)
     {
            for(k = 0;k < WIDTH; k++)
            {
                    LCD_WrDat(0x00);
            }
     }
}

初始化函数,这个问题就大了,不同的芯片初始化是不一样的,开始怎么都出来,后来看了一下手册,duangduang的。

void LCD_Init(void)
{
    LCD_RST_OL;  //LCD(低电平)复位
    LCD_WrCmd(0xae);
    LCD_RST_OH;     // RES置高
    LCD_WrCmd(0xa2);    // LCD偏压设置:1/9 BIAS
    LCD_WrCmd(0xa1);    //列地址选择为从右到左对应0~127;0xa1:列地址从左到右;0xa0:列地址从右到左
    LCD_WrCmd(0xc0);    // 行地址从上到下为0~63;0xc0:行地址从上到下;0xc8:行地址从下到上
    LCD_WrCmd(0x26);    // V5电压内部电阻调整设置
    LCD_WrCmd(0x81);    //亮度调整命令0~63(暗到亮)
    LCD_WrCmd(0x10);    //亮度调节为双字节命令,前一个参数控制字的深浅
    LCD_WrCmd(0x2f);    //上电控制,打开调压器、稳压器和电压跟随
    LCD_WrCmd(0xaf);    //0xae:set display off。0xaf:set display on
    //LCD_WrCmd(0x60);  //其实行设置

}

接着是写入字符,我这里用的是小字符,宽度占6个点

void LCD_Write_Char(uint8_t x, uint8_t y, uint8_t c) 
{
    uint8_t i = 0;
    if ((c >= 'A') && (c <= 'Z'))
    {
        c = c - 'A' + 10;
    }
    else if ((c >= 'a') && (c <= 'z')) 
    {
        c = c - 'a' + 44;
    }
    else if (c == ' ')
    {
        c = 36;
    }
    else if (c == ':')
    {
        c = 37;
    }
    else if (c == '-')
    {
        c = 38;
    }
    else if (c == '/')
    {
        c = 39;
    }
    else if(c == '.')
    {
        c = 40;
    }
    else if (c == ',')
    {
        c = 41;
    }
    else if (c == '^')
    {
        c = 42;
    }

    if (x > 126)
    {
        x = 0;
        y ++;
    }

    LCD_Set_XY(x * 6, y);
    for (i = 0; i < 6; i++) 
    {
        LCD_WrDat(SmallChars[c * 6 + i]); 
    }

}
void LCD_Write_Num5(uint8_t x, uint8_t y, int num)
{
    LCD_Write_Char(x,     y, num / 10000);
    LCD_Write_Char(x + 1, y, num % 10000 / 1000);
    LCD_Write_Char(x + 2, y, num % 1000 / 100);
    LCD_Write_Char(x + 3, y, num % 100/10);
    LCD_Write_Char(x + 4, y, num % 10);
}
void LCD_Write_String(uint8_t x, uint8_t y, uint8_t *s)
{
    uint8_t i;

    for (i=0; s[i]!='\0'; i++)
    {
        LCD_Write_Char(x + i, y, s[i]);
    }
}
//这里的字符是16*16大小的
void LCD_Write_Chinese(uint8_t x,uint8_t y,uint8_t *China)
{
    uint8_t ii = 0;

        LCD_Set_XY(x, y);
        for(ii = 0; ii < 16; ii++)
        {           
            LCD_WrDat(China[ii]);           
        }
        LCD_Set_XY(x, y + 1);
        for(ii = 0; ii < 16; ii++)
        {           
            LCD_WrDat(China[16 + ii]);          
        }

}

接着是防止闪屏写的“双缓冲”.其实这段代码在51上没有试过,32上的内存空间很大,51上定义了一个字符数组就没有空间了,也懒的删再去试。原理是吧所有的点写到一个数组里面,然后全部写出来,这样清屏的时候只要把数组清一下就可以了,不需要刷屏,就可以防止屏闪

uint8_t data buff[HEIGHT][WIDTH]={0};
void LCD_Write_Point(uint8_t hang,uint8_t lie)
{
    buff[hang][lie] = 1;
}
void LCD_Draw(void)
{
        uint8_t dat = 0;
        uint8_t i,j,k;
        unsigned short t = 0;
        for(j = 0; j < (HEIGHT >> 3); j++)//hang
        {
            for(i = 0; i < WIDTH; i++)//lie
            {
                    for(k = 0; k < 7; k++)
                    {
                        if(buff[(j << 3) + k][i])
                            dat |= (1 << k);
                    }
                    LCD_WrDat(dat);
                    dat = 0;
            }       
        }   
}
void LCD_ClearBuff(void)
{
        uint8_t i = 0, j = 0;
        for(i = 0; i < WIDTH; i++)
            for(j = 0; j < HEIGHT; j++)
                buff[j][i] = 0;
}
//TFT上画出的线很漂亮,但是这个上面。。。。。不知道为什么
void LCD_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
    char t; 
    char xerr = 0,yerr = 0,delta_x,delta_y,distance; 
    char incx,incy,uRow,uCol; 
    delta_x = x2 - x1; 
    delta_y = y2 - y1; 
    uRow = x1; 
    uCol = y1; 
    if(delta_x > 0)
        incx = 1; 
    else if(delta_x == 0)
        incx=0;
    else 
    {
        incx = -1;
        delta_x = -delta_x;
    } 

    if(delta_y > 0)
        incy = 1; 
    else if(delta_y == 0)
        incy = 0;
    else
    {
        incy = -1;
        delta_y = -delta_y;
    } 
    if(delta_x > delta_y)
        distance = delta_x;
    else 
        distance = delta_y; 
    for(t = 0;t <= distance + 1; t++ )
    {  
        LCD_Write_Point(uRow,uCol);
        xerr += delta_x ; 
        yerr += delta_y ; 
        if(xerr > distance) 
        { 
            xerr -= distance; 
            uRow += incx; 
        } 
        if(yerr > distance) 
        { 
            yerr -= distance; 
            uCol += incy; 
        } 
    }  
}

这个东西真的很有收获,一个收获就是知道数据手册的重要性,另一个数关于双缓冲的,下一步想要来重定向

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值