原创 12864学习笔记(串行1)

2012-11-6 00:15 1176 21 21 分类: 消费电子

接上次的话茬,在并行的驱动方式下,我们的编程的确是很省事,不过最大的不足就是,如果你的单片机能够给你使用的端口没有那么多,特别是那8个数据管脚占有的那么多的数量,看着心疼啊,所以这里介绍另一种驱动的方法,那就是串行的驱动方法。

 

串行的方式有时就不说了,但是也有缺点,那就是速度的制约,你想,原来8根数据线一同传输的数据,这时要用2根数据线进行传输,速度肯定是变慢了,具体变慢了多少呢?这个你可以自己计算一下。

 

 

下面是在Arduino中的有关的管脚的定义:

 

 

可以明显的看出来,这里的使用的管脚少了很多其实主要就是烧得数据管脚部分,现在我们如果要发送数据,其实这就是主要的功能实现的方法,用发送数据的方法告诉LCD要显示啥,在哪里显示,以及以怎样的顺序来进行显示,怎样的方式。

 

所以这样看来,以前的发送数据的函数肯定是不能够使用了,所以这里我们需要去重新写一个函数,以其能够用两根线也能完成我们需要完成的事情,这件事情其实不是很难,主要是在这里,很多事情的铺垫已经做好了。

我们再一次回到时序图,在这里面,有所有我们需要的东西,有我们的函数的书写的指导,有我们需要拉高拉低的电平,有我们需要显示字符的位置,有我们能够做的任何一件事。

 

照之前的经验,这里重写写数据函数,当然,还有读数据函数。这里的写可以这么理解,就是分为8个阶段,8个脉冲,读也是这样子来完成,那么这样的8个脉冲之前必须还要加上一些标记性的东西才行,不然LCD凭什么就能知道他应该去把之后的8个脉冲之内的数据当成他需要读取的数据或者给出的数据?恩,这就在时序图中看出来了。

 

恩,之前的准备工作还是不可以少的,所以这里贴上,基本上和之前并行的时候差不多,只不过中间使用到的发送数据的函数做了一个改头换面,所以我们的调用形式还是不变,我觉得这个其实还是很重要的,在实际的开发过程中,底层的开发人员提供一些基本的函数,而在设计这些函数之前,必须考虑到今后的改动,以及在入口参数方面做一些详尽的考虑,这样使得以后的开发少一点纠结,这也是一个好的习惯,有些参数现在可能用不到,但是可能以后会用得到,所以有的时候需要做出一些权衡,也是为了上层的工作更好的开展。

好了,闲话少说,初始化:

// set the pin mode

  pinMode(vcc_pin,OUTPUT);

  pinMode(psb_pin,OUTPUT);

  pinMode(reset_pin,OUTPUT);

  pinMode(bla_pin,OUTPUT);

  pinMode(blk_pin,OUTPUT);

  pinMode(e_pin,OUTPUT);

  pinMode(rs_pin,OUTPUT);

  pinMode(rw_pin,OUTPUT);

  pinMode(v0_pin,OUTPUT);

  pinMode(reset_pin,OUTPUT);

 

  // testing point

    digitalWrite(vcc_pin,HIGH);

    digitalWrite(bla_pin,HIGH);

    digitalWrite(blk_pin,LOW);

    digitalWrite(psb_pin,0); // set the mode to parallel

    analogWrite(v0_pin,150);

 

    digitalWrite(reset_pin,LOW);

digitalWrite(reset_pin,HIGH);

 

 

reset就是一个复位,不过这里是这样,其实不是很必须,不过复位了那就更多一点放心,而已。

 

之后是一个功能的实现。

    LCD_Init();

   

    delay(1000);

    LCD_WriteStr(1,1,shuzu);

 

这个init的函数后面会讲,之前的初始化其实是对管脚的一轮的初始定义,而在软件代码上还需要一个初始化,这里的目的就是在屏上写一串字符,字符定义在一个数组中,是:char shuzu[]={"hello"};

好了,看看具体的实现。

我们将写的函数分为两部分,一个有概括的意味:

void LCD_write_byte(unsigned char RW, unsigned char RS, unsigned char W_data)

 

还有一个是一个像是在埋头苦干的小伙:

void serial_write_byte(unsigned char dat)

 

好了,下面是这两者的代码,不过稍等一会,给出时序图先。

 

这是读写的时序,是每一次写的时候的方式表达。

还有一张图:

这是传送一个完整的8位的字节数据所经历的过程,这样我们写函数的时候就能知道是不是对了,只需要对照这样的两张图进行书写,拉高拉低电平就可以了吗很多的期间其实在时序图上是很复杂的,远远比这个要复杂很多,所以这个时候需要编写者的耐心和细心,这两样是必不可少的,做电子的,其实都是需要这个的,你不知道你所写的代码将要运行在哪一个地方,不知道谁将来回去进行借鉴和参考,并且或者是直接的应用,如果这些代码做的事情和人们的生命安全有关系,和重大的工程项目有关系,那么,你可以想见,这样的细心和耐心是必要的。

这里控制的管脚的名字似乎是不认识了吧,没有关系,其实是换了一身马甲,你还是能够认出他们的。Sclk就是e这个管脚,就是允许管脚,然后剩下的应该很好判断吧,之后的代码中你能够轻易的看出来。

下面啥都不说了,贴代码,一切尽在代码中!

void serial_write_byte(unsigned char dat)

{

 

    unsigned char i;

 

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

 

                   {

 

                            if((dat&0x80)==0){

                             clear_rw();

                             delay(2);

                             set_e();

                             delay(4);

                             clear_e();

                             delay(2);

                             clear_rw();

                        }

 

                            else{

                             set_rw();

                             delay(2);

                             set_e();

                             delay(4);

                             clear_e();

                             delay(2);

                             clear_rw();

                        }

 

 

                            dat = dat << 1;

 

 

                   }

 

}

 

 

 

 

 

void LCD_write_byte(unsigned char RW, unsigned char RS, unsigned char W_data)

 

{

 

    unsigned int H_data,L_data,S_ID = 0xf8;  //11111RWRS0

 

    if(RW == 0)                             //RW=0,MCU写一个数据到液晶;

 

      {

 

          S_ID &=~ 0x04;

 

      }

 

    else                    //RW=1,从液晶读数据到MCU

 

      {

 

         S_ID |= 0X04;

 

      }

 

    if(RS == 0)                                   //RS=1,写入的是数据

 

      {

 

         S_ID &=~ 0x02;

 

      }

 

    else                      //RS=0,写入的是指令;

 

      {

 

         S_ID |= 0X02;

 

      }

 

    H_data = W_data;

 

    H_data &= 0xf0;           //屏蔽低4位的数据

 

    L_data = W_data;          //xxxx0000格式

 

    L_data &= 0x0f;           //屏蔽高4位的数据

 

    L_data <<= 4;             //xxxx0000格式

 

    set_rs();

 

    serial_write_byte(S_ID);    //发送S_ID

 

    serial_write_byte(H_data);  //发送H_data

 

    serial_write_byte(L_data);  //发送L_data

 

    clear_rs();

 

}

 

 

 

void LCD_Init(void)

 

{

 

  delay(2);

 

  LCD_write_byte(0,0,0x30); //功能设置 8位数据,基本指令

 

 

  delay(2);

 

  LCD_write_byte(0,0,0x04); //点设定:显示字符/光标从左到右移位,DDRAM地址加1

 

  delay(2);

 

  LCD_write_byte(0,0,0x0C);  //显示设定:开显示,显示光标,当前显示位反白闪动

 

  delay(2);

 

  LCD_write_byte(0,0,0x01);  //写指令:清除显示, 清DDRAM

 

  delay(2);

 

  LCD_write_byte(0,0,0x02);  //写指令:DDRAM地址归位

 

  delay(2);

 

  LCD_write_byte(0,0,0x80);  //写指令:设置DDRAM地址,把显示地址设为0X80,即为第一行的首位

 

  delay(2);

 

 

}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
21
关闭 站长推荐上一条 /3 下一条