树莓派笔记12:通过SPI操作OLED显示屏

树莓派自带SPI和I2C接口,因此可以方便地控制带SPI的控制芯片的OLED显示屏。要想成功实现树莓派与oled的通信,最好是买一个以SSD1306为主控芯片的oled,因为关于这个芯片的驱动库是最容易搜到的,当然如果有能力自己写驱动程序的话就无所谓了。这是我买的128X64,SPI接口的OLED模块,不到20块。
树莓派笔记12:通过SPI操作OLED显示屏_第1张图片
网上对树莓派SPI操作OLED的大多数文章我猜应该是参考了这个链接里的教程https://learn.adafruit.com/ssd1306-oled-displays-with-raspberry-pi-and-beaglebone-black?view=all,这是Adafruit公司专门为配合SSD1306的驱动库写的教程,按照该教程很快就能调通了。

1 关于SPI

SPI是串行外设接口(Serial Peripheral Interface)的简写,其实就是一种总线通信协议,该总线以主从方式工作,通常是一个主设备和一个或多个从设备,一般需要4根线来进行数据通信,即SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选),相应的,有一套时序逻辑规定了通信过程。一般使用SPI的设备都配备了现成的SPI模块,只需要对相应的寄存器写入指令就可以进行通信了,如果没有SPI接口,也可以软件实现,就是根据时序图手动操作GPIO来实现通信,这就比较费劲了。

树莓派已经带了SPI接口,不过默认是关闭的。执行sudo raspi-config 进入配置页,打开SPI接口。
树莓派笔记12:通过SPI操作OLED显示屏_第2张图片
然后有的教程里说要把/etc/modprobe.d/raspi-blacklist.conf文件里的”blacklist spi-bcm2708”注释掉,但是我的这个文件是空的。重启后,可以执行lsmod 查看是否有spi模块存在;同时,在/dev下是否存在spidev0.0和spidev0.1两个文件,这两个文件代表了树莓派SPI模块可以使能两个SPI从设备,也对应了GPIO上的CE0和CE1脚。

2 接线

把模块的引脚接到树莓派的GPIO上, 需要注意这里要分清GPIO引脚号是BCM编号还是实际编号。GND脚和树莓派的GND连接;VCC接到3.3V脚;D0接到树莓派的SCLK脚(第23号脚),即BCM.11脚;D1接到MOSI脚(第19号脚),即BCM.10;RES接到BCM.17脚,即第11号脚;DC接到BCM.22脚,即第15号脚;CS接到CE0脚(第24号脚)。总之,除了RES和DC是可以任意指定GPIO口,其他引脚是必须和树莓派上的指定脚连接的。

3 安装相关库

执行下面的更新内核并安装基本环境,这个不是必须的,一般都已经装好了:

sudo apt-get update
sudo apt-get install build-essential python-dev python-pip
sudo pip install RPi.GPIO

接着安装python-imaging和python-smbus库, Python Imaging Library库包含了很多图像或图形操作,它是Adafruit_Python_SSD1306驱动库的所需要的基本模块;python-smbus不太清楚是什么库,网上搜索似乎是和I2C有关。

sudo apt-get install python-imaging python-smbus

最后,从Github上拷贝Adafruit_Python_SSD1306代码文件,并安装Adafruit_Python_SSD1306库。

sudo apt-get install git
git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
cd Adafruit_Python_SSD1306
sudo python setup.py install

下载源文件的时候,可能会连不上GitHub,如果这样就在自己电脑上到该网址下载zip文件,用WinSCP复制到树莓派,再用unzip命令解压缩。

4 程序编写

接下来就可以编写Python程序来测试了。可以通过浏览上面链接里的教程或者Adafruit_Python_SSD1306目录下的examples熟悉操作oled的方法。大致的操作方法可以按下面的步骤:首先创建display对象,它代表了我们的oled模块;接着新建image对象,可以把它看成是一个画板,与它相关联的drawing对象则代表了具体的绘制情况,我们就是调动drawing的方法来构建要显示的内容;然后让display对象接收image对象,即把我们设置的绘图信息传递给oled;最后调用display()方法让oled显示出来。下面是我写的测试程序:

import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageDraw
import ImageFont

# 引脚配置,按照上面的接线来配置
RST=17
DC=22
# 因为连的是CE0,这里的PORT和DEVICE也设置为0
SPI_PORT=0
SPI_DEVICE=0

#根据自己的oled型号进行初始化,我的是128X64、SPI的oled,使用SSD1306_128_64初始化
disp=Adafruit_SSD1306.SSD1306_128_64(rst=RST,dc=DC,spi=SPI.SpiDev(SPI_PORT,SPI_DEVICE,max_speed_hz=8000000))

disp.begin()
disp.clear()
disp.display() #清屏

#image 1,绘制了几个图形
width=disp.width
height=disp.height
image1=Image.new('1',(width,height)) #新建一个128X64的二值图像对象
draw1=ImageDraw.Draw(image1) #获取image1的draw对象

padding=1
shape_width=50
left=padding
top=padding
right=width-padding
bottom=height-padding
x=padding

draw1.rectangle((left,top,right,bottom),outline=1,fill=0) #画矩形
draw1.ellipse((left+10,top+10,left+10+shape_width,top+10+shape_width),outline=1,fill=0) #画椭圆
draw1.polygon([(right-20,top+10),(width/2+5,bottom-10),(right-5,bottom-10)],outline=1,fill=0) #画三角

# image 2,载入一副图片
image2=Image.open('testImage.jpg').resize((128,64)).convert('1')

# image 3,显示一些文字
image3=Image.new('1',(width,height))
draw3=ImageDraw.Draw(image3)
font1=ImageFont.load_default()
font2=ImageFont.truetype('04B_30__.TTF',15)
font3=ImageFont.truetype('baby blocks.ttf',18)
draw3.text((0,0),'Hello',font=font1,fill=1)
draw3.text((0,15),'World!',font=font2,fill=1)
draw3.text((0,35),'Enjoy it!',font=font3,fill=1)

try:
    index=1
    while True: #循环显示
        if index==1:
            disp.image(image1)
            index+=1
        elif index==2:
            disp.image(image2)
            index+=1
        else:
            disp.image(image3)
            index=1
        disp.display()
        time.sleep(2)
except:
    disp.clear()
    disp.display()

在上面的程序中,创建了3个image对象进行循环显示。image1是调用了一些绘图方法进行图形绘制,例如rectangle方法,指定其左上角和右下角的坐标,并指定边框(outline)和内部(fill)颜色,因为oled模块只有两种颜色(灭和亮),所以指定其颜色时也只需要指定1和0,大于1的值都是表示“1”的状态。

image2是加载了一副图片:
树莓派笔记12:通过SPI操作OLED显示屏_第3张图片
图片的格式无所谓,因为python-imaging库能解析各种常用图像格式;大小也无所谓,因为在程序中可以用resize()方法调整到128X64;同时应使用convert()方法将原图转成二值图(传入”1”)。当然,选用的图片不能复杂,否则在oled上只能显示一堆零散的点。

image3显示一些文字,这个调用text方法就可以了。如果想要一些特别的字体,可以去http://www.dafont.com/bitmap.php下载ttf文件,放在程序文件目录下,使用ImageFont.truetype方法载入字体文件,最后在text方法中指定字体。

5 测试结果

image1:
树莓派笔记12:通过SPI操作OLED显示屏_第4张图片

image2:
树莓派笔记12:通过SPI操作OLED显示屏_第5张图片

image3:
树莓派笔记12:通过SPI操作OLED显示屏_第6张图片
我的oled有黄蓝两种颜色,是因为我买的oled上下两部分本来颜色就不同。

你可能感兴趣的:(树莓派笔记)