驱动一个mipi接口的屏幕

Mipi屏幕的驱动

mipi屏幕驱动步骤:
电路设计、确定时序、上电验证

一、电路设计

原理图:这里主要是R4电阻的确定,根据MP3302数据手册和屏幕的数据手册得到屏幕背光led的额定电流,用MP3302DJ这颗IC做恒流驱动。
在这里插入图片描述PCB:唯一注意的地方就是mipi需要做100Ω的差分等长布线,预留测时序的接口P1。
在这里插入图片描述

二、时序确定

mipi接口的屏幕在初始化时需要根据厂家给的时序进行改写到设备树中,具体改写过程不做赘述,参考链接:
Mipi屏幕驱动1
Mipi屏幕驱动2

通常厂家给的格式如下:(伪代码)

SSD_SEND(0x01,0xE0,0xAB,0xBA);
SSD_SEND(0x01,0xE1,0xBA,0xAB);
SSD_SEND(0x01,0xB1,0x10,0x01,0x47,0xFF);
SSD_SEND(0x01,0xB2,0x0C,0x14,0x04,0x50,0x50,0x14);
SSD_SEND(0x01,0xB3,0x56,0x53,0x00);
SSD_SEND(0x01,0xB4,0x33,0x30,0x04);
SSD_SEND(0x01,0xB6,0xB0,0x00,0x00,0x10,0x00,0x10,0x00);
SSD_SEND(0x01,0xB8,0x05,0x12,0x29,0x49,0x48);
SSD_SEND(0x01,0xB9,0x7C,0x65,0x55,0x49,0x46,0x36,0x3B,0x24,0x3D,0x3C,0x3D,0x5C,0x4C,0x55,0x47,0x46,0x39,0x26,0x06,0x7C,0x65,0x55,0x49,0x46,0x36,0x3B,0x24,0x3D,0x3C,0x3D,0x5C,0x4C,0x55,0x47,0x46,0x39,0x26,0x06);
SSD_SEND(0x01,0xC0,0xFF,0x87,0x12,0x34,0x44,0x44,0x44,0x44,0x98,0x04,0x98,0x04,0x0F,0x00,0x00,0xC1);
SSD_SEND(0x01,0xC1,0x54,0x94,0x02,0x85,0x9F,0x00,0x7F,0x00,0x54,0x00);
SSD_SEND(0x01,0xC2,0x17,0x09,0x08,0x89,0x08,0x11,0x22,0x20,0x44,0xFF,0x18,0x00);
SSD_SEND(0x01,0xC3,0x86,0x46,0x05,0x05,0x1C,0x1C,0x1D,0x1D,0x02,0x1F,0x1F,0x1E,0x1E,0x0F,0x0F,0x0D,0x0D,0x13,0x13,0x11,0x11,0x00);
SSD_SEND(0x01,0xC4,0x07,0x07,0x04,0x04,0x1C,0x1C,0x1D,0x1D,0x02,0x1F,0x1F,0x1E,0x1E,0x0E,0x0E,0x0C,0x0C,0x12,0x12,0x10,0x10,0x00);
SSD_SEND(0x01,0xC6,0x2A,0x2A);
SSD_SEND(0x01,0xC8,0x21,0x00,0x31,0x42,0x34,0x16);
SSD_SEND(0x01,0xCA,0xCB,0x43);
SSD_SEND(0x01,0xCD,0x0E,0x4B,0x4B,0x20,0x19,0x6B,0x06,0xB3);
SSD_SEND(0x01,0xD2,0xE3,0x2B,0x38,0x00);
SSD_SEND(0x01,0xD4,0x00,0x01,0x00,0x0E,0x04,0x44,0x08,0x10,0x00,0x00,0x00);
SSD_SEND(0x01,0xE6,0x80,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
SSD_SEND(0x01,0xF0,0x12,0x03,0x20,0x00,0xFF);
SSD_SEND(0x01,0xF3,0x00);

DCS_Short_Write_NP(0x11);
Delay(750);//delay 150ms
DCS_Short_Write_NP(0x29);
Delay(100);//delay 20ms

目前的改写都是需要自己一一改写,本文借助Chatgpt写了一个自动转换的代码,实际上是一个文本处理程序,为了节省时间,仅实现多余三个参数的情况,1个参数和2个参数还有延时的情况需要自己添加。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void convert(const char *input) {
    const char *ptr = input;
    int arg_count = 0;

    // Look for "SSD_SEND(" in the input
    ptr = strstr(input, "SSD_SEND(");

    if (ptr != NULL) {
        // Move the pointer to the end of "SSD_SEND("
        ptr += 8;

        // Print the initial part (39 00)
        printf("39 00 ");

        // Count the number of arguments
        while (*ptr != '\0' && *ptr != ')') {
            if (*ptr == '0' && *(ptr + 1) == 'x') {
                // Skip "0x" and the hexadecimal digits
                ptr += 2;
                while ((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'A' && *ptr <= 'F')) {
                    ptr++;
                }
                arg_count++;
            }
            ptr++;
        }

        // Print the argument count as a hexadecimal character
        printf("%02X", arg_count-1);

        // Print a space
        printf(" ");
    } else {
        printf("SSD_SEND not found in input.");
        return;
    }

    // Parse and print the arguments
    ptr = strstr(input, "0x");
    int first = 1;
    while (ptr != NULL) {
        if (!first) {
            // Convert the hexadecimal string to an integer
            int value = (int)strtol(ptr, (char **)&ptr, 16);
            // Print the value as a hexadecimal character
            printf("%02X ", value);
        } else {
            first = 0;
            // Skip "0x" and the hexadecimal digits
            ptr += 2;
            while ((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'A' && *ptr <= 'F')) {
                ptr++;
            }
        }
        // Look for the next "0x" occurrence
        ptr = strstr(ptr, "0x");
    }

    printf("\n");
}
void splitText(const char *text, char *line) {
    const char *delimiter = ";"; // 按分号分割
    const char *ptr = text;

    while (*ptr != '\0') {
        if (*ptr == ';') {
            strcat(line, ";"); // 追加分号
            strcat(line, "\n"); // 添加换行符
        } else {
            strncat(line, ptr, 1);
        }
        ptr++;
    }
}
int main() {

    const char *text = "SSD_SEND(0x01,0xE0,0xAB,0xBA);"
                       "SSD_SEND(0x01,0xE1,0xBA,0xAB);"
                       "SSD_SEND(0x01,0xB1,0x10,0x01,0x47,0xFF);"
                       "SSD_SEND(0x01,0xB2,0x0C,0x14,0x04,0x50,0x50,0x14);"
                       "SSD_SEND(0x01,0xB3,0x56,0x53,0x00);"
                       "SSD_SEND(0x01,0xB4,0x33,0x30,0x04);"
                       "SSD_SEND(0x01,0xB6,0xB0,0x00,0x00,0x10,0x00,0x10,0x00);"
                       "SSD_SEND(0x01,0xB8,0x05,0x12,0x29,0x49,0x48);"
                       "SSD_SEND(0x01,0xB9,0x7C,0x65,0x55,0x49,0x46,0x36,0x3B,0x24,0x3D,0x3C,0x3D,0x5C,0x4C,0x55,0x47,0x46,0x39,0x26,0x06,0x7C,0x65,0x55,0x49,0x46,0x36,0x3B,0x24,0x3D,0x3C,0x3D,0x5C,0x4C,0x55,0x47,0x46,0x39,0x26,0x06);"
                       "SSD_SEND(0x01,0xC0,0xFF,0x87,0x12,0x34,0x44,0x44,0x44,0x44,0x98,0x04,0x98,0x04,0x0F,0x00,0x00,0xC1);"
                       "SSD_SEND(0x01,0xC1,0x54,0x94,0x02,0x85,0x9F,0x00,0x7F,0x00,0x54,0x00);"
                       "SSD_SEND(0x01,0xC2,0x17,0x09,0x08,0x89,0x08,0x11,0x22,0x20,0x44,0xFF,0x18,0x00);"
                       "SSD_SEND(0x01,0xC3,0x86,0x46,0x05,0x05,0x1C,0x1C,0x1D,0x1D,0x02,0x1F,0x1F,0x1E,0x1E,0x0F,0x0F,0x0D,0x0D,0x13,0x13,0x11,0x11,0x00);"
                       "SSD_SEND(0x01,0xC4,0x07,0x07,0x04,0x04,0x1C,0x1C,0x1D,0x1D,0x02,0x1F,0x1F,0x1E,0x1E,0x0E,0x0E,0x0C,0x0C,0x12,0x12,0x10,0x10,0x00);"
                       "SSD_SEND(0x01,0xC6,0x2A,0x2A);"
                       "SSD_SEND(0x01,0xC8,0x21,0x00,0x31,0x42,0x34,0x16);"
                       "SSD_SEND(0x01,0xCA,0xCB,0x43);"
                       "SSD_SEND(0x01,0xCD,0x0E,0x4B,0x4B,0x20,0x19,0x6B,0x06,0xB3);"
                       "SSD_SEND(0x01,0xD2,0xE3,0x2B,0x38,0x00);"
                       "SSD_SEND(0x01,0xD4,0x00,0x01,0x00,0x0E,0x04,0x44,0x08,0x10,0x00,0x00,0x00);"
                       "SSD_SEND(0x01,0xE6,0x80,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);"
                       "SSD_SEND(0x01,0xF0,0x12,0x03,0x20,0x00,0xFF);"
                       ;

    char all[50000] = ""; // 初始化line

    splitText(text, all);

    // printf("%s", all); // 输出分割后的文本

    const char *delimiter = "\n";
    char *line = strtok(all, delimiter);

    while (line != NULL) {
        convert(line);
        line = strtok(NULL, delimiter);
    }

    return 0;
}

运行结果如下:
在这里插入图片描述

修改后的设备树节点:

&dsi {
	status = "okay";

	rockchip,lane-rate = <480>;
	panel@0 {
		compatible = "ilitek,ili9881d", "simple-panel-dsi";
		reg = <0>;
		backlight = <&backlight>;
		power-supply = <&vcc18_lcd_n>;
		prepare-delay-ms = <5>;
		reset-delay-ms = <1>;
		init-delay-ms = <80>;
		disable-delay-ms = <10>;
		unprepare-delay-ms = <5>;

		width-mm = <68>;
		height-mm = <121>;

		dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
			      MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
		dsi,format = <MIPI_DSI_FMT_RGB888>;
		dsi,lanes = <4>;
	    panel-init-sequence = [
			39 00 03 E0 AB BA
			39 00 03 E1 BA AB
			39 00 05 B1 10 01 47 FF
			39 00 07 B2 0C 14 04 50 50 14
			39 00 04 B3 56 53 00
			39 00 04 B4 33 30 04
			39 00 08 B6 B0 00 00 10 00 10 00
			39 00 06 B8 05 12 29 49 48
			39 00 27 B9 7C 65 55 49 46 36 3B 24 3D 3C 3D 5C 4C 55 47 46 39 26 06 7C 65 55 49 46 36 3B 24 3D 3C 3D 5C 4C 55 47 46 39 26 06
			39 00 11 C0 FF 87 12 34 44 44 44 44 98 04 98 04 0F 00 00 C1
			39 00 0B C1 54 94 02 85 9F 00 7F 00 54 00
			39 00 0D C2 17 09 08 89 08 11 22 20 44 FF 18 00
			39 00 17 C3 86 46 05 05 1C 1C 1D 1D 02 1F 1F 1E 1E 0F 0F 0D 0D 13 13 11 11 00
			39 00 17 C4 07 07 04 04 1C 1C 1D 1D 02 1F 1F 1E 1E 0E 0E 0C 0C 12 12 10 10 00
			39 00 03 C6 2A 2A
			39 00 07 C8 21 00 31 42 34 16
			39 00 03 CA CB 43
			39 00 09 CD 0E 4B 4B 20 19 6B 06 B3
			39 00 05 D2 E3 2B 38 00
			39 00 0C D4 00 01 00 0E 04 44 08 10 00 00 00
			39 00 09 E6 80 01 FF FF FF FF FF FF
			39 00 06 F0 12 03 20 00 FF
			15 00 02 F3 00
			05 FF 01 11
			05 64 01 29
		];

		display-timings {
            native-mode = <&timing0>;
            timing0: timing0 {
                clock-frequency = <78000000>;
                hactive = <800>;
                vactive = <1280>;
                hfront-porch = <80>;
                hsync-len = <20>;
                hback-porch = <80>;
                vfront-porch = <20>;
                vsync-len = <4>;
                vback-porch = <12>;
                hsync-active = <0>;
                vsync-active = <0>;
                de-active = <0>;
                pixelclk-active = <0>;
            };

		};

        
		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			port@0 {
				reg = <0>;
				panel_in_dsi: endpoint {
					remote-endpoint = <&dsi_out_panel>;
				};
			};
		};
	};

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@1 {
			reg = <1>;
			dsi_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi>;
			};
		};
	};
};

三、上电验证

在这里插入图片描述

在这里插入图片描述

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_45281309

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值