8段数码管、1602、5110、12864点阵屏……这些都是最最常见的、可用于简单电子开发的显示屏。我最喜欢用点阵屏,因为它相比其他字符式的屏来说,可以用来显示任意大小的字符(包括汉字)、图片等。但点阵屏的操作方式略比其他屏复杂……如图,点阵屏要显示的内容是由相应的点按照一定的顺序“拼凑”出来的!下面要说的就是这“拼凑”的方法! 此OLED 模块 是在淘宝买的, 因为不能发链接,只能介绍店铺名为 惠特自动化 或者,在淘宝搜索OLED ,旺旺名为leehunter8801 图1 点阵显示的效果
操作方式大致按图2流程 图2 液晶屏操作大致流程
1.通信方式SPI、I2C、并行(8080)……这些都是向屏幕发送数据的方式,首先你应该根据自己屏的情况,选择合适的通信方式,然后将MCU的通信方式配置好!注意: - 传统的51单片机没有I2C或SPI功能,只能使用8080的并口方式,或者用IO口来模拟IIC或SPI通信;
- 8080方式的速度是最快的,但是也是最占用IO口的(通信就要8个IO口),这种屏不适合用在430、STM32这样的IO口不是很丰富的MCU上,但这些MCU一般都有硬件I2C或SPI功能;
- 硬件I2C或SPI比模拟IIC货SPI速度快,且更省资源,但不同芯片的配置方法不同,这里介绍用IO口模拟SPI和I2C通信的方式。
1.1 模拟SPI写数据[size=1em]
- 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略慢[size=1em]
- 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这样: 图3. 每次对应点阵竖着的8个点
–> 一个byte数据的每一位分别对应哪一个点?我分别向屏幕写入了“0x0F”、“0xF0”、“0×01”、“0×02”、“0×04”、“0×08”这样一些有代表性的数据,显示效果是这样的: 图4. 对应数据来看看这张图
总结一下:从上到下第一个点为最低位,第8个点为最高位!–> 当写完一个byte的数据后,下一组数据从哪里开始写?如图5所示 图5. 显示的顺序
明白了这个规律,要显示一个字或符号,只要把它对应的点找出来,然后向屏幕写数据就OK了!怎么才能得到你想要显示内容的点阵呢?这个可以用软件来计算!这种软件一般被称为“取模软件” 图6. 推荐这样配置取模软件
3.在显示屏上显示一些东西我们可以把取得的字模寸在数组里,然后用一个专门的文件来存放……比如codetab.h 3.1 显示6*8的ASCII字符串每一个字符都有独一的ASCII值,通过这一点,可以找到某一字符在codetab中的具体位置,程序中要做的就是来处理这种“查询”的过程!比如显示一个6*8的ASCII字符,可以通过下面的代码来完成: [size=1em]
- 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[j] != '\0')
- {
- c = ch[j] - 32;
- if(x>125) //如果一行的点阵不够显示,就换行
- {
- x=0;
- y++;
- }
- SetPos(x,y);//设置起始点坐标的方式是通过写命令来完成的,具体什么命令,需要你去查找产品
- for(i=0;i<6;i++)
- {
- WriteData(font6x81);//写数据
- }
- x += 6;
- j++;
- }
- }
复制代码
我在main函数中写了如下几句代码: [size=1em][size=1em]1 | 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:hello14blog@gmail.com"); |
效果是这样的: 图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[j]!='\0')
- {
- c =ch[j]-32;
- if(x>120) //溢出即换行
- {
- x=0;
- y++;
- }
- SetPos(x,y);
- for(i=0;i<8;i++) //先写完上面一行的8个点
- WriteData(F8X161);
- SetPos(x,y+1);
- for(i=0;i<8;i++) //再写下面一行的8个点
- WriteDdata(F8X161);
- x+=8;
- j++;
- }
- }
复制代码
[size=1em]
显示效果是这样的: 图8. 惠利特自动化
3.3 显示16*16汉字因为汉字不能通过ASCII码来查询,所以用了一种特殊的方式,我习惯将其称之为“字码索引”。先来看看汉字的字码是什么样子的: [size=1em]
- 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这样的数字,就是字码的索引,用代码这样来完成操作: [size=1em]
- 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]);
- adder += 1;
- }
- SetPos(x,y + 1); //再写下面一行的8个点
- for(wm = 0;wm < 16;wm++)
- {
- WriteData(F16x16[adder]);
- adder += 1;
- }
- }
复制代码
显示效果: 图9. 显示点阵汉字
3.4 显示图片的函数[size=1em][size=1em]
- 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
- {
- LCD_Set_Pos(x0,y);
- for(x=x0;x
- {
- LCD_WrDat(BMP[j++]);
- }
- }
- }
复制代码
图10. 显示图片的效果
4. 挽总- 上文介绍了一些主要显示函数,基本上可以满足一些简单的电子开发;
- 还有更多的功能,比如要显示一个点,显示波形……以后再介绍;
- 演示所用的点阵屏叫“OLED显示屏”,它的特点是非常小,显示效果锐利……在淘宝惠特自动化 买的 ,惠特自动化是店铺名字。 亲们可以直接搜索店铺名字。
|