原创 AVR学习日志(五十三)—学习使用LCD12864

2010-12-5 18:32 5401 7 9 分类: MCU/ 嵌入式

      


       


好久没有搞液晶显示了,这两天学习了一下LCD12864点阵液晶,LCD12864在市面上主要分为两种,一种是带字库的,控制芯片一般是st7920,因为它带中文字库,所以价格自然就高一些了;还有一种是不带字库的,它的控制芯片一般是KS0108,虽不带字库,但由于是点阵式的所以一样可以让它显示汉字。关于它的驱动不是很难,其实就是单片机的IO口操作,但是在写它的驱动之前建议你好好看看它的数据手册,还有它的指令集及读写时序,这是非常重要的哦。附件中有我的调试程序时用的仿真电路,它仅仅是调试程序时用。具体硬件电路怎么设计,请参阅相关数据手册。


       好了,硬件不多说了,不是把我的程序贴上来吧:


    


//---------------------------------------------------------------------------------


// 一些关于LCD的宏定义,方便调用


//---------------------------------------------------------------------------------


// 空指令延时


#define NOP()            asm("nop")


 


// LCD起始行/页/列指令定义


#define LCD_START_ROW    0xC0          // 起始行


#define LCD_PAGE        0xB8          // 页指令


#define LCD_COL          0x40          // 列指令


 


// 液晶控制引脚定义


#define RW               PC0           // 读写引脚


#define DI               PC1           // 数据指令


#define EN               PC2           // 使能


#define CS1              PC3           // 右半屏选择


#define CS2              PC4           // 左半屏选择


#define RST              PC5           // 复位


 


// 液晶端口


#define LCD_PORT         PORTA         // 液晶DB0-DB7


#define LCD_DDR          DDRA          // 设置数据方向


#define LCD_PIN          PINA          // 读状态数据


#define LCD_CTRL         PORTC         // 液晶控制端口


 


// 液晶端口定义


#define RW_H()           LCD_CTRL |= _BV(RW)


#define RW_L()           LCD_CTRL &= ~_BV(RW)


 


#define DI_H()           LCD_CTRL |= _BV(DI)


#define DI_L()           LCD_CTRL &= ~_BV(DI)


 


#define EN_H()           LCD_CTRL |= _BV(EN)


#define EN_L()           LCD_CTRL &= ~_BV(EN)


 


#define CS1_H()          LCD_CTRL |= _BV(CS1)


#define CS1_L()          LCD_CTRL &= ~_BV(CS1)


 


#define CS2_H()          LCD_CTRL |= _BV(CS2)


#define CS2_L()          LCD_CTRL &= ~_BV(CS2)


 


#define RST_H()          LCD_CTRL |= _BV(RST)


#define RST_L()          LCD_CTRL &= ~_BV(RST)


//-----------------------The end-------------------------------------------------


 //-------------------------------------------------------------------------------


//  some functions about LCD


//-------------------------------------------------------------------------------


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


//函数名称:void wait_lcd_ready(void)


//功    能:等待LCD就绪


//入口参数:NULL


//出口参数:NULL


//备    注:NULL


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


void wait_lcd_ready(void)


{


    unsigned char busy_check;


    do{  


     LCD_DDR  = 0x00;  // 配置数据端口为输入


    LCD_PORT = 0xff;  // 设置内部上拉


     RW_H();


     NOP();


     DI_L();          // 读状态寄存器


 


     busy_check = (LCD_PIN & 0x80);


 


     EN_H();


     NOP();


     EN_L();


}while(busy_check == 1);



 


}


 


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


//函数名称:void lcd_write_cmd(uint8_t cmd)


//功    能:向LCD发送命令


//入口参数:cmd -- 要写入的命令


//出口参数:NULL


//备    注:NULL


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


void lcd_write_cmd(unsigned char cmd)


{


wait_lcd_ready();  // 等待液晶就绪


LCD_DDR  = 0xff;   // 设置为输出方向


LCD_PORT = 0xff;   // 初始时为全高


 


//CS1_H();


//CS2_H();


RW_L();


NOP();


DI_L();           // 写命令寄存器 0 -- 命令寄存器  1 -- 数据寄存器


 


LCD_PORT = cmd;   // 要写入的命令


 


EN_H();           // 使能液晶,写入命令 


NOP();


EN_L();


 


}


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


//函数名称:void lcd_write_dat(uint8_t dat)


//功    能:向LCD发送数据


//入口参数:dat -- 要写入的数据


//出口参数:NULL


//备    注:NULL


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


void lcd_write_dat(unsigned char dat)


{


wait_lcd_ready();  // 等待液晶就绪


LCD_DDR  = 0xff;   // 设置为输出方向


LCD_PORT = 0xff;   // 初始时为全高


 


    RW_L();


NOP();


DI_H();            // 写数据寄存器


 


    if(Reverse_Display == 1)


{


     LCD_PORT = dat;


}


else


{


     LCD_PORT = ~dat;  


}


   


//DI_L();


EN_H();           // 使能液晶,写入数据


NOP();


EN_L();


 


}


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


//函数名称:void lcd_init(void)


//功    能:LCD实始化


//入口参数:NULL


//出口参数:NULL


//备    注:NULL


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


void lcd_init(void)


{


lcd_write_cmd(0x3f);    //开显示, 关显示为 -- 0x3e


    _delay_ms(15);


    /*


       lcd_write_cmd(0x38);      //8位形式,两行字符。


_delay_ms(15);


lcd_write_cmd(0x0f);     //开显示。


_delay_ms(15);


lcd_write_cmd(0x01);     //清屏。


_delay_ms(15);


lcd_write_cmd(0x06);     //画面不动,光标右移。


_delay_ms(15);


     */


lcd_write_cmd(LCD_START_ROW);    //设置起始行。


_delay_ms(15);  


}


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


//函数名称:void lcd_common_show(uint8_t P,uint8_t L, uint8_t n,uint8_t *r)


//功    能:通用显示函数,从P页的第L列显示n个字节数据


//入口参数:uint8_t P   -- 第p页,取值范围0-7


//          uint8_t len -- 第L列,取值范围0-127


//          uint8_t n   -- n个字节


//          uint8_t *r  -- r所指向的缓冲


//出口参数:NULL


//备    注:第字节8位是垂直显示的,高位在上,低位在下,每个8*128的矩形区域为一页


//          整个LCD又由64*64的左半屏和64*64的右半屏构成


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


void lcd_common_show(unsigned char P,unsigned char L, unsigned char n,unsigned char *r)


{


uint8_t i;


if(L < 64)     //从左半屏显示


{


     CS1_H();   //选择左半屏


     CS2_L();


        lcd_write_cmd(0x34);             //扩展指令集


     lcd_write_cmd(LCD_PAGE + P );    //选择起始页


        lcd_write_cmd(LCD_COL + L );     //选择起始列


     lcd_write_cmd(0x30);             //绘图显示开


 


        if((L + n)<64)


     {


          for(i=0; i<n; i++)


          {


               lcd_write_dat(r);


          }


     }


     //如果越界则跨越左右半屏显示


     else


        {


          //左半屏显示部分


            for(i=0; i<(64-L); i++)


          {


               lcd_write_dat(r);


          }


 


          //右半屏显示处理


          CS1_L();


          CS2_H();      //选择右半屏


          lcd_write_cmd(0x34);             //扩展指令集


            lcd_write_cmd(LCD_PAGE + P );    //选择起始页


            lcd_write_cmd(LCD_COL);          //右半屏起始列


            lcd_write_cmd(0x30);             //绘图显示开


 


 


          for(i=(64-L); i<n; i++)


          {


               lcd_write_dat(r);


          }


     }


}


    //全部显示右半屏


else


{


     CS1_L();


     CS2_H();                        //选择右半屏


     lcd_write_cmd(0x34);            //扩展指令集


     lcd_write_cmd(LCD_PAGE + P );   //选择起始页


     lcd_write_cmd(LCD_COL+L-64);    //右半屏起始列


     lcd_write_cmd(0x30);            //绘图显示开


 


     for(i=0; i<n; i++)


     {


          lcd_write_dat(r);


     }


}


}


 


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


//函数名称:void display_816_char(uint8_t P,uint8_t L,unit8_t *M)


//功    能:显示一个8*16点阵字符


//入口参数:uint8_t P   -- 第P页


//          uint8_t len -- 第L列


//          uint8_t *M  -- M所指向的缓冲


//出口参数:NULL


//备    注:NULL


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


void display_char(unsigned char P,unsigned char L,unsigned char *M)


{


lcd_common_show(P,  L,8,M);       //显示上半部分8*8


    lcd_common_show(P+1,L,8,M+8);   //显示下半部分8*8


}


 


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


//函数名称:void display_word(uint8_t P,uint8_t L,unit8_t *M)


//功    能:显示一个16*16点阵汉字


//入口参数:uint8_t P   -- 第P页


//          uint8_t len -- 第L列


//          uint8_t *M  -- M所指向的缓冲


//出口参数:NULL


//备    注:NULL


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


void display_word(unsigned char P,unsigned char L,unsigned char *M)


{


lcd_common_show(P,  L,16,M);       //显示上半部分16*8


    lcd_common_show(P+1,L,16,M+16);    //显示下半部分16*8


}


 


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


//函数名称:void display_word_string(uint8_t P,uint8_t L,unit8_t *M)


//功    能:显示一个16*16点阵汉字


//入口参数:uint8_t P   -- 第P页


//          uint8_t L   -- 第L列


//          uint8_t n   -- n个汉字


//          uint8_t *M  -- M所指向的缓冲


//出口参数:NULL


//备    注:NULL


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


void display_word_string(unsigned char P,unsigned char L,unsigned char n,unsigned char *M)


{


    uint8_t i;


for(i=0; i<n; i++)


{


    display_word(P,L,M);


     L = L+16;            // 因为一个汉字占16*16个点阵,即一个汉字要点16列,16行


     M = M+32;            // 共需要32个字符


}


}


 


//-------------------------------The end-----------------------------------------


上面这些是关于液晶驱动的一些函数,至于其它的函数也没有什么了,就只剩下一些头文件与一个主函数了,下面是测试的主函数:


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


//函数名称:int main(void)


//功    能:主函数


//入口参数:NULL


//出口参数:NULL


//备    注:NULL


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


int main(void)


{


Reverse_Display = 1; 


 


port_init();   // 端口初始化


lcd_init();    // LCD初始化


 


display_word_string(2,32,4,(uint8_t *)dis_code); //从第2页32列开始显示4个汉字  


Reverse_Display = 0;


display_word_string(4,4,7,(uint8_t *)(dis_code+128));     //从第2页32列开始显示4个汉字 


 


while(1);


 


return 0;


}


附件是有源程序代码及仿真电路还有一些说明,需要的话可以下载下来看看,好了今天先到这吧,这只是开始,并不是结束,路还很长,懒猫该继续修行去了……


 


再喊一下口号:


 


每天进步一点点,开心多一点^_^


 

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户1825580 2015-1-7 22:15

很不错

用户431930 2012-11-10 19:16

最近在用在学习M16,下载来学习下,多谢分享,期待更多好文章。
相关推荐阅读
xucun915_925777961 2013-04-28 11:31
毕业后的五年拉开大家差距的原因在哪里?【转】
  有人工作,有人继续上学,大家千万不要错过这篇文章,能看到这篇文章也是一种幸运,真的受益匪浅,对我有很大启迪,这篇文章将会改变我的一生,真的太好了,希望与有缘人分享,也希望对有缘人有所帮助!...
xucun915_925777961 2013-03-31 20:28
职场大牛精彩总结:职场上,如何做人做事做管理【转】(文/张子阳)
      大道至简,越是根源和基本的问题,道理实际上越简单。关于如何做人、做事、做管理的书很多,我看得不多,但是我觉得这些书更多是侧重技术和实现细节上的,而很少从人的思想和观念去讲。实际...
xucun915_925777961 2013-03-28 14:03
介绍几种优秀的UML工具
统一建模语言(UML是 Unified Modeling Language的缩写)是用来对软件密集系统进行可视化建模的一种语言。UML为面向对象开发系统的产品进行说明、可视化、和编制文档的一种标准语言...
xucun915_925777961 2013-03-27 18:05
IAR EW FOR 8051 修改工程名称的方法
        近段时间一直在搞蓝牙4.0的开发任务,所以用到了IAR编译器,话说IAR编译器用途蛮广,可以编译MSP430,ARM,还有TI的51核芯片,当然,这要不同的版本,我现在用的是for...
xucun915_925777961 2013-03-26 16:40
Cortex-M3学习日志(八)-- TFT实验Part(a)
    自己用的LPC1768的开板带有一块2.4寸的TFT彩色液晶屏,虽然自己工作中还用不过显示屏,但是晚上闲着也是闲着,于是继续玩咱的LPC1768吧。 我的开发板上的液晶屏的用的是SPI接口,当...
xucun915_925777961 2013-03-25 20:48
说说那几款查看源代码的工具
说说那几款查看代码的工具 今天给大家介绍几款单片机工程师所喜欢的几款查看源代码的工具,这几款工具在懒猫的日常工作中可是帮了不少忙。 一、 Source Insight     Source Insig...
EE直播间
更多
我要评论
2
7
关闭 站长推荐上一条 /1 下一条