hunter8801 发表于 2014-4-28 18:16:48

入门贴申精:128*64点阵显示屏的驱动方法及常用的显示函数

本帖最后由 hunter8801 于 2014-4-28 18:16 编辑

一些简单的函数,对于大神就不算什么,但对于初学者还是很有用的,请各位高抬贵手,帮顶顶!

8段数码管、1602、5110、12864点阵屏……这些都是最最常见的、可用于简单电子开发的显示屏。我最喜欢用点阵屏,因为它相比其他字符式的屏来说,可以用来显示任意大小的字符(包括汉字)、图片等。但点阵屏的操作方式略比其他屏复杂……如图,点阵屏要显示的内容是由相应的点按照一定的顺序“拼凑”出来的!下面要说的就是这“拼凑”的方法!
http://www.14blog.com/wp-content/uploads/2014/04/1.png
图1 点阵显示的效果
操作方式大致按图2流程来
http://www.14blog.com/wp-content/uploads/2014/04/2.png
图2 液晶屏操作大致流程

1.通信方式
SPI、I2C、并行(8080)……这些都是向屏幕发送数据的方式,首先你应该根据自己屏的情况,选择合适的通信方式,然后将MCU的通信方式配置好!注意:

传统的51单片机没有I2C或SPI功能,只能使用8080的并口方式,或者用IO口来模拟I2C或SPI通信;
8080方式的速度是最快的,但是也是最占用IO口的(通信就要8个IO口),这种屏不适合用在430、STM32这样的IO口不是很丰富的MCU上,但这些MCU一般都有硬件I2C或SPI功能;
硬件I2C或SPI比模拟I2C货SPI速度快,且更省资源,但不同芯片的配置方法不同,这里介绍用IO口模拟SPI和I2C通信的方式。
1.1 模拟SPI写数据void SPI_Write(unsigned char data)
{
unsigned char i;

CS = 0;//选中SPI设备,一般都是低电平选中
for(i=0;i<8;i++) //通过IO口产生高低电平,发送一个byte的数据(8位)
{
   CLK = 0
   if((data << i) & 0x80)
   {
   SI = 1; // SI -- slave input 从机输入
   }
   else
   {
   SI = 0;
   }
   CLK = 1;
}
CS = 1;
}1.2 模拟I2C通信 -- 模拟I2C就比SPI略复杂一些,这就是为什么它比模拟SPI略慢void IIC_Start() //开启I2C总线
{
SCL = 1;
SDA = 1;
SDA = 0;
SCL = 0;
}
void IIC_Stop() //停止I2C总线
{
SCL = 0;
SDA = 0;
SCL = 1;
SDA = 1;
}
void Write_IIC_Byte(unsigned char IIC_Byte) //通过I2C向外发送一个byte的数据
{
unsigned char i;
for(i=0;i<8;i++)
{
   if(IIC_Byte & 0x80)
   SDA = 1;
   else
   SDA=0;
   SCL = 1;
   SCL=0;
   IIC_Byte<<=1;
}
SDA=1;
SCL=1;
SCL=0;
}2.初始化

要操作点阵显示屏,这里又有一个重要的东西——写数据和写命令!让屏幕休眠、让屏幕滚动之类的操作,就要向屏幕写命令;要让屏幕显示内容,就要写数据。怎样让屏幕知道你发送的东西是数据还是命令?有的屏幕有类似D/C(Data/Command)这样的引脚,说明是通过高低电平来区分,有的屏幕是向屏幕写入特定的值来区分。 点阵屏内部都有一个驱动芯片,这个驱动芯片就负责按照程序的要求,在某一个点来进行操作。所谓的初始化就是这个驱动芯片的初始化,初始化中注意两个地方:


[*]一个是复位!这个非常重要,如果没有完全复位,可能导致屏幕不稳定、显示乱码等畸形问题!
[*]另一个就是初始化代码!这个初始化代码一般都是一些16进制数,可以在显示屏的规格书之类的文档里面找到,可以通过“写命令”的方式能够把初始化代码发送给显示屏。

完成了这些步骤,就可以让它显示你想要的东西了!先来看看写到屏幕上的数据是如何显示的:

--> 因为每次向屏幕写入一个byte的数据,每个byte的数据都有8位,所以每次至少要操作8个点,像图3这样:
http://www.14blog.com/wp-content/uploads/2014/04/3.png
图3. 每次对应点阵竖着的8个点

--> 一个byte数据的每一位分别对应哪一个点?我分别向屏幕写入了“0x0F”、“0xF0”、“0x01”、“0x02”、“0x04”、“0x08”这样一些有代表性的数据,显示效果是这样的:
http://www.14blog.com/wp-content/uploads/2014/04/4.png
图4. 对应数据来看看这张图

总结一下:从上到下第一个点为最低位,第8个点为最高位!

--> 当写完一个byte的数据后,下一组数据从哪里开始写?如图5所示:
http://www.14blog.com/wp-content/uploads/2014/04/5.png
图5. 显示的顺序

明白了这个规律,要显示一个字或符号,只要把它对应的点找出来,然后向屏幕写数据就OK了!怎么才能得到你想要显示内容的点阵呢?这个可以用软件来计算!这种软件一般被称为“取模软件”(文章结尾处附件)
http://www.14blog.com/wp-content/uploads/2014/04/6.png
图6. 推荐这样配置取模软件

3.在显示屏上显示一些东西
我们可以把取得的字模寸在数组里,然后用一个专门的文件来存放……比如codetab.h(文章结尾附件)

3.1 显示6*8的ASCII字符串
每一个字符都有独一的ASCII值,通过这一点,可以找到某一字符在codetab中的具体位置,程序中要做的就是来处理这种“查询”的过程!比如显示一个6*8的ASCII字符,可以通过下面的代码来完成:
void Char_F6x8(unsigned char x, unsigned char y, const char ch[]) //x,y对应起始点坐标,x: 0~127,y: 0~7
{
unsigned char c,i,j=0;
while(ch != '\0')
{
c = ch - 32;
if(x>125) //如果一行的点阵不够显示,就换行
{
   x=0;
   y++;
}
SetPos(x,y);//设置起始点坐标的方式是通过写命令来完成的,具体什么命令,需要你去查找产品
for(i=0;i<6;i++)
{
   WriteData(font6x8);//写数据
}
x += 6;
j++;
}
}
我在main函数中写了如下几句代码:
Char_F6x8(0,0,"Welcome to new york, happy everyday -- I know a joke about that sentence, Do U want know? pls reply or e-mail me:[email protected]");
效果是这样的:
http://www.14blog.com/wp-content/uploads/2014/04/7.png
图7. Welcome to NewYork...的笑话有人知道么?

3.2 显示8*16的ASCII字符串
上面6*8的字符,这个倒简单……因为每一个字符竖着都只有8个点,刚好是一个byte。要是想显示大一些的字符,比如说8*16的这样会占用两行的字符,怎么操作呢?
void Char_P8x16Str(unsigned char x, unsigned char y, unsigned char ch[])
{
unsigned char c=0,i=0,j=0;
while (ch!='\0')
{
   c =ch-32;
   if(x>120) //溢出即换行
   {
   x=0;
   y++;
   }
SetPos(x,y);
for(i=0;i<8;i++) //先写完上面一行的8个点
   WriteData(F8X16);
SetPos(x,y+1);
for(i=0;i<8;i++) //再写下面一行的8个点
   WriteDdata(F8X16);
x+=8;
j++;
}
}
显示效果是这样的:
http://www.14blog.com/wp-content/uploads/2014/04/8.png
图8. 惠利特自动化

3.3 显示16*16汉字
因为汉字不能通过ASCII码来查询,所以用了一种特殊的方式,我习惯将其称之为“字码索引”。先来看看汉字的字码是什么样子的:
0x80,0x80,0xC0,0x60,0x30,0x18,0x2C,0xE7,0xC7,0x0C,0x18,0x30,0x60,0xC0,0x80,0x80,
0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x82,0xC2,0x62,0x3A,0x1E,0x06,0x00,0x00,0x00,//今",0

0x40,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x40,0x40,
0x80,0x80,0xC0,0x60,0x30,0x1C,0x0F,0x03,0x03,0x0F,0x1C,0x30,0x60,0xC0,0x80,0x80,//天",1

0x40,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x40,0x40,
0x80,0x80,0xC0,0x60,0x30,0x1C,0x0F,0x03,0x03,0x0F,0x1C,0x30,0x60,0xC0,0x80,0x80,//天",2

0x20,0x30,0x5C,0x4F,0x57,0x54,0x54,0x54,0x54,0x54,0x54,0xD4,0xD4,0x04,0x04,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0x70,0xF0,0xF0,//气",3

0x00,0xFC,0xFC,0x84,0xFC,0xFC,0x44,0x54,0x54,0x54,0x7F,0x7F,0x54,0x54,0x54,0x44,
0x00,0x3F,0x3F,0x10,0x3F,0x3F,0x00,0xFF,0xFF,0x15,0x15,0x55,0xD5,0xFF,0x7F,0x00,//晴",4

0x00,0xFC,0xFC,0x25,0x27,0x26,0xFC,0xFC,0x00,0xFE,0xFE,0x22,0x22,0xFE,0xFE,0x00,
0x00,0x7F,0x7F,0x31,0x15,0x1D,0xB9,0xF1,0x70,0x3F,0x0F,0x42,0xC2,0xFF,0x7F,0x00,//朗",5
后面的0、1、2、3、4、5这样的数字,就是字码的索引,用代码这样来完成操作:
void Char_P16x16Ch(unsigned char x, y, N) //x,y是起始点坐标,N 就是对应的汉字
{
unsigned char wm=0;
unsigned int adder=32*N; //通过字码的索引来确定地址
SetPos(x , y); //先写上面一行的8个点
for(wm = 0;wm < 16;wm++)
{
   WriteData(F16x16);
   adder += 1;
}
SetPos(x,y + 1); //再写下面一行的8个点
for(wm = 0;wm < 16;wm++)
{
   WriteData(F16x16);
   adder += 1;
}
}

显示效果:
http://www.14blog.com/wp-content/uploads/2014/04/9.png
图9. 显示点阵汉字
3.4 显示图片的函数
void Draw_BMP(unsigned char x0, y0,x1, y1,unsigned char BMP[]) //x0,y0是图片起始点的坐标,x1,y1是结束点坐标
{
unsigned int j=0;
unsigned char x,y;

if(y1%8==0)
   y=y1/8;
else
   y=y1/8+1;
for(y=y0;y<y1;y++)
{
   LCD_Set_Pos(x0,y);
   for(x=x0;x<x1;x++)
   {
   LCD_WrDat(BMP);
   }
}
}
http://www.14blog.com/wp-content/uploads/2014/04/10.png
图10. 显示图片的效果

4. 挽总

[*]上文介绍了一些主要显示函数,基本上可以满足一些简单的电子开发;
[*]还有更多的功能,比如要显示一个点,显示波形……以后再介绍;
[*]演示所用的点阵屏叫“OLED显示屏”,它的特点是非常小,显示效果锐利……我在这家买的:
http://item.taobao.com/item.htm?spm=2013.1.0.0.s62LHC&id=36399661547








智能创客 发表于 2014-4-29 09:54:29

帅,赞一个。{:soso_e100:}

benbenqi 发表于 2014-4-30 10:57:11

老帅了,思路清晰。

fisherdl 发表于 2014-5-1 15:34:18

这样的帖子,即便使是产品推销也还是要顶的。

Zeroi 发表于 2014-6-28 01:52:12

顶下,虽然现在还看不懂

651804005 发表于 2014-12-16 08:47:25

里面还是挺好的,学习中ing

猴子也疯狂 发表于 2016-5-22 15:14:21

楼主 好厉害 我最近也在学oled 遇到好多问题 能请教你嘛我qq1217000432

哈哈,是你 发表于 2017-7-17 11:20:41

很不错。。。。。
页: [1]
查看完整版本: 入门贴申精:128*64点阵显示屏的驱动方法及常用的显示函数