在 Milk-V Duo 上使用 SSD1351

转载自:SSD1351 On the Milk-V Duo | Futz's Microcontrollers & Robotics

我购买了一块使用SSD1351控制器的Waveshare 128x128 RGB OLED显示屏。我开始编写一些适用于Milk-V Duo的代码,使用了WiringX SPI库命令。在浪费了几个小时后,我再次意识到WiringX根本不起作用。它需要大量的改进。目前的情况是毫无用处的。

所以,回到位移SPI。没有问题 - SPI非常简单。我遇到的唯一问题是WiringX的digitalWrite命令速度很慢,我的代码完全没有延迟,因此更新显示屏的速度太慢了。哦,好吧,现在足够好了。一些内联汇编代码可以提高一些速度,但我需要Duo的MCU的良好数据手册才能这样做。

和往常一样,Solomon Systech的数据手册非常晦涩,还存在一些错误。我花了很多试错和测试代码才弄清楚他们所说的一些事情,以及发现他们描述的启动顺序与实际操作顺序相反。真是有趣!

照片和视频的质量很差,因为显示屏刷新随机被我的Pixel 7手机相机捕捉到,该相机没有快门速度控制,事实上,没有任何高级控制。不要购买谷歌手机。我并不完全讨厌Pixel,但我的旧三星手机好太多了。

这是一个非常简单的演示代码。它甚至远未达到驱动程序的水平。这只是用于初始化显示屏并在屏幕上显示一些颜色的最简单的代码。稍后我会做一些更有野心的事情:

ssd1351_128x128_rgb.c

#include <unistd.h>
#include <wiringx.h>
#include "ssd1351_128x128_rgb.h"

int rst = 15;       //reset - physical pin 20
int dc = 14;        //D/C - physical pin 19
int clk = 6;        //clk - physical pin 9
int dat = 7;        //dat - physical pin 10
unsigned char framebuff[0x8000];

int main(void){
  init();
  cls();

  while(1){
    for (int x=0;x<0x8000;x+=2){
      framebuff[x] = 0xf8;
      framebuff[x+1] = 0x00;
    }
    transbuff();

    for (int x=0;x<0x8000;x+=2){
      framebuff[x] = 0x07;
      framebuff[x+1] = 0xe0;
    }
    transbuff();

    for (int x=0;x<0x8000;x+=2){
      framebuff[x] = 0x00;
      framebuff[x+1] = 0x1f;
    }
    transbuff();
  }
}

void cls(void){
  for(int x=0;x<0x8000;x++)
    framebuff[x] = 0;
  transbuff();
}

//write framebuff to GDDRAM
void transbuff(){
  digitalWrite(dc,LOW);      //command
  spiwrite(0x5c);
  digitalWrite(dc,HIGH);      //data
  for(int x=0;x<0x8000;x++)
    spiwrite(framebuff[x]);
}

void spiwrite(unsigned char p){
  for(int x=0;x<8;x++){
    if(p & 0x80)
      digitalWrite(dat,HIGH);
    else
      digitalWrite(dat,LOW);
    digitalWrite(clk,HIGH);
    digitalWrite(clk,LOW);
    p <<= 1;
  }
}  

int init(){
  //wiringx init
  if(wiringXSetup("duo", NULL) == -1){
    wiringXGC();
  }

  pinMode(dc,PINMODE_OUTPUT);
  pinMode(rst,PINMODE_OUTPUT);
  pinMode(clk,PINMODE_OUTPUT);
  pinMode(dat,PINMODE_OUTPUT);
  digitalWrite(clk,LOW);

  //OLED init
  usleep(6000);           //OLED reset
  digitalWrite(rst,1);
  usleep(10000);
  digitalWrite(rst,0);
  usleep(50000);
  digitalWrite(rst,1);

  digitalWrite(dc,0);     //send command
  spiwrite(0xae);         //display OFF

  spiwrite(0xfd);         //unlock MCU protect
  digitalWrite(dc,1);     //send data
  spiwrite(0x12);

  digitalWrite(dc,0);
  spiwrite(0xfd);         //make a2 accessible
  digitalWrite(dc,1);
  spiwrite(0xb1);

  digitalWrite(dc,0);
  spiwrite(0xa2);         //set vertical scroll by row
  digitalWrite(dc,1);
  spiwrite(0x00);

  digitalWrite(dc,0);
  spiwrite(0xb3);         //clock speed
  digitalWrite(dc,1);
  spiwrite(0xf0);         //max clock speed

  digitalWrite(dc,0);
  spiwrite(0xa0);         //remap/color depth 65k
  digitalWrite(dc,1);
  spiwrite(0x74);

  digitalWrite(dc,0);
  spiwrite(0xaf);         //display ON
}

ssd1351_128x128_rgb.h

void transbuff(void);
void cls(void);
void spiwrite(unsigned char);
int init(void);