瑞芯微RK3506通过fbtft适配ST7735S屏幕记录

网上有很多相关的文章,但是内核版本不相同,屏幕模组也不同,我适配时踩了很多。。。记录一下

 

主控 HD-RK3506G-MINI

内核 6.1.99

屏幕 ST7735S 1.8' 128*160,某宝搜TFT屏幕第一家就是

 

1.不用修改fbtft代码

现在fbtft已经被完善,相关的配置都在设备树,不需要再修改驱动代码了

 

2.内核相关配置

进入瑞芯微家的sdk,./build.sh kconfig进入内核配置

选择Device Drivers  ---> [*] SPI support  ---> <*>   Rockchip SPI controller driver (不论是tinydrm还是fbtft都一定要选,不然后面的配置不会出现)

选择Device Drivers  ---> [*] Staging drivers  ---> <*>   Support for small TFT LCD display modules  ---> <*>   FB driver for the ST7735R LCD Controller

内核默认没有打开VT(虚拟终端),需要在Character devices中打开,再打开FrameBuffer Console,这样就可以在屏幕上显示终端了

退出配置,接下来修改设备树

注意有时候你做的修改会被默认配置替换,比如rk3506-display.config每次编译前都会被merge,需要注意下输出的提示

 

2.设备树SPI配置

// 加入rk3506g-mini-v10.dtsi中
&spi1 {
	status = "okay";
	pinctrl-names = "default";
	st7735: st7735r@0 {
		compatible = "sitronix,st7735r";
		reg = <0>; //chip select 0:cs0, 1:cs1
		spi-max-frequency = <32000000>; //spi output clock
		rgb; // rgb模式, 如果实际测试红蓝反了就改成bgr
		buswidth = <8>;
		fps = <60>;
        // 0 90 180 270 顺时针
        rotate = <270>; // 又是坑 rotation已更名为rotate
		dc-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; // DC脚,具体引脚请参考原理图
		reset-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; // rest脚
	};
};

 修改完设备树后输入./build.sh kernel编译内核,输出kernel/zboot.img,烧录进板

 

3.测试程序

开机后TFT屏幕应该由白变黑,代表设备通信正常,简单用C写了个demo,可以测试屏幕参数是否正常:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <string.h>
#include <time.h>

// 屏幕参数
#define WIDTH 128
#define HEIGHT 160
#define BPP 16  // 16位色

// 颜色定义 (RGB565格式)
#define RED     0xF800
#define GREEN   0x07E0
#define BLUE    0x001F
#define WHITE   0xFFFF
#define BLACK   0x0000

// 根据实际情况修改
#define FB_DEVICE "/dev/fb0"

int main(int argc, char *argv[]) {
    int fbfd = 0;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    char *fbp = 0;
    int x = 0, y = 0;
    unsigned int color = 0;
    long int location = 0;
    
    // 打开帧缓冲设备
    fbfd = open(FB_DEVICE, O_RDWR);
    if (fbfd == -1) {
        perror("Error: cannot open framebuffer device");
        exit(1);
    }
    
    // 获取固定屏幕信息
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        perror("Error reading fixed information");
        exit(2);
    }
    
    // 获取可变屏幕信息
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        perror("Error reading variable information");
        exit(3);
    }
    
    printf("Display info: %dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
    
    // 检查是否为16bpp (st7735s)
    if (vinfo.bits_per_pixel != 16) {
        printf("Error: not supported bits per pixel (requires 16bpp)\n");
        exit(4);
    }
    
    // 计算屏幕大小
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    
    // 映射帧缓冲到内存
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((int)fbp == -1) {
        perror("Error: failed to map framebuffer device to memory");
        exit(5);
    }
    
    // 测试颜色数组
    unsigned int colors[] = {RED, GREEN, BLUE, WHITE};
    const char *color_names[] = {"RED", "GREEN", "BLUE", "WHITE"};
    
    for (int c = 0; c < 4; c++) {
        color = colors[c];
        printf("Displaying %s screen...\n", color_names[c]);
        
        // 填充整个屏幕
        for (y = 0; y < HEIGHT; y++) {
            for (x = 0; x < WIDTH; x++) {
                location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8) +
                           (y + vinfo.yoffset) * finfo.line_length;
                
                if (vinfo.bits_per_pixel == 16) {
                    *((unsigned short *)(fbp + location)) = color;
                }
            }
        }
        
        // 等待2秒
        sleep(2);
    }
    
    // 清理
    munmap(fbp, screensize);
    close(fbfd);
    
    printf("Test completed.\n");
    return 0;
}

 

二编: 屏幕太小,换ILI9341+XPT2046触摸屏了,目前还在研究触屏,下一期出驱动+触摸屏校准笔记

posted @ 2025-06-07 14:48  星如雨yu  阅读(571)  评论(0)    收藏  举报