通过Rock的SPI接口,控制oled灯的显示
通过Rock的SPI接口,控制oled灯的显示
先上一个成品图,完整代码。
准备工作
-
一块装有linux系统,并且拥有最新版本内核(包含spidev驱动)的ROCK开发板
最新内核可以到这里下载boot-linux.img,烧录方式请参考烧录 -
一个oled显示屏(我的例子中,使用的是SSD1306芯片驱动的128×64分辨率)
-
若干连接线
连接方式
屏幕有7个接口,分别为
- GND => 地线
- VCC => 电源
- D0 => 时钟
- D1 => 数据
- RES => 复位
- DC => 命令/数据 转换位
- CS => 片选
下面这个是rock pro 的拓展口
接线方式为 (不唯一)
- GND => 接地即可(如, J8-17)
- VCC => 可不接
- D0 => J8-23(SPI1_CLK)
- D1 => J8-28(SPI1_TX)
- RES => J8-7(GPIO167)
- DC => J8-9(GPIO169)
- CS => J8-19(SPI1_CSN0)
oled工作原理介绍
OLED显示技术具有自发光的特性当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,能够节省电能,以后在许多领域都会有应用。
当oled屏幕开启,单不显示的时候,跟关闭是一样的,没有一点光。
CS, D0, D1, GND四个引脚不用我们多顾虑,通信的spi协议驱动已经在内核中写好,通过/dev/spidev1.0文件写入即可
RES引脚用于把屏幕驱动芯片的所有设置清空,复位用的,接在GPIO169上
DC引脚比较关键,当我们需要配置屏幕的一些参数时,此引脚需要处于低电平,需要写数据在屏幕显示时,需要处于高电平
代码结构
代码总共6个文件,一个显示脚本oled.sh,一个makefile,oledfont.h是存储了英文和数字的字库, mian.c是控制模块,oled.c才是驱动屏幕的内容。
说明代码前,对于不知道如何操作rock板gpio口的朋友,需要先看看这个文章
我截取了几个比较重要的函数说明一下.
//传入一个数值,根据这个数据,初始化某个gpio
int __initgpio( int pin){
while(1){
char valuepath[50] = {0, };
sprintf(valuepath, "/sys/class/gpio/gpio%d/value", pin);
int fd3 = open(valuepath, O_WRONLY); //只读方式打开
if(fd3 != -1){
return fd3; //如果该文件打开正确,表示已经初始化过,直接返回文件描述符即可
}
if( errno != 2){
perror("value open :");
exit(1); //如果错误码不为2,表示该文件存在,却因其他原因打不开,直接退出
}
//进去此处,表示该文件不存在,gpio需要初始化
int fd = open("/sys/class/gpio/export", O_WRONLY);
if(fd == -1){
perror("export open :");
return -1;
}
char gpio[10] = {0,};
sprintf(gpio, "%d", pin);
if( write(fd, gpio, strlen(gpio)+1) == -1){ //往文件中写入pin值
perror("export write :");
return -1;
}
//成功后,会在当前文件夹生成gpioxxx文件夹
char direcpath[50] = {0, };
char *out = "out";
sprintf(direcpath, "/sys/class/gpio/gpio%d/direction", pin);
int fd2 = open(direcpath, O_WRONLY);
if(fd == -1){
perror("direction open :");
return -1;
}
if( write(fd2, out, strlen(out)+1) == -1){
perror("direction write :");
return -1;
}
}
}
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 i;
if(cmd)
OLED_DC_Set(); //如果需要写入数据,DC高电平
else
OLED_DC_Clr(); //如果需要写入命令,DC低电平
int ret = write(SPI, &dat, sizeof(dat));
if(ret == -1)
perror("spi write :");
OLED_DC_Set();
}
这两个是比较核心的函数,其他函数大家看看代码,比较简单
控制脚本
PIN="--DCgpio=166 --RESgpio=169"
./oled Hello,friends -i -b "$PIN"
./oled Hello,friends -r 1 -f -t 1000 "$PIN"
./oled I\`m\ Radxa -r 3 "$PIN"
需要显示的文字,可不带,如果带,必须为第一个参数
- -i 第一次开启屏幕时,必须带上,初始化屏幕
- -b 翻转屏幕
- -f 刷新屏幕
- -r 显示时的行数,默认居中
- -t 延迟执行,单位为ms
- DCgpio默认169, REgpio默认167, 不使用默认,需要每次显示指定
- …