2024年9月5日 星期四

香橙派 zero3 (linux 6.1.xx) 連接 SPI LCD 屏幕 (ILI9341)

參考連結

前言

Linux 並沒有正式支援 SPI 界面的 LCD 螢幕,在 Armbian 下是透過 Overlay 來連接 SPI 界面的 LCD 螢幕。

在網路上找到的資料,都是舊的作法,香橙派的用户手册中查找到的驱动方法,也是只能在 linux 4.9 下驅動屏幕的方案。 但 Orange PI zero3 最近的系统是 debian bookworm linux6.1.31,因此不能用舊的方法驅動。

最先是在 CSDN 找到一篇,是新的作法,照著做,可以成功地輸出顯示到 LCD,但觸控功能沒有啟動。後來又找到相關的作法,把觸控功能也啟動了。

在淘寶買 spi lcd屏幕時,要注意使用的晶片。第一次貪大,買了 3.5" 的 LCD,使用的晶片為 ILI9488,必須自己編譯 Kernel 的 module。要選較舊的 ILI9341 晶片的 LCD,在 Armbian 的 kernel 就有現成的 module 可用。

另外,觸控功能的 IC 是 XPT2046,是 TI 的 ADS7843 的相容 IC,因此是用 ADS7843 的驅動程式。

正文

香橙派接腳定義如下圖。



連接 Orange PI 與屏幕,參考。SPI 是一對多的協定,其中 SDI, SDO, SCK 是共用的,使用 CS 選擇要溝通的裝置。

--------------
OPi Zero3 wiring:
Pin 23 - PH6  <-->  SPI1 SCK       & T_CLK
Pin 21 - PH8  <-->  SPI1 SDO<MISO> & T_DO
Pin 19 - PH7  <-->  SPI1 SDI<MOSI> & T_DIN
Pin 11 - PC6  <-->  DC
Pin 7  - PC9  <-->  RESET
Pin 13 - PC5  <-->  LED
Pin 22 - PC7  <-->  SPI1 CS       (PH9, originally)
Pin 18 - PC14 <-->  T_CS
Pin 16 - PC15 <-->  T_IRQ
Pin 1  - 3.3V
Pin 6  - GND
--------------

经过查找,发现有 ili9341 的驱动模块,位於下面的目錄:

  • /lib/modules/6.1.31-sun50iw9/kernel/drivers/staging/fbtft/fb_ili9341.ko
  • /lib/modules/6.1.31-sun50iw9/kernel/drivers/input/touchscreen/ads7846.ko

于是通过设备树 overlay 添加 ili9341 的设备节点,如下:

在 /boot/dtb/allwinner/overlay/ 目錄下,建立檔案 ili9341_lcd.dts。檔名可自己任意決定。

/dts-v1/;
/plugin/;

/ {
    compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h616";

    fragment@0 {
        target = <&spi1>;
        __overlay__ {
            status = "okay";
            /*cs-gpios = <&pio 7 9 0>;*/ /* PH9*/
            cs-gpios = <&pio 2 7 0>, <&pio 2 14 0>; /* PC7 PC14 */

            ili9341: ili9341@0 {
                compatible = "ilitek,ili9341";
                reg = <0>;  /* Chip Select 0 */
		#spi-cs-high;
                spi-max-frequency = <40000000>;
                rotate = <90>;
                bgr = <0>;
                fps = <30>;
		width = <240>;
		height = <320>;
                buswidth = <8>;
                reset-gpios = <&pio 2 9 1>; /*RESET=PC9*/
                dc-gpios = <&pio 2 6 0>; /*DC_RS=PC6*/
                led-gpios = <&pio 2 5 0>; /*LED=PC5*/
                debug = <4>;
            };

            ads7846: ads7846@0 {
                compatible = "ti,ads7846";
                reg = <1>;  /* Chip Select 1 */
		#spi-cs-high;
                spi-max-frequency = <1000000>;
                interrupt-parent = <&pio>;
                interrupts = <2 15 2>; /* PC15 IRQ_TYPE_EDGE_FALLING */
                pendown-gpio = <&pio 2 15 0>; /* PC15 */
		/* ti,swap-xy = <0x1>; */
		ti,x-min = /bits/ 16 <0>;
                ti,y-min = /bits/ 16 <0>;
                ti,x-max = /bits/ 16 <0x0FFF>;
                ti,y-max = /bits/ 16 <0x0FFF>;
                ti,pressure-min = /bits/ 16 <0>;
                ti,pressure-max = /bits/ 16 <0xFFFF>;
		ti,x-plate-ohms = /bits/ 16 <400>;
            };
        };
    };
};

执行下面的指令,會產生 ili9341_lcd.dtbo,放在 /boot/overlay-user/ 的目錄下。

$ sudo orangepi-add-overlay ili9341_lcd.dts
Compiling the overlay
Copying the compiled overlay file to /boot/overlay-user/
Overlay ili9341_lcd was already added to /boot/orangepiEnv.txt, skipping
Reboot is required to apply the changes

如訊息所說,會在 /boot/orangepiEnv.txt 的檔案中加入該 overlay。

$ cat /boot/orangepiEnv.txt 
verbosity=1
bootlogo=false
console=both
disp_mode=1920x1080p60
overlay_prefix=sun50i-h616
rootdev=UUID=535922e7-511d-46ea-82e6-573f913006af
rootfstype=ext4
user_overlays=opi_z3_ili9341_lcd

若要暫時停用該 overlay,可將其註解掉。例如,要使用 ADXL345 测量谐振時,也是用 SPI 來連接。

重新啟動,可以成功點亮 LCD。

疑难杂症

香橙派的 SPI1 CS 對應到 CPU 的 PH9,但使用 PH9,會報錯,dmesg 訊息如下:

-----------------
pin PH9 already requested by 5011000.spi;
-----------------

若是将 ili9341.dts 中的 cs-gpio 一行注释掉,則 fb0 可成功挂载,但是屏幕白屏

可以尝试更换cs的引脚,在此是把 cs 的引脚从 PH9 更换至 PC7 后可以正常点亮。另外,觸控的 CS 信號則是用 PC14。


具体操作:修改 ili9341_lcd.dts,

-----------------
    /* cs-gpios = <&pio 7 9 0>;  */
    cs-gpios = <&pio 2 7 0>; 
-----------------

"<&pio " 後面接的第一個數字,0 ~ 7 對應 Port A ~ Port H。最後一個數字,應是指定輸出 / 輸入。

只接 LCD 時,SPI1 SDO 不用接。開始時,照著 CSDN 的作法,成功點亮了 LCD。後來加上觸控的設定,沒注意到 SPI1 SDO 沒接,測了好久不成功,才發現一支腳沒接。

LCD 的設定

開機後,LCD 即會輸出顯示,但啟動 X 的應用程式,沒有顯示。

fb_tft 透過 fb_ili934 控制 LCD。在 X 的設定目錄下,建立 fbdev 的相關設定檔,如下。

$ cat /etc/X11/xorg.conf.d/98-fbdev.conf 
Section "Device"
  Identifier "myfb"
  Driver "fbdev"
  Option "fbdev" "/dev/fb0"
EndSection

重新啟動後,成功啟動 KlipperScreen。

觸控校正與設定

觸控是使用 XPT2046, 其為 ADS7846 的相容 IC。觸控要校正,才會和 LCD 的顯示一致。最先找到的作法,不能成功設定,但有了相關概令。參考 Arch Linux 的 Calibrating Touchscreen,只要設定 libinput 的 TransformationMatrix 參數即可。

設定的內容如下。

$ cat /etc/X11/xorg.conf.d/99-calibration.conf
Section "InputClass"
	Identifier	"calibration"
	MatchProduct	"ADS7846 Touchscreen"
	Option "TransformationMatrix" "0 1.15 -0.1 1.1 0 -0.05 0 0 1"
EndSection

轉換公式計算如下。X / Y range 是指傳回的數值的範圍,這裡是 0xFFF,即 4096。

-----------------------------------------------------
[  0    1.15  -0.1  ][X]   [ 1.15*Y - 0.10*Y_range ]
[ 1.1    0    -0.05 ][Y] = [ 1.10*X - 0.05*X_range ]
[  0     0      1   ][1]   [        1              ]
-----------------------------------------------------

網路上可以找到計算的公式,但後發現直接觀察修正最快。因為 KlipperScreen 不會顯示游標,我也不會啟動遠端的 X,只好另外裝 LightDM,啟動 lightdm,再慢慢調上面的參數。





網誌存檔