12864ST7565P液晶驱动Word文件下载.docx
- 文档编号:16339868
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:29
- 大小:1.15MB
12864ST7565P液晶驱动Word文件下载.docx
《12864ST7565P液晶驱动Word文件下载.docx》由会员分享,可在线阅读,更多相关《12864ST7565P液晶驱动Word文件下载.docx(29页珍藏版)》请在冰豆网上搜索。
。
“?
”页地址的设置。
假设输入0xb0,也就是页地址0。
那么关于设置列地址的命令是0x1?
和0x0?
命令0x1?
的“?
”是列地址的“高四位”,0x0?
的“?
”是列地址的“低四位”。
假设输入0x10,0x00,也就是说列地址是8'
b0000_0000,亦即0。
假设我要设置页地址1(00000001),和列地址65(01000001)。
那么我需要输入:
0xb1;
0x14;
0x01;
通过几页的内容,我只是要读者明白ST7565P芯片驱动液晶的规则和一些基本的概念,真正的好戏儿在后头。
上图是在黑金开发板上的12864液晶原理图。
对于串行输入模式的液晶来说,重要的引脚有P/S,CS,A0,DB6(SCL)和DB7(SDI)而已。
ST7565P芯片可以支持3种传输模式,当然最简单的传输模式还是SPI模式,然而控制“传输模式的引脚”就是P/S。
当P/S被拉低时就是表示“串行传输模式”。
CS是使能信号(低电平有效)。
A0是命令或者数据决定信号(0=命令,1=数据)。
SCL是串行时钟信号,SI是串行输入信号。
至于其他的引脚属性自己去查相关的数据手册吧,这里只说重要的引脚而已。
上图是ST7565P芯片,SPI传输的时序图。
从图中我们可以明白,SI读取数据都是在SCL信号的上升沿。
在这里我再重复一下:
CS是使能信号。
SI是串行数据输入信号。
SCL是串行时钟信号。
AO是决定当前的SI信号上的是命令还是数据(1=数据,0=命令)。
在顺序操作上(以C语言为例),ST7565P芯片液晶的简易驱动概念如下:
01
//建立最基本的传输函数
02
SPI_Send{unsigned
char
Data}{}
03
04
//建立传输数据函数
05
Send_Data(unsigned
Data)
06
{
07
A0=1;
SPI_Send(Data);
08
......
09
}
10
11
//建立传输命令函数
12
Send_Command(unsigned
Data)
13
14
A0=0;
15
16
17
18
//建立初始化函数
19
Initial_Function()
20
21
//液晶显示初始化配置
22
Send_Command(0xaf);
//液晶使能
23
Send_Command(0x40);
//开始显示
24
Send_Command(0xa6);
//此命令表达1=点亮,0=点灭
25
26
//扫描次序配置
27
Send_Command(0xa0);
//列扫描向左至右
28
Send_Command(0xc8);
//也扫描从上至下
29
30
//内部电源配置
31
Send_Command(0xa4);
32
Send_Command(0xa2);
33
Send_Command(0x2f);
34
Send_Command(0x24);
35
Send_Command(0x81);
//背光LED配置命令
36
//背光LED配置值
37
38
39
//绘图函数
40
Draw_Fucntion()
41
42
for(
int
page=0;
page<
8;
page++)
43
44
Send_Command(0xb0|page);
//设置页地址
45
Send_Command(0x10);
//设置列地址“高四位”-0000
46
Send_Command(0x00);
//设置列地址“第四位”-0000
47
48
x=0;
x<
128;
x++)Send_Data(*pic++);
49
50
51
52
//主函数
53
main(
void
)
54
55
Initial_Function();
56
Draw_Function();
57
58
whiel
(1);
//停止
59
在顺序操作中,我们会先建立最基本的SPI_Send()函数,然后基于SPI_Send()函数又建立Send_Data()和Send_Command()等函数。
接下来,会基于Send_Command()函数建立Initial_Function()函数,和基于Send_Data()函数建立Draw_Fucntion()函数。
最后在主函数中调用Initial_Function()和Draw_Function()函数。
在4-1章我说过了,顺序操作如同吃饭那样,有“步骤的概念”,然而顺序操作的语言都是偏向高级语言,所以在编辑上占到许多好处。
很多重要的指令都是被隐性处理,如函数的调用指令和返回指令等。
在上述的内容中,一些高级函数无视了许多隐性指令,只要简单的多次嵌入低层函数,就能形成Initial_Function()和Draw_Function()等高级函数。
此外函数的调用也有很方便。
那么VerilogHDL语言要如何模仿顺序操作呢?
SPI发送模块
上图所示是要建立的功能模块,spi_write_module.v亦即spi发送模块。
为了最大发挥VerilogHDL语言特性,SPI_Data和SPI_Out的位配置如下:
SPI_Data
[9]
[8]
[7..0]
CS
A0
Data
SPI_Out
[3]
[2]
[1]
[0]
SCL
SI
在这里需要重申几个常常容易被疏忽的重点:
我们知道SPI的时钟信号在“上升沿”的时候是“锁存数据”,在时钟信号的“下降沿”是“设置数据”。
但是在单片机上编写SPI写函数,或者调用单片机SPI硬件资源来执行SPI写操作,我们常常会忽略了这些具体的细节。
(那些有关使用单片机SPI硬件资源的事儿,我什么都不想说,因为这样的做法什么也学不到。
SPI_Send(unsignedcharData)
CS=0;
SCL=0;
for(inti=0;
i<
i++)
if(Data&
0x80)SI=1;
elseSI=0;
Data<
<
=1;
SCL=0;
SCL=1;
SCL=1;
(7-i))SI=1;
上面有两个SPI_Send函数,左边的写法是最常用,但是也是最容易忽略小细节。
相比右边的写法比较谨慎,以最低的方法去符合一写小细节。
对于SPI时钟信号,在空闲的时候总是处于高电平(几乎所有与上升沿有关的信号,在默认状态下都是处于高电平)。
SPI时钟信号在下降沿“设置”SI数据(主机数据移位操作),反之SPI时钟信号在上升沿“锁存”数据(从机读取数据操作)。
很明显左边的写法没有符合这个规则,然而右边的写法却符合这个规则。
无论是左边的写法还是右边的写法,都忽略了一个致命的细节,两种写法都无法确定SPI时钟信号的时钟频率。
当然可以基于上述的写法产生更笨拙的写法,如下:
SPI_Send(unsigned
i=0;
Delay_US(10);
//添加延迟函数
else
SI=0;
哦!
这样的此法只会浪费单片机宝贵的处理资源...除非这个单片机有置入实时操作系统,否则那样的活儿将会是非常的糟糕。
虽然顺序操作的语言在“结构性”和“简易性”上,远远领先VerilogHDL语言。
但是你别忘了我们可以利用VerilogHDL语言来“模仿”顺序操作。
可能读者会误会“仿顺序操作”只是在外形上模仿“顺序操作”而已。
但是实际上,我们可以借与VerilogHDL语言本身的特性,只要稍微用心去发挥一下,读者不仅可以模仿“顺序操作”的“操作概念”,而且还可以发挥出超越“顺序操作”本身的极限。
虽然spi_write_module.v终究仅是模仿SPI_Send()函数这个部分而已,但是这不是代表我们可以拥有“只要目的,不要细节”这种盲目的态度。
spi_write_module.v
SCL的时钟频率定义为1Mhz,也就是说一个周期是1us,半周期就是0.5us。
如果以20Mhz来定时,那么计数的结果是10。
在19行定义了0.5us
第23~33行是0.5us的定时器。
但是比较不同的是,这个定时器平时不工作,当Start_Sig拉高的时候才开始计数(第30行)。
第37~64行是spi_write_module.v的核心功能。
I寄存器表示操作步骤,rCLK寄存器表示SCL然而rDO寄存器表示SI。
如同前面所述那样,SCL时钟信号,处于空闲状态时是出于高电平,所以rCLK复位与逻辑1(46行)。
在这里稍微提醒一下:
SPI_Data:
第9位表示CS,第8位表示A0,第7..0位表示一字节数据。
SPI_Out:
第3位表示CS,第2位表示A0,第1位表示SCL,第0位表示SI。
当Start_Sig拉高的同时,定时器开始计数(30行),该模块也开始执行(50行)。
当第一个定时产生的时候(54行),也就是第一个时钟的前半周期,亦即下降沿,rCLK设置为逻辑0。
根据SPI传输的规则,下降沿的时候主机设置数据,rDO赋予SPI_Data信号的第7位(SPI传输是从最高位开始,最低位结束),最后i递增以示下一个步骤。
当i等于1的时候并且定时产生(56行),这表示第一个时钟的后半周期,亦即上升沿,rCLK设置为逻辑1。
在SPI传输的规则中上升沿的时候,从机锁存数据,从机自己单纯的将rCLK拉高即可。
然后i递增以示下一个步骤。
上述的步骤会一直重复到第八次,直到一字节的数据发送完毕。
最后会产生一个完成信号(59~63行)。
这里有一个表达式需要说明一下:
i>
>
1:
表示i除与2。
因为右移操作也是代表除与j^2,j是右移次数。
假设8>
2,亦即8/2^2等于2。
8>
3,亦即8/2^3等于1。
最后还有一个重点就是SPI_Out的驱动(70行)。
在上面我已经重复过SPI_Out是占4位的输出。
而且每一个位都有意义。
SPI_Out第3位:
表示了CS,所以直接由SPI_Data的第9位驱动。
SPI_Out第2位:
表示了A0,同样也是直接由SPI_Data的第8位驱动。
SPI_Out第1位:
表示了SCL,以寄存器rCLK来驱动。
SPI_Out第0位:
表示了SI,以寄存器rDO来驱动。
这样的目的是简化连线的复杂度。
我们知道VerilogHDL语言的位操作是很强大。
懂得善用,会对建模提到很大的帮助。
初始化模块
乍看initial_module.v既包含了initial_control_module.v和spi_write_module.v。
spi_write_module.v前面已经说过了,至于initial_control_module.v吗~我们知道我们需要一个控制模块来执行,初始化的步骤,而该模块就是这个初衷。
initial_control_module.v
第11~17行定义了输出和输入口相关的信息,具体和图形一样。
在22行定义了rData寄存器,它是用来驱动SPI_Data(94行)。
第23行定义了isSPI_Start标志寄存器,如命名般一样,是用来驱动SPI_Start_Sig,换句话就是SPI发送模块的是能信号。
第26~88是该模块的核心部分。
当上一层将Start_Sig拉高的时候(注意:
initial_control_module.v的Start_Sig外部连线是Initial_Start_Sig),该模块就开始工作(35行)。
全核心部分都是使用“仿顺序操作”的写法。
前三个命令是液晶的“显示配置命令”(38~48行),然而我们知道要对液晶写数据的时候,CS和A0都必须拉低,由于SPI_Data位分配的关系。
rData寄存器第9..8位都是赋予2'
b00。
假设i等于0。
那么机会发送第一个命令,亦即0xaf,
(39行)一开始由于条件if没有达到,(40行)rData会被赋予2'
b00,8'
haf,并且isSPI_Start会设置位逻辑1,这时候SPI发送模块就会开始工作。
直到SPI发送模块发送一字节数据,并且反馈一个完成信号的高脉冲(SPI_Done_Sig),if条件就会成立(39行),然后isSPI_Start就会被设置为逻辑0,然后i递增以示下一步步骤。
类似上面的操作会一直重复,直到完成发送3个“显示配置命令”,2个“扫描次序配置命令”,和6个“内部电源配置命令”(38~80行)。
直到最后该模块会反馈一个完成信号给上一层模块(82~86行),并且(83行)复位rData寄存器(前两位必须设置为逻辑1,而后八位可以是任意值)。
initial_module.v
initial_module.v是initial_control_module.v和spi_write_module的组合模块。
连线关系基本上和“图形一样”。
有一点可能会使读者们困惑。
因为“低级建模”的全部功能不可能在一个模块中完成,多多少少,读者们会对模块与模块之间的关系会有“不解”的情况。
笔者在这里要求读者们要保持平常心去理解,因为VerilogHDL语言的建模本来就需要很强的逻辑性。
目前面对的难题就当做是为日后的修行吧。
绘图模块
draw_module.v是一个组合模块,同样draw_module.v有包含spi_write_module.v。
此外draw_module.v也含有draw_control_module.v和pika_rom_module.v,pika_rom_module.v是一个8bitsx1024words的rom。
draw_control_module.v控制模块主要是控制绘图的所有操作步骤,然而pika_rom_module.v包含了所需要的图片资料。
该控制模块对spi_write_module.v的链接也和initial_control_module.v一样。
draw_control_module.v
第13~20行的定义基本上都和“图形”一样,除了Start_Sig和Done_Sig比较特别,它们在外部的连线时Draw_Start_Sig和Draw_Done_Sig。
第31~67行是该模块的核心部分,但是别被它吓到了,它不过是充气胖子。
在这里我们简单复习一下在“顺序操作”中的Draw_Function()的操作。
page++)
Send_Command(0xb0|page);
//页地址配置
//列地址高四位配置
//列地址第四位配置
x=0;
x++)Send_Data(*p++);
//发送128次列填充
上述的一段函数代码中,一个Draw_Function()函数的功能表达的一了百了,而且该函数中最大作用就是for循环,很可惜VerilogHDL语言是不推荐使用for循环。
(不要问我为什么,很多的参考书上都是这样写的,如果以我的角度说,我表示for循环不适合VerilogHDL语言的风格)。
在Draw_Function()函数之中,第一个for循环控制page,亦即页。
并且在每一个页的开始都重新配置列地址。
至于第二个for循环是用于控制128次的列填充。
那么VerilogHDL语言该如何呢?
在34~39行中,i控制执行步骤,x控制列扫描地址(列填充次数),y控制页扫描次序,rData是用来驱动SPI_Out(73行),而isSPI_Start是用来驱动SPI_Start_Sig。
当Start_Sig被拉高的时候(41行),该控制模块就开始工作。
我们先假设一个情况:
当i等于0的时候,由于if条件不成立(45行)。
由于“顺序操作”关系,必须先设置页地址,rData被赋予2'
b00(CS=0,A0=0,亦即发送命令)和y寄存器的值,Y寄存器复位值是8'
d0。
然后isSPI_Start寄存器被设置为逻辑1(46行)。
此时SPI发送模块开始工作。
当SPI发送完一字节的数据,就会反馈一个高脉冲至完成信号SPI_Done_Sig。
此时if条件就会成立(45行),isSPI_Start寄存器被设置为0,然后i递增以示下一步步骤。
当页地址设置完毕后,接下来的操作就要设置列地址。
48~50行是设置列地址的高四位,52~54行是设置列地址的第四位。
具体操作和设置也地址一样。
不一样的是,每一次设置“新一页”,列地址都必须复原为0。
当页地址和列地址设置okay后,接下来就是128次的列填充操作了。
x寄存是用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 12864 ST7565P 液晶 驱动