原创 学习使用LPC2134的IO口_结合LCD12864显示

2011-5-30 16:51 3292 25 28 分类: 消费电子

由于项目所需,所以这段时间,抽空学了一下LPC2134,它是基于ARM7核的微处理器,内部有128K的flash与16k的RAM,所以一般的处理程序,内部空间就够用了,当然你要上想在上面跑跑操作系统什么的,那就另当别论了。关于这个处理器其它方面的内部资料,如果你想了解,建议你好好翻翻它的数据手册,如果你说英文太难啃,网上有大把中文的资料,当然懒猫还是建议你看英文原版,一它是厂家的资料,比较真实可靠一般不会有什么大错,二你还可以凑这个空档学学英语,真学好了这也是你要工资的筹码。

 

今天只是实验一下它的IO端口功能,如何实验,懒猫就不再从流水灯开始了,懒猫选择从LCD12864开始,说实在看着这么大一块屏,挺吓人的,其实LCD也没有那么可怕,处理好时序就能让它乖乖的显示,所以想写好LCD12864的驱动首先还是要好好翻看它的数据手册,这里懒猫就不再详述数据手册上的内容了。不过在这里懒猫要先啰嗦一句,想让LCD12864正确显示,一定要记住先清屏,其实也就是清它内部寄存器,否则初始化时它内部的RAM中不知道是什么乱七八糟的东东,一旦你没有清屏,很可能在显示时会出现乱码或显示不正常,如下图所示:

201105230_lanmao_f1.jpg

图1-1 初始化时没有加清屏函数

其实懒猫在上大学时就试着用51写LCD12864的驱动程序,所以这次使用还算顺利,记得当时初次使用LCD12864出现这种情况,懒猫非常郁闷,以为自己的驱动程序没有写好,于是使劲翻看数据手册,仔细的看时序,最后还单步调试,发现问题还是没有解决,最后懒猫看到LCD12864中RAM时,突然想到单片机的设置变量时,初值也是随机的,于是就想着清一下RAM,结果问题还真解决了,呵呵,当时那个兴奋呀,无以言表。现在想想那时真的有点傻的可爱,网上有好多现成的程序,自己却一个人死扣自己的程序。可惜时光如梭,转眼间懒猫毕业就要两年了,那些激情燃烧的岁月已渐渐远去,却永远无法抹去我美好的记忆……

 

好了,不费话,说一说这次测试的电路,外围电路很简单,没有接什么东东,就接了一块LCD12864,2134的晶振是12MHz的,实时时钟频率是32.768KHz,下面给出仿真电路图,上面省略了很多东东,这次仿真用的是proteus7.5的版本,仿真不能代替实物,懒猫的程序都是通过实物测试通过的,仿真只是为了调试之用,如果你真想学到真本领,做项目是最好的途径。

201105230_lanmao_f2.jpg

图2 电路仿真图

注意,这是仿真电路图,实际设计中要加上电源,晶振,电位器等部件,这个电路图只说明一下LCD与LPC2134的数据接口。

 

说一下程序,程序包括main.c与display.c两个C源程序代码,只是简单的测试一下lpc2134与LCD12864为后面的实验做一个铺垫,以后的实验可能会用到这个驱动,由于程序东东比较多,所以就只贴出display.c这个源程序,其它的程序在附件中,如果有兴趣可以下载下来查看:

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

//文件名称:display.c

//功    能:LCD12864驱动函数

//作    者:懒猫爱飞

//备    注:MCU      -- LPC2134

//          Crystal  -- 12MHz

//          RTC      -- 32.768KHz  

//          开发环境 -- RealView MDK-ARM Verxion 4.12

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

#define IN_DISPLAY

 

#include "config.h"

#include "display.h"

 

//LCD12864引脚配置

#define LCD_CS1 4     /*-- P0.4 --*/

#define LCD_CS2 3     /*-- P0.3 --*/

#define LCD_RST 5     /*-- P0.5 --*/

#define LCD_DI  21    /*-- P0.21 --*/

#define LCD_RW  11    /*-- P0.11 --*/

#define LCD_EN  10    /*-- P0.10 --*/

 

//LCD12864操作宏定义

#define LCD_DE() IO0SET |= 1<    >

#define LCD_IE() IO0CLR |= 1<    >

#define LCD_RE() IO0SET |= 1<    >

#define LCD_WE() IO0CLR |= 1<    >

#define LCD_EH() IO0SET |= 1<    >

#define LCD_EL() IO0CLR |= 1<    >

 

 

//LCD12864命令宏定义

#define LCDSTARROW 0xC0    /*-- 设置起始行指令 --*/

#define LCDPAGE    0xB8    /*-- 设置页指令 --*/

#define LCDLINE    0x40    /*-- 设置列指令 --*/

 

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

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

//功    能:简短微秒级延时

//入口参数:uint32 t -- 延时长度

//出口参数:NULL

//备    注:NULL

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

void delay_us(uint32 us)

{

    while(us--);     

}

 

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

//函数名称:void Out_Data(uint8 Odata)

//功    能:向端口输出数据

//入口参数:uint8 Odata -- 要输出的数据

//出口参数:NULL

//备    注:NULL

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

void Out_Data(uint8 Odata)

{

    IO1CLR |= (uint32)(0xFF<<16);  // 将输出端口置0

    IO1SET |= (uint32)(Odata<<16); // 输出要输出的数据Odata

}

 

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

//函数名称:void Write_Data(uint8 Wdata)

//功    能:向LCD12864端口写入数据

//入口参数:uint8 Wdata -- 要写入的数据

//出口参数:NULL

//备    注:NULL

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

void Write_Data(uint8 Wdata)

{

    LCD_DE();        // 写数据使能

    delay_us(1);     // 延时等待端口电平稳定   

    LCD_WE();        // 写命令使能

    delay_us(1);     // 延时等待数据写进端口寄存器

    Out_Data(Wdata); // 输出要写入LCD12864的数据

    delay_us(1);     // 延时等待端口电平稳定

    LCD_EH();        // 数据在EN下降沿写入LCD12864中

    delay_us(3);     // 延时

    LCD_EL();        // EN下降沿

    delay_us(3);     // 延时一下

}

 

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

//函数名称:void Write_Cmd(uint8 Wcmd)

//功    能:向LCD12864端口写入命令

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

//出口参数:NULL

//备    注:NULL

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

void Write_Cmd(uint8 Wcmd)

{

    LCD_IE();        // 写命令使能

    delay_us(1);

    LCD_WE();        // 写命令使能

    delay_us(1);  

    Out_Data(Wcmd);  // 写入命令

    delay_us(1);

    LCD_EH();        // 数据在EN下降沿写入LCD12864中

    delay_us(3);    

    LCD_EL();        // EN下降沿

    delay_us(3);                                     

}

 

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

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

//功    能:LCD端口初始化函数

//入口参数:NULL

//出口参数:NULL

//备    注:NULL

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

void Init_LCDIO(void)

{

    IO0DIR |=  (1< )     >

              |(1< )<>

                                  |(1< )<>

                                  |(1< )<>

                                  |(1< )<>

                                  |(1< );<>

    IO0SET |= (1< )|(1<

    IO0CLR |= 1<

    IO0CLR |= 1< ;               >

    delay_us(50);

    IO0SET |= 1< ;               >

    delay_us(50);

    IO0SET |= (1< )|(1<

    Write_Cmd(0x3F);                     //开显示, 关显示为 -- 0x3e

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

    Write_Cmd(0x0F);                     // 开显示

    Write_Cmd(0x01);                     // 清屏

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

    Write_Cmd(0xC0);                     // 设置起始行

}

 

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

//函数名称:void Show_Row(uint8 ucPage,uint8 ucLine,uint8 ucWidth,uint8 const *ucaRow)

//功    能:在8×128的格子里显示自定义长度的一行

//入口参数:uint8 ucPage   -- 取值范围0~7

//          uint8 ucLine   -- 取值范围0~127

//          uint8 ucWidth  -- 取值范围0~127

//          ucLine+ucWidth<1128

//          uint8 const *ucaRow    -- 要显示的数组

//出口参数:NULL

//备    注:NULL

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

void Show_Row(uint8 ucPage,uint8 ucLine,uint8 ucWidth,uint8 const *ucaRow)

{

    uint8 ucCount = 0;

    if(ucLine<64)

    {

        IO0SET |= 1< ;           >

                  IO0CLR |= 1< ;<>

                  Write_Cmd(LCDPAGE+ucPage);     // 设定页号

                  Write_Cmd(LCDLINE+ucLine);     // 设定列号

                  Write_Cmd(0x34);

                  if(ucLine+ucWidth<64)          // 位于左半屏

                  {

                                for(ucCount = 0;ucCount ;uccount++)<>

                                {

                                              Write_Data(*(ucaRow+ucCount));   // 写入数据

                                }            

                  }

                  else                                    // 跨越两个半屏 先写完左半屏

                  {

                                for(ucCount=0;ucCount<64-ucLine;ucCount++)

                                {

                                               Write_Data(*(ucaRow+ucCount));              // 写入数据

                                }

 

                                IO0CLR |= 1< ;                                   >

            IO0SET |= 1< ;<>

                      Write_Cmd(LCDPAGE+ucPage);          // 设定页号

                      Write_Cmd(LCDLINE);                 // 设定列号

                                Write_Cmd(0x34); 

                                for(ucCount=64-ucLine;ucCount ;uccount++)<>

                                {

                                                Write_Data(*(ucaRow+ucCount));// 写入数据

                                }                                                                                                

                  }

    }

    else                                    // 位于右半屏

    {

                  IO0CLR |= 1< ;                                   >

        IO0SET |= 1< ;<>

                  Write_Cmd(LCDPAGE+ucPage);          // 设定页号

                  Write_Cmd(LCDLINE+ucLine-64);       // 设定列号

                  Write_Cmd(0x34);

                  for(ucCount=0;ucCount ;uccount++)<>

                  {

                                Write_Data(*(ucaRow+ucCount));  // 写入数据           

                  }

    }

}

 

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

//函数名称:void Show_Onehz(uint8 ucPage,uint8 ucLine,uint8 const *ucaChinMap)

//功    能:将16×16汉字显示在8×128的格子里

//入口参数:uint8 ucPage -- 取值范围 0~7

//          uint8 ucLine -- 取值范围 0~127

//          int8 const *ucaChinMap -- 要显示的汉字数组

//出口参数:NULL

//备    注:NULL

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

void Show_Word(uint8 ucPage,uint8 ucLine,uint8 const *ucaChinMap)

{

    Show_Row(ucPage,ucLine,16,ucaChinMap);                                      // 汉字上半部分

    Show_Row(ucPage+1,ucLine,16,ucaChinMap+16);                          // 汉字下半部分

}

 

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

//函数名称:void Display_HZ(uint8 pagenum,uint8 colnum,uint8 num)

//功    能:LCD显示汉字

//入口参数:uint8 pagenum -- 页码

//          uint8 colnum  -- 列数

//          uint8 num     -- 第几个汉字

//出口参数:NULL

//备    注:NULL

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

void Display_HZ(uint8 pagenum,uint8 colnum,uint8 num)

{

  //uint8 k;

  uint8 const *p1;

  //k=colnum*16;

  p1=hz_mode[num];

  Show_Word(pagenum,colnum,p1);

}

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

//函数名称:void Show_Char(uint8  ucPage,uint8  ucLine,uint8  const *ucaCharMap)

//功    能:将8×16字符显示在8×128的格子里。

//入口参数:uint8  ucPage – 要写入的页

//           uint8  ucLine – 要写入的列

//           uint8  const *ucaCharMap – 要写入的数值

//出口参数:NULL

//备    注:NULL

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

void Show_Char(unsigned char ucPage,unsigned char ucLine,unsigned char const *ucaCharMap)

{

    Show_Row(ucPage,ucLine,8,ucaCharMap);

    Show_Row(ucPage+1,ucLine,8,ucaCharMap+8);

}

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

//函数名称:void Clear_Screen()

//功    能:清屏函数

//入口参数:NULL

//出口参数:NULL

//备    注:NULL

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

void Clear_Screen()

{

   uint8 i,j;

   for(i=0;i<8;i+=2)   //共8页

   {

      for(j=0;j<128;j+=8)     //共128列

      {

        Show_Char(i,j,CHAR_B);

      }

   }

}

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

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

//功    能:LCD初始化函数

//入口参数:NULL

//出口参数:NULL

//备    注:NULL

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

void Init_LCD(void)

{

    Init_LCDIO();    // 初始化LCD接口

    Clear_Screen();  // 要先清屏,不然会显示不正常

 

    /*-- 以下显示函数显示“懒猫爱飞,学习日志” --*/

    Display_HZ(2,0,10);     // 懒

    Display_HZ(2,16,11);    // 猫

    Display_HZ(2,32,12);    // 爱

    Display_HZ(2,48,13);    // 飞

 

    Display_HZ(3,64,14);    // 学

    Display_HZ(3,80,15);    // 习

    Display_HZ(3,96,16);    // 日

    Display_HZ(3,112,17);   // 志

}

当然这个程序还不完善,还没显示图片的函数,以后会慢慢加上的,现在还只是在LPC2134中裸奔,主要是为了了解一下它内部结构与内部资源,以后的资料会涉及到ucos可其它嵌入式系统,这个慢慢再总结。

好了,今天说就先到这吧

最后再吼一下懒猫的口号:

 

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

 

文章评论3条评论)

登录后参与讨论

用户1406868 2012-9-30 06:01

能够在低于10毫瓦的电压下工???有吗?

用户1409914 2012-5-18 22:05

没有找到下载的附件哦

100325258_284169027 2012-4-12 20:37

难说啊,不一定按套路出牌的

用户1247239 2012-4-12 17:33

开始不信,细看很有道理

用户1295444 2012-4-12 15:42

ARM公司在研发采用了乱序执行设计的Cortex-A9芯片过程中积累了部分经验,但是在其新的Cortex-A15设计方案中,ARM将会为每一个执行单元提供独立的预留缓存空间(指令队列)。 这里是说每个执行部件具有独立的指令队列?查看了一下Cortex-A15的文档没有相关描述

用户1646898 2012-4-12 13:43

看了一半

用户1627826 2012-4-12 09:47

分析的很好 很强大

用户1635994 2012-4-12 09:18

恩,很有说服力。感觉主要还是Intel没有推出相关移动领域的产品。SSD IDF 2012 Intel大会上,Intel就展出了很有竞争性的产品,共同期待~~

用户1410841 2012-4-12 09:15

很好谢谢

用户1249549 2011-5-31 23:47

hao
相关推荐阅读
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...
我要评论
3
25
关闭 站长推荐上一条 /2 下一条