本帖最后由 kk5290122 于 2013-6-17 19:34 编辑
前段时间刚与大家分享了如何使用PSOC3并行驱动LCD12864液晶,应各位热心坛友的支持,今天再和大家分享一下如何使用PSOC3串行驱动LCD12864液晶。 我想大家对串行和并行应该都有一定的了解,并行就是将每一个数据字节的各位用多条数据线同时进行传送,一次可以发送多位数据,每一位数据都需要一条传输线,显然此时需要的数据传输线也就会相应增加许多;而串行则是将数据字节按一位一位的形式在一条传输线上逐个传送,此时只需要一条数据线,外加若干控制线就可以完成信号的传输。由于串行方式一次只能传送一位数据,所以传输速率在相同的条件下明显会比并行传输慢许多,但这样所带来的好处就是传输线的大量减少,尤其是在长距离传输时,可以大幅降低成本,这对用户来说是一个相当大的优势;相对于串行方式,并行方式则传输速度较快,控制也比串行方式简单,但由此而付出的代价也正是传输线的增加所带来的成本的大幅增加。 总之串行方式和并行方式各有利弊,我们在使用时要根据自身的实际需要来择优选取,在近距离和对传输速率要求比较高的地方我们一般选择并行方式,而在远距离和对传输速率要求不高的地方我们则通常会选择串行方式。 既然我们上面提到了串行和并行的不同之处,下面我们就针对我们的具体工程来说一下用PSOC3来实现这两种方式的相同和不同之处。首先要声明的一点是,在上次并行驱动的介绍时我们使用了控制寄存器,为了避免与上次的重复以及体现使用控制寄存器与不使用控制寄存器的区别我们这里就只使用Creator模块组件中的引脚组件来建立我们的工程。 我们这里主要是介绍用PSOC3来实现这两种方式的不同之处,打开这两种方式在Creator中所建立的原理图,如下图1和2所示。我们明显可以看到串行方式比并行方式少了右边的8条数据线(Pin_DATA引脚),而左边的4条线则是二者为了实现各自的信号控制所需要的控制线,其中在并行方式原理图中Pin_RS、Pin_RW和Pin_EN分别是LCD12864液晶的数据/命令选择端、读写选择端和使能端;而在串行方式原理图中Pin_CS、Pin_SID和Pin_SCLK则分别是LCD12864液晶的串行片选端、串行数据端和串行同步时钟端,而Pin_PSB则是二者共有的串并行选择端。分别根据液晶的串行和并行读写操作时序来操作不同的控制线就可以实现对液晶的串行和并行操作。当然由于串行和并行所需要的引脚数不同,在引脚配置里面也就会有相应差别,具体差别大家可以下载工程文件查看。
图1:串行驱动原理图
图2:并行驱动原理图
下面我们就来具体介绍一下LCD12864液晶的串行读写操作时序,液晶的串行读/写操作时序如下图3所示:
图3:LCD12864液晶串行读写时序
其中: (1) CS:液晶的片选信号线,每次在进行数据操作时都必须将CS端拉高。 (2) SCLK:串行同步时钟线,每操作一位数据都要有一个SCLK跳变沿,而且在这里是上升沿有效。也就是说,每次SCLK由低电平变为高电平的瞬间,液晶控制器将SID上的数据读入或输出。 (3) SID:串行数据,每一次操作都由三个字节数据组成,第一字节向控制器发送命令控制字,告诉控制器接下来是什么操作,若为写指令则发送11111000,若为写数据则发送 11111010。第二字节的高4位发送指令或数据的高4位,第二字节的低4位补0。第三字节的高4位发送指令或数据的低4位,第三字节的低4位同样补0。
有了上面的时序图,以及对相应控制线的操作说明,我们就可以像并行操作那样通过读写相应的引脚来编写我们的底层驱动函数了,这也正是并行驱动与串行驱动在软件方面最大的区别了。我们只需把并行驱动中对液晶进行写指令和写数据的底层驱动函数按照串行操作的时序分别对不同的控制引脚进行读写操作,其他的例如主函数,只要保证这两个底层驱动函数的函数名一样,无需任何改动就可以实现对液晶的串行驱动。下面是这两个底层驱动函数的具体代码,我这里使用的函数与并行时有所不同,大家可以参看注释,在此就不做具体说明了。
/*串行写指令到LCD*/
void LCD_Serial_Send_Command(uchar serial_cmd)
{
uchar i,in_data; //
while(LCD_Read_Busy()); //
in_data=0xf8; //发送写指令控制命令
Pin_CS_Write(1); //片选信号拉高,有效
for(i=0;i<8;i++) //发送第1个字节,将8位控制命令由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
in_data=serial_cmd;
in_data&=0xf0; //取要发送指令命令的高4位
for(i=0;i<8;i++) //发送第2个字节,将8位指令数据的高4位由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
in_data=serial_cmd; //
in_data<<=4; //左移4位,取要发送指令命令的低4位
for(i=0;i<8;i++) //发送第3个字节,将8位指令数据的低4位由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
Pin_CS_Write(0); //完成指令发送,片选拉低
CyDelay(10); //延时10ms
}
/*串行写数据到LCD*/
void LCD_Serial_Send_Data(uchar serial_data)
{
uchar i,in_data; //
while(LCD_Read_Busy()); //
in_data=0xfa; //发送写数据控制命令
Pin_CS_Write(1); //片选信号拉高,有效
for(i=0;i<8;i++) //发送第1个字节,将8位控制命令由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
in_data=serial_data;
in_data&=0xf0; //取要发送数据命令的高4位
for(i=0;i<8;i++) //发送第2个字节,将8位数据的高4位由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
in_data=serial_data; //
in_data<<=4; //左移4位,取要发送数据命令的低4位
for(i=0;i<8;i++) //发送第3个字节,将8位数据的低4位由高到低1位1位的送到串行数据端
{
Pin_SCLK_Write(0);
Pin_SID_Write((bit)(in_data&0x80));//最高位送数据端
Pin_SCLK_Write(1); //产生时钟上升沿,数据有效
in_data=in_data<<1; //数据左移1位
}
Pin_CS_Write(0); //完成数据发送,片选拉低
CyDelay(10); //延时10ms
}
到此PSOC3对LCD12864液晶的串行驱动也基本分享完毕,此外在学习串行驱动的过程中我还解决了一个上次使用控制寄存器组件的并行驱动中所遇到的一个问题:液晶读忙函数的实现。由于上次用到了控制寄存器组件,没能实现,而这次只用了引脚组件,只要在并行驱动中把引脚组件的配置属性设为双向的,就可以实现液晶的读忙函数。而且在串行驱动中也实现了读忙函数,大家不妨看一下串行驱动中读忙函数的实现技巧,想必会有所收获的,下面是几张实现的实际效果图,大家明显可以看出串行驱动比并行驱动少用了很多线在,在连线较多的情况下一般都可以使用串行驱动。
LCD12864Serial.zip
(1.78 MB)
|