PCB 布局参考了老王0.8元128x32OLED显示屏转接板,开源项目地址:老王0.8元128x32OLED 模块-部分优化。
老王家买的屏幕放了快一年了,终于还是决定整个单独的模块,之前一直打算集成到开发板上的,不太灵活。相比那个转接板,主要的修改是:
- 添加了3.3V LDO,ME6206A33,就是常用的662K,可以兼容3.3V 到5V 的输入电压;
- 四线SPI 接口加入了电平转换电路,可以兼容3.3V 和5V 电平;
- 7pin 排针减少到6pin,去掉复位,没什么用;
- 去掉多余的螺丝孔,板子面积很小,一个M3 螺丝就够固定了。不需要螺丝固定的话还可以一剪子把螺丝孔突出的环形部分剪掉;
实物图如下:
电路
就是复制粘贴成品OLED 模块的上电路,电容的参数不敏感,小范围变动取值对屏幕工作没什么影响,比如C4,换成0.1uF 实测也OK。
供电
参考ME6206 的规格书:
OLED 工作电流不大,所以压差应该不超过300mV。理论上,如果输入3.3V,输出电压仍大于3V,而OLED 芯片SSD1316 的规格书上说最低电压3V,所以足够驱动了。另外,OLED 模块的电源正极V+ 可以不接,因为CS 线默认是高电平,只在通讯过程中拉低,其他几个信号线也可能间歇地处于高电平,那么当单片机使用5V 供电时,可以只通过这几个信号线给OLED 供电,实测基本能用,只是屏幕亮度会降低,还有点闪。
电平转换
因为模块是用SPI 驱动的,参考:SPI 接口OLED 使用5V 信号驱动可能需要电平转换,就是说如果直接和5V 单片机连在一起,屏幕可能不工作,所以就加了四组分压电路,用来把5V 电平降到3.3V。
还有个拨动开关SW-LVL-SHIFT,开关闭合时启用分压功能,断开后分压电路就退化成了限流电路,下拉部分R7 至R10 失去作用,R3 和R6 串入信号线里限流。经过实测,用5V 的Arduino 驱动,只要限流电阻就够了,OLED 可以工作,所以四个下拉电阻和拨动开关可以不装。不过,SPI 信号线SCLK 和MOSI 上的限流电阻肯定会影响信号的上升时间,也就是说SPI 通信频率不能太高,虽说我也没试过最高能到多少。
焊接
- 原理图里那两个和0.1uF 电容并联的4.7uF 电容可以不装,之前试过,能用;
- 像上面说的,2k 下拉电阻R7 至R10 以及拨动开关也可以不装;
- 如果确定不需要兼容5V 电平,LDO 可以去掉,1k 限流电阻可以用一坨锡替代;
- LDO 的输入输出电阻也可以用1uF,怎么方便怎么来;
所有元件都是贴片的,而且是单面安装,推荐使用焊锡膏配加热台的焊接方式,我是用针管点锡膏的,反正元件种类不多,熟悉之后也挺快的,唯一的难点就是那个座子,我就没遇到过能一次性焊好的。如果用加热台焊接,注意座子底下焊锡膏尽量少一点,免得之后连锡太多拖不开;要是焊锡膏太多,融化的锡球还可能把座子给顶起来。不推荐用热风木仓焊座子,很容易烤坏,其实加热台基本也焊不了座子,只是能初步把座子固定在焊盘上,之后用烙铁的时候稍微省点事。
座子的焊盘我修改过,把引脚的焊盘向外拉长了,就是为了方便检查和用烙铁拖。除了电烙铁,必要的工具还有放大镜和助焊膏。处理连锡的方法就是先助焊膏满上,把烙铁头用海绵或者钢丝球清理干净,然后轻柔的贴在连锡的焊盘上向外拖。动作轻柔的目的是避免把焊盘刮坏,引脚的焊盘间距太小了,阻焊层很脆弱。此外,还要避免烙铁头把融化的锡挤到座子里面。除了容易连锡,还容易虚焊,可以用放大镜快速观察一下,涂满助焊膏,在烙铁头上沾一点焊锡,然后从里往外拖,让烙铁上的锡沾到引脚和焊盘上,沾得焊锡太多就容易把焊锡挤进座子内部。烙铁和座子引脚接触时间太长的话会让座子内部的铜引脚被加热到比较高的温度,焊锡也就更容易跑进去。
故障排除
如果单片机程序ok,但屏幕全黑,没反应,首先考虑是不是座子上连锡或虚焊。连锡用放大镜很容易观察到,用干净的烙铁头配上助焊膏也很容易拖干净,所以更可能是虚焊。此时需要先把屏幕拔下来,这里也有点要注意的地方,如果是虚焊,说明座子的引脚只靠塑料件固定着,没连到焊盘上,那么,刚经过高温焊接,塑料肯定有一些变形,引脚的固定不一定牢靠,有可能在拔掉屏幕时把座子的引脚一起拔下来,避免的方法当然是尽量控制焊接温度和时间。然后要么拿放大镜纯靠眼力判断虚焊的地方,要么就用万用表测量焊盘和座子引脚的通断,可能需要用细尖表笔,一个一个扫过去,熟练的话也不怎么费劲。
如果屏幕能亮,但是亮度比较低,会闪烁,那可能是那个560K 的电阻没焊好。加热台上焊接有时候会出现立碑的现象,就是电阻之类的小东西一侧的焊锡比较少,然后电阻被另一侧的焊锡拉着拽起来了,导致电阻一边浮空。总之大部分问题应该都是和座子的焊接有关,其他元件没焊好容易观察到。
例程
使用例程参考Arduino 版u8g2 库的例子,屏幕型号SSD1316 128x32,四线SPI 驱动方式,RST 不连接, 参数上写U8X8_PIN_NONE
。虽然,似乎大部分人都说这屏幕是128x32,但我不管怎么试,看起来都更像是128x28,用8x7 的字符刚好够显示4 行,8x8 的字符第四行会显示不全。顺便放上一个Hello world 例程,Arduino 加U8G2 库,使用硬件SPI:
/*
HelloWorld.ino
"Hello World" version for U8x8 API
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include
#ifdef U8X8_HAVE_HW_SPI
#include
#endif
//DC 连接到D9, CS 到D10,SCK 和MOSI 连到对应的SPI 引脚,V+ 连接到5V 或3.3V 电源,也可以不接。
U8X8_SSD1316_128X32_4W_HW_SPI u8x8(10, 9, U8X8_PIN_NONE);
void setup(void)
{
u8x8.begin();
u8x8.setPowerSave(0);
}
void loop(void)
{
static bool line = false;
u8x8.setFont(u8x8_font_chroma48medium8_r);
if(line) {
u8x8.drawString(0,1,"1: 8x7 character");
u8x8.drawString(0,2,"2: 4 line => 28 ");
}
else {
u8x8.drawString(0,1,"Hello World! ");
u8x8.drawString(0,2,"Hello World! ");
}
line = !line;
u8x8.drawString(0,0,"0 start line");
u8x8.drawString(0,3,"3 end line");
delay(2000);
}