1. 核心概览

这是一款集成了电源管理、显示内存(RAM)、时序控制等多种功能的单片显示驱动芯片(通常称为Driver IC)。它采用COG(Chip-On-Glass) 工艺,直接将芯片绑定在玻璃基板上,使得屏幕模块非常轻薄紧凑。它需要外接一个主控MCU(单片机)来向其发送图像数据和指令。


2. 详细特性解释

◆ 显示分辨率选项
  • 480 (RGB) × 272 (V): 宽480像素,高272像素。这是一种常见的宽屏分辨率,也称为WVGA( Wide Video Graphics Array)。

  • 320 (RGB) × 240 (V): 宽320像素,高240像素。这是一种经典的方屏分辨率,也称为QVGA(Quarter Video Graphics Array)。

注意: 这里的“(RGB)”表示每个像素由红、绿、蓝三个子像素组成。所以实际的物理驱动通道数会更高(480 x 3 = 1440个源极通道)。

◆ LCD驱动输出电路

这说明了芯片直接驱动液晶屏的能力。

  • Source Outputs: 720 Channels: 源极输出720通道。这正好对应480 (RGB) × 3 = 1440个子像素,但通常芯片会以奇偶或分组方式驱动,所以通道数可以是物理子像素数的一半(720通道通过分时等方式驱动1440列)。

  • Gate Outputs: 544 Channels: 栅极输出544通道。这用于逐行扫描,272行分辨率只需272通道,544通道意味着它可以支持最高544行的屏幕(可能是为其他型号预留或内部设计冗余)。

  • Common Electrode Output: 公共电极输出,用于形成驱动液晶的电场。

◆ 64灰阶与6位DAC
  • 64 gray scale: 可以显示64级灰度。

  • true 6 bit DAC: 使用一个6位的数模转换器(DAC)来产生64种不同的电压电平,以精确控制每个子像素的亮度,从而混合出 64^3 = 262,144 种颜色(即26万色)。这是实现64级灰度的硬件基础。

◆ 接口(与主控MCU的连接方式)

这是芯片非常关键的部分,定义了它如何接收数据。

  • 8080-I/8080-II系列MCU接口: 这是一种并行接口,以Intel 8080系列MCU命名。速度快,但需要大量引脚。

    • 8-bits/9-bits/16-bits: 支持不同位宽的数据传输。16位模式(R5G6B5)最常用,一次传输一个像素的颜色数据。

  • 3-wire/4-wire Serial Peripheral Interface (SPI): 串行外设接口。引脚需求少(3-4根),但速度较慢,适合分辨率较低或刷新率要求不高的场景。

    • 2 data lane SPI: 双线SPI,通过两条数据线同时传输数据,速度比单线SPI快一倍。

    • Q-SPI: 四线SPI(Quad SPI),通过四条数据线同时传输,速度更快。是现代SPI接口的主流高性能模式。

总结: 接口选择提供了灵活性,高速应用用并行8080接口,节省引脚用SPI接口,追求平衡则用Q-SPI。

◆ 芯片内置电路(高度集成化的体现)

这些功能通常需要外部元件实现,但这款芯片将其集成 inside,大大简化了外围电路设计。

  • DC/DC Converter: 直流-直流转换器(电荷泵)。用于从较低的输入电压(如3.3V)生成驱动LCD所需的各种高低电压(如VGH、VGL等)。

  • Timing Controller: 时序控制器。产生驱动LCD源极和栅极所需的所有精确时序信号,是显示驱动的“大脑”。

  • Graphic RAM: 293760 bytes: 显存(帧缓存)。这个大小非常关键480 x 272 x 18-bit / 8 ≈ 293760 bytes。这意味着芯片内部有一块内存,可以存储一整帧480x272分辨率、18位色深(RGB各6位)的图像数据。MCU只需将图像数据写入这块内存,芯片就会自动循环读取并显示出来,极大减轻了MCU的负担(无需持续刷新)。

  • Non-Volatile (NV) Memory: 非易失性存储器。用于存储屏幕的初始化寄存器设置和出厂默认值。通电后芯片可以自动从NV Memory加载配置,无需MCU每次开机都重新发送一大串初始化命令。

◆ 供电电压范围

定义了芯片不同部分正常工作所需的电压。

  • I/O Voltage (1.65V ~ VCI): 用于与MCU通信的IO引脚电平,兼容1.8V等低电压逻辑。

  • Analog Voltage (VCI: 3.0V ~ 3.6V): 模拟电路的核心电压,通常是3.3V。

  • Charge pump Voltage (VCIP: 3.0V ~ 3.6V): 电荷泵的输入电压。

◆ 片上电源系统(由内部DC/DC产生)

这些是驱动LCD面板本身所需的特殊电压。

  • GVDD, GVCL: 用于驱动源极(Source)的灰度电压的正负参考电压。

  • VGH (Gate High): 打开TFT开关管的高电平电压(~15V)。

  • VGL (Gate Low): 关闭TFT开关管的低电平电压(~ -10V)。

◆ 优化布局用于COG组装
  • COG (Chip-On-Glass): 指芯片通过ACF(各向异性导电胶)直接压接绑定在LCD玻璃基板的引线上。这种工艺使显示屏模块非常薄、轻、结构紧凑。芯片的引脚布局和尺寸专门为这种工艺进行了优化。

TE 引脚是一个输出信号,其核心作用是将 LCD 控制器内部的刷新时序反馈给 MCU,让 MCU 知道何时向显存写入数据是安全的,从而避免屏幕出现"撕裂"现象。

// 1. 配置 TE 控制寄存器 (0xE7),使能输出
NV3041_WriteCommand(0xE7); // TE_CTRL 命令
NV3041_WriteData(0x10);    // 设置 D4=1 (te_out_oe=1),使能输出

// 2. 发送 TEON 命令 (0x35),选择模式并启动输出
NV3041_WriteCommand(0x35); // TEON 命令
NV3041_WriteData(0x01);    // 设置 D0=1 (te_sel=1),选择模式1 (V-Blanking + H-Blanking)
// MCU 端中断处理函数
void TE_GPIO_EXTI_Callback(void) {
    // 检测到 TE 信号的边沿(表示进入消隐期)
    if(HAL_GPIO_ReadPin(TE_GPIO_Port, TE_Pin)) {
        // 安全:现在可以开始更新显存了!
        update_frame_buffer(); // 你的画面更新函数
    }
}

// 主循环中
while (1) {
    // 主循环处理其他任务...
    // 屏幕更新由 TE 中断同步触发,不会在这里盲目更新
}

简单来说:TE 引脚就像是 LCD 对 MCU 说:"我准备好接收新数据了,现在可以安全地写了!"

当 RDX 引脚被 MCU 拉低时,NV3041A 会将内部数据或状态寄存器的内容输出到数据总线上,MCU 可以读取这些数据。

软件模拟8080驱动屏幕(已跑通):

.c


#include "k_NV3041A_lcd_driver.h"
#include "system/includes.h"
#include "kph_para.h"

para_info kph_para;

static void timer_cfg(u32 freq, u32 us)
{
    JL_TIMER_TypeDef *TMR = JL_TIMER4;//选择定时器4
    u8 timer_irq = IRQ_TIMER4_IDX;//选择定时器4
    const u8 timer_index[16] =  {0, 4, 1, 5, 2,  6,  3,  7,   8,   12,  9,    13,   10,   14,   11,    15};
    const u32 timer_table[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
    u32 clock = clk_get("timer");
    u8 psc = 0;
    u8 tmp = 0;
    u32 prd = 0;
    u32 ts = us / (1000 * 1000);//计算秒
    u32 tu = us % (1000 * 1000);//计算秒剩余us
    u8 i;
    float tp = 0;

    if (freq >= clock) {
        freq = clock;
    } else if (freq <= 1) {
        freq = 1;
        if (ts) {
            tp = (float)tu / (1000 * 1000);
        }
    }
    /*求prd值*/
    prd = clock / freq;
    if (prd > 65535) {
        for (psc = 0; psc < 16; psc++) {
            prd = (u32)(clock / (timer_table[psc]) / freq);
            if (prd <= 65535) {
                break;
            } else if (psc == 15) {
                prd = 65535;
                break;
            }
        }
    }
    prd = ts ? (prd * ts + tp * prd) : prd;
    psc = timer_index[psc];
    TMR->CON = 0;
    TMR->CNT = 0;
    TMR->CON |= BIT(14);
    TMR->PRD = prd;
    TMR->CON |= psc << 4; //lsb_clk分频
    TMR->CON |= BIT(0);
    while (!(TMR->CON & BIT(15)));
    TMR->CON |= BIT(14);
    TMR->CON = 0;
}
void time_delay(u32 us)//延时us级别
{
    u32 freq = 1000000 / us;
    timer_cfg(freq, us);//传参:当只需要设置频率,则us = 0
}



// 简单的延时函数实现
void Delayms(unsigned int ms) 
{
    // 使用系统提供的延时函数
    if(ms < 10) {
        return;
    }
    os_time_dly(ms/10);
}
/**
 * @brief 设置数据总线值 (8位)
 * @param data 要发送的8位数据
 */
static void set_data_bus(uint8_t data) {
    // 使用宏定义来设置每个数据位
    // if (data & 0x01) {LCD_D0_HIGH();} else {LCD_D0_LOW();}
    // if (data & 0x02) {LCD_D1_HIGH();} else {LCD_D1_LOW();}
    // if (data & 0x04) {LCD_D2_HIGH();} else {LCD_D2_LOW();}
    // if (data & 0x08) {LCD_D3_HIGH();} else {LCD_D3_LOW();}
    // if (data & 0x10) {LCD_D4_HIGH();} else {LCD_D4_LOW();}
    // if (data & 0x20) {LCD_D5_HIGH();} else {LCD_D5_LOW();}
    // if (data & 0x40) {LCD_D6_HIGH();} else {LCD_D6_LOW();}
    // if (data & 0x80) {LCD_D7_HIGH();} else {LCD_D7_LOW();}
    gpio_direction_output(LCD_DATA_D0, (data >> 0) & 0x01);
    gpio_direction_output(LCD_DATA_D1, (data >> 1) & 0x01);
    gpio_direction_output(LCD_DATA_D2, (data >> 2) & 0x01);
    gpio_direction_output(LCD_DATA_D3, (data >> 3) & 0x01);
    gpio_direction_output(LCD_DATA_D4, (data >> 4) & 0x01);
    gpio_direction_output(LCD_DATA_D5, (data >> 5) & 0x01);
    gpio_direction_output(LCD_DATA_D6, (data >> 6) & 0x01);
    gpio_direction_output(LCD_DATA_D7, (data >> 7) & 0x01);
}

/**
 * @brief 产生WRX写脉冲
 */
static void generate_wrx_pulse(void) {
    
    // 需要短暂延时,确保建立时间和保持时间
    // 这里用空循环实现简短延时,具体时间需要根据你的MCU频率调整
    // time_delay(5);
    WR_GPIO_HIGH();  // WRX拉高 (上升沿)
    // time_delay(5);
}

/**
 * @brief 写命令到NV3041A (8080并行接口)
 * @param cmd 命令字节
 */
void NV3041_SPI_Write_cmd(uint8_t cmd) {
    // 1. 设置DCX为低电平 (命令模式)
    DC_GPIO_LOW();
    
    // 2. 片选有效 (低电平有效)
    CS_GPIO_LOW();

    RD_GPIO_HIGH();

    WR_GPIO_LOW();  // WRX拉低 (下降沿)
    
    // 3. 设置数据总线
    set_data_bus(cmd);
    
    // 4. 产生WRX写脉冲 (上升沿锁存数据)
    generate_wrx_pulse();
    
    

    // 5. 恢复DCX为高电平 (数据模式)
    DC_GPIO_HIGH();

    // 6. 释放片选
    CS_GPIO_HIGH();
}

/**
 * @brief 写数据到NV3041A (8080并行接口)
 * @param data 数据字节
 */
void NV3041_SPI_Write_data(uint8_t data) {
    // 1. DCX为高电平 (数据模式)
    DC_GPIO_HIGH();
    
    // 2. 片选有效 (低电平有效)
    CS_GPIO_LOW();

    RD_GPIO_HIGH();

    WR_GPIO_LOW();  // WRX拉低 (下降沿)
    
    // 3. 设置数据总线
    set_data_bus(data);
    
    // 4. 产生WRX写脉冲 (下降沿锁存数据)
    generate_wrx_pulse();
    
    DC_GPIO_LOW();
    // 5. 释放片选
    CS_GPIO_HIGH();
}


//推挽输出
void gpio_push_pull_init(unsigned int gpio,int value)
{
    gpio_set_pull_up(gpio, 0);
    gpio_set_pull_down(gpio, 0);
    gpio_direction_output(gpio, value);
}
//浮空输入
void gpio_pull_float_init(unsigned int gpio)
{
    gpio_set_pull_up(gpio, 0);
    gpio_set_pull_down(gpio, 0);
    gpio_set_die(gpio, 1);
    gpio_direction_input(gpio);
}

static void *TE_IntHandler(void)   //外部中断处理
{
    printf("hello,lcd");
}

void TE_gpio_init(void)
{
    port_wakeup_reg(EVENT_IO_0, LCD_TE, EDGE_POSITIVE, TE_IntHandler);//gpio中断模式使用
}

/**
 * @brief 设置数据总线为输出模式(用于写操作)
 */
static void set_data_bus_output(void) {
    gpio_push_pull_init(LCD_DATA_D0, 0);
    gpio_push_pull_init(LCD_DATA_D1, 0);
    gpio_push_pull_init(LCD_DATA_D2, 0);
    gpio_push_pull_init(LCD_DATA_D3, 0);
    gpio_push_pull_init(LCD_DATA_D4, 0);
    gpio_push_pull_init(LCD_DATA_D5, 0);
    gpio_push_pull_init(LCD_DATA_D6, 0);
    gpio_push_pull_init(LCD_DATA_D7, 0);
}

/**
 * @brief 设置数据总线为输入模式(用于读操作)
 */
static void set_data_bus_input(void) {
    // 根据你的SDK配置为输入模式,可能需要使用不同的函数
    gpio_pull_float_init(LCD_DATA_D0);
    gpio_pull_float_init(LCD_DATA_D1);
    gpio_pull_float_init(LCD_DATA_D2);
    gpio_pull_float_init(LCD_DATA_D3);
    gpio_pull_float_init(LCD_DATA_D4);
    gpio_pull_float_init(LCD_DATA_D5);
    gpio_pull_float_init(LCD_DATA_D6);
    gpio_pull_float_init(LCD_DATA_D7);
}



//初始化LCD GPIO
void NV3041A_lcd_gpio_init(void)
{
    set_data_bus_output();

    gpio_push_pull_init(LCD_DC,0);
    gpio_push_pull_init(LCD_RD,0);
    gpio_push_pull_init(LCD_WR,0);
    gpio_push_pull_init(LCD_CS,0);
    gpio_push_pull_init(LCD_RESET,0);

    // TE_gpio_init();

}


/**
 * @brief 从数据总线读取一个字节
 * @return 读取到的数据
 */
static uint8_t read_data_bus(void) {
    uint8_t data = 0;
    
    data |= (gpio_read(LCD_DATA_D0) << 0);
    data |= (gpio_read(LCD_DATA_D1) << 1);
    data |= (gpio_read(LCD_DATA_D2) << 2);
    data |= (gpio_read(LCD_DATA_D3) << 3);
    data |= (gpio_read(LCD_DATA_D4) << 4);
    data |= (gpio_read(LCD_DATA_D5) << 5);
    data |= (gpio_read(LCD_DATA_D6) << 6);
    data |= (gpio_read(LCD_DATA_D7) << 7);
    
    return data;
}

/**
 * @brief 设置显示窗口(定义要更新的区域)
 * @param x_start 起始列地址
 * @param y_start 起始行地址  
 * @param x_end 结束列地址
 * @param y_end 结束行地址
 */
void NV3041_SetWindow(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end) {
    // 设置列地址 (X方向)
    NV3041_SPI_Write_cmd(0x2A); // COL_ADR 命令
    NV3041_SPI_Write_data(x_start >> 8);    // 起始地址高字节
    NV3041_SPI_Write_data(x_start & 0xFF);  // 起始地址低字节
    NV3041_SPI_Write_data(x_end >> 8);      // 结束地址高字节  
    NV3041_SPI_Write_data(x_end & 0xFF);    // 结束地址低字节

    // 设置行地址 (Y方向)
    NV3041_SPI_Write_cmd(0x2B); // ROW_ADR 命令
    NV3041_SPI_Write_data(y_start >> 8);    // 起始地址高字节
    NV3041_SPI_Write_data(y_start & 0xFF);  // 起始地址低字节
    NV3041_SPI_Write_data(y_end >> 8);      // 结束地址高字节
    NV3041_SPI_Write_data(y_end & 0xFF);    // 结束地址低字节
}

/**
 * @brief 填充整个屏幕为指定颜色
 * @param color RGB565格式的颜色值
 */
void NV3041_FillScreen(uint16_t color) {
    // 1. 设置显示窗口为全屏
    NV3041_SetWindow(0, 0, WIDTH-1, HEIGHT-1); // 480x272 屏幕
    
    // 2. 发送内存写命令
    NV3041_SPI_Write_cmd(0x2C); // MEMWR 命令
    
    // 3. 写入整个屏幕的像素数据
    uint32_t total_pixels = WIDTH * HEIGHT;
    uint8_t high_byte = color >> 8;   // 颜色高字节
    uint8_t low_byte = color & 0xFF;  // 颜色低字节
    
    for(uint32_t i = 0; i < total_pixels; i++) {
        NV3041_SPI_Write_data(high_byte);
        NV3041_SPI_Write_data(low_byte);
    }
}






void NV3041A_lcd_driver(void)
{
    //NV3041A-01+HK4.3IPS 外置VCOM pixel 5-6-5 code--16bit 20240425
    NV3041_SPI_Write_cmd(0xff);
    NV3041_SPI_Write_data(0xa5);

    NV3041_SPI_Write_cmd(0xE7);//TE_output_en
    NV3041_SPI_Write_data(0x10);

    NV3041_SPI_Write_cmd(0x35);//TE_ interface_en
    NV3041_SPI_Write_data(0x01);

    NV3041_SPI_Write_cmd(0x3A);
    NV3041_SPI_Write_data(0x01);//00---666//01--565

    NV3041_SPI_Write_cmd(0x40);
    NV3041_SPI_Write_data(0x01);  //01:IPS/00:TN  

    NV3041_SPI_Write_cmd(0x41);	   
    NV3041_SPI_Write_data(0x01);//01--8bit//03--16bit

    NV3041_SPI_Write_cmd(0x55);
    NV3041_SPI_Write_data(0x01); 

    NV3041_SPI_Write_cmd(0x44);//VBP  
    NV3041_SPI_Write_data(0x15);//21

    NV3041_SPI_Write_cmd(0x45);//VFP  
    NV3041_SPI_Write_data(0x15);//21

    NV3041_SPI_Write_cmd(0x7d);//vdds_trim[2:0]
    NV3041_SPI_Write_data(0x03);//2.07V
                                
    NV3041_SPI_Write_cmd(0xc1);//avdd_clp_en avdd_clp[1:0] avcl_clp_en avcl_clp[1:0]
    NV3041_SPI_Write_data(0xab);//6.74V/-5.16V

    NV3041_SPI_Write_cmd(0xc2);//vgh_clp_en vgl_clp[2:0]		
    NV3041_SPI_Write_data(0x17);

    NV3041_SPI_Write_cmd(0xc3);//vgl_clp_en vgl_clp[2:0]		
    NV3041_SPI_Write_data(0x10);//-10.951

    NV3041_SPI_Write_cmd(0xc6);//avdd_ratio_sel avcl_ratio_sel vgh_ratio_sel[1:0] vgl_ratio_sel[1:0]	
    NV3041_SPI_Write_data(0x3a);//35

    NV3041_SPI_Write_cmd(0xc7);//mv_clk_sel[1:0] avdd_clk_sel[1:0] avcl_clk_sel[1:0]	
    NV3041_SPI_Write_data(0x25); //2e

    NV3041_SPI_Write_cmd(0xc8);//	VGL_CLK_sel
    NV3041_SPI_Write_data(0x11); 

    NV3041_SPI_Write_cmd(0x7a);//	user_vgsp
    NV3041_SPI_Write_data(0x55);

    NV3041_SPI_Write_cmd(0x6f);//	user_gvdd
    NV3041_SPI_Write_data(0x2f);

    NV3041_SPI_Write_cmd(0x78);//	user_gvcl								
    NV3041_SPI_Write_data(0x29);

    NV3041_SPI_Write_cmd(0x73);//osc
    NV3041_SPI_Write_data(0x08);

    NV3041_SPI_Write_cmd(0x74);
    NV3041_SPI_Write_data(0x15);//12

    NV3041_SPI_Write_cmd(0xc9);
    NV3041_SPI_Write_data(0x00); 

    NV3041_SPI_Write_cmd(0x67);	   
    NV3041_SPI_Write_data(0x33);//11

    //gate_ed
    NV3041_SPI_Write_cmd(0x51);//gate_st_o[7:0]
    //NV3041_SPI_Write_data(0x4b);
    NV3041_SPI_Write_data(0x20);

    NV3041_SPI_Write_cmd(0x52);//gate_ed_o[7:0]
    NV3041_SPI_Write_data(0x7c);

    NV3041_SPI_Write_cmd(0x53);//gate_st_e[7:0]
    //NV3041_SPI_Write_data(0x45);
    NV3041_SPI_Write_data(0x1c);

    NV3041_SPI_Write_cmd(0x54);//gate_ed_e[7:0]
    NV3041_SPI_Write_data(0x77);

    ////sorce old
    NV3041_SPI_Write_cmd(0x46);//fsm_hbp_o[5:0]
    NV3041_SPI_Write_data(0x0a);

    NV3041_SPI_Write_cmd(0x47);//fsm_hfp_o[5:0]
    NV3041_SPI_Write_data(0x2a);

    NV3041_SPI_Write_cmd(0x48);//fsm_hbp_e[5:0]
    NV3041_SPI_Write_data(0x0a);

    NV3041_SPI_Write_cmd(0x49);//fsm_hfp_e[5:0]
    NV3041_SPI_Write_data(0x1a);

    NV3041_SPI_Write_cmd(0x56);//src_ld_wd[1:0] src_ld_st[5:0]
    NV3041_SPI_Write_data(0x43);

    NV3041_SPI_Write_cmd(0x57);//pn_cs_en src_cs_st[5:0]
    NV3041_SPI_Write_data(0x42);

    NV3041_SPI_Write_cmd(0x58);//src_cs_p_wd[6:0]
    NV3041_SPI_Write_data(0x3c);

    NV3041_SPI_Write_cmd(0x59);//src_cs_n_wd[6:0]
    NV3041_SPI_Write_data(0x64); 

    NV3041_SPI_Write_cmd(0x5a);//src_pchg_st_o[6:0]
    NV3041_SPI_Write_data(0x41);  

    NV3041_SPI_Write_cmd(0x5b);//src_pchg_wd_o[6:0]
    NV3041_SPI_Write_data(0x3c); 

    NV3041_SPI_Write_cmd(0x5c);//src_pchg_st_e[6:0]
    NV3041_SPI_Write_data(0x02);	

    NV3041_SPI_Write_cmd(0x5d);//src_pchg_wd_e[6:0]
    NV3041_SPI_Write_data(0x3c);	


    NV3041_SPI_Write_cmd(0x5e);//src_pol_sw[7:0]
    NV3041_SPI_Write_data(0x1f);

    NV3041_SPI_Write_cmd(0x60);//src_op_st_o[7:0]
    NV3041_SPI_Write_data(0x80);

    NV3041_SPI_Write_cmd(0x61);//src_op_st_e[7:0]
    NV3041_SPI_Write_data(0x3f);

    NV3041_SPI_Write_cmd(0x62);//src_op_ed_o[9:8] src_op_ed_e[9:8]
    NV3041_SPI_Write_data(0x21);

    NV3041_SPI_Write_cmd(0x63);//src_op_ed_o[7:0]
    NV3041_SPI_Write_data(0x07);

    NV3041_SPI_Write_cmd(0x64);//src_op_ed_e[7:0]
    NV3041_SPI_Write_data(0xe0);

    NV3041_SPI_Write_cmd(0x65);//chopper
    NV3041_SPI_Write_data(0x01);//01-A2,02--A1

    NV3041_SPI_Write_cmd(0xca);	   //avdd_mux_st_o[7:0]
    NV3041_SPI_Write_data(0x20);

    NV3041_SPI_Write_cmd(0xcb);	   //avdd_mux_ed_o[7:0]
    NV3041_SPI_Write_data(0x52);	 

    NV3041_SPI_Write_cmd(0xcc);	   //avdd_mux_st_e[7:0]
    NV3041_SPI_Write_data(0x10);

    NV3041_SPI_Write_cmd(0xcD);	   //avdd_mux_ed_e[7:0]
    NV3041_SPI_Write_data(0x42);

    NV3041_SPI_Write_cmd(0xD0);  //avcl_mux_st_o[7:0]
    NV3041_SPI_Write_data(0x20);

    NV3041_SPI_Write_cmd(0xD1);  //avcl_mux_ed_o[7:0]
    NV3041_SPI_Write_data(0x52);

    NV3041_SPI_Write_cmd(0xD2);  //avcl_mux_st_e[7:0]
    NV3041_SPI_Write_data(0x10);

    NV3041_SPI_Write_cmd(0xD3);  //avcl_mux_ed_e[7:0]
    NV3041_SPI_Write_data(0x42);

    NV3041_SPI_Write_cmd(0xD4);  //vgh_mux_st[7:0]
    NV3041_SPI_Write_data(0x0a);

    NV3041_SPI_Write_cmd(0xD5);  //vgh_mux_ed[7:0]
    NV3041_SPI_Write_data(0x32);

    NV3041_SPI_Write_cmd(0xe5);	   //DVDD_TRIM
    NV3041_SPI_Write_data(0x06);   //1.65	 05

    NV3041_SPI_Write_cmd(0xe6);	   //ESD_CTRL
    NV3041_SPI_Write_data(0x00);

    NV3041_SPI_Write_cmd(0x6e);	   //LVD_en
    NV3041_SPI_Write_data(0x14);

    //gammma 01
    NV3041_SPI_Write_cmd(0x80);	   //gam_vrp0	     63
    NV3041_SPI_Write_data(0x02);//04
    NV3041_SPI_Write_cmd(0xA0);    //gam_VRN0	     63
    NV3041_SPI_Write_data(0x02);//00

    NV3041_SPI_Write_cmd(0x81);	   //gam_vrp1	     62
    NV3041_SPI_Write_data(0x04);//07
    NV3041_SPI_Write_cmd(0xA1);    //gam_VRN1		 62-
    NV3041_SPI_Write_data(0x04);//05

    NV3041_SPI_Write_cmd(0x82);	   //gam_vrp2	     61	
    NV3041_SPI_Write_data(0x01);//06
    NV3041_SPI_Write_cmd(0xA2);    //gam_VRN2		 61-
    NV3041_SPI_Write_data(0x01);//04

    NV3041_SPI_Write_cmd(0x83);	   //gam_vrp3	     2
    NV3041_SPI_Write_data(0x07);//39
    NV3041_SPI_Write_cmd(0xA3);    //gam_VRN3		2-
    NV3041_SPI_Write_data(0x07);//39

    NV3041_SPI_Write_cmd(0x84);	   //gam_vrp4	     1
    NV3041_SPI_Write_data(0x0a);//3A
    NV3041_SPI_Write_cmd(0xA4);    //gam_VRN4		 1-
    NV3041_SPI_Write_data(0x0a);//3A

    NV3041_SPI_Write_cmd(0x85);	   //gam_vrp5	     0
    NV3041_SPI_Write_data(0x0f);//3F   
    NV3041_SPI_Write_cmd(0xA5);    //gam_VRN5		 0-
    NV3041_SPI_Write_data(0x0f);//3F

    NV3041_SPI_Write_cmd(0x86);	   //gam_prp0	     50
    NV3041_SPI_Write_data(0x13);//2C
    NV3041_SPI_Write_cmd(0xA6);   //gam_PRN0	 	   50-
    NV3041_SPI_Write_data(0x13);//2a

    NV3041_SPI_Write_cmd(0x87);	   //gam_prp1	 	14
    NV3041_SPI_Write_data(0x17);//43//19
    NV3041_SPI_Write_cmd(0xA7);    //gam_PRN1	 	14-
    NV3041_SPI_Write_data(0x1b);//47//19

    NV3041_SPI_Write_cmd(0x88);	   //gam_pkp0	  	 59
    NV3041_SPI_Write_data(0x07);//08
    NV3041_SPI_Write_cmd(0xA8);    //gam_PKN0		 59-
    NV3041_SPI_Write_data(0x07);//08

    NV3041_SPI_Write_cmd(0x89);	   //gam_pkp1	    57
    NV3041_SPI_Write_data(0x0f);//0F
    NV3041_SPI_Write_cmd(0xA9);    //gam_PKN1		57-
    NV3041_SPI_Write_data(0x0E);//0F

    NV3041_SPI_Write_cmd(0x8a);	   //gam_pkp2	    54
    NV3041_SPI_Write_data(0x17);//1a
    NV3041_SPI_Write_cmd(0xAa);	   //gam_PKN2		54-
    NV3041_SPI_Write_data(0x17);//1a

    NV3041_SPI_Write_cmd(0x8b);	   //gam_PKP3	    44
    NV3041_SPI_Write_data(0x11);//10
    NV3041_SPI_Write_cmd(0xAb);    //gam_PKN3		44-
    NV3041_SPI_Write_data(0x10);//10

    NV3041_SPI_Write_cmd(0x8c);	   //gam_PKP4	    38
    NV3041_SPI_Write_data(0x16);//16 
    NV3041_SPI_Write_cmd(0xAc);	   //gam_PKN4		38-
    NV3041_SPI_Write_data(0x16);//16

    NV3041_SPI_Write_cmd(0x8d);	   //gam_PKP5		32
    NV3041_SPI_Write_data(0x15);//14
    NV3041_SPI_Write_cmd(0xAd);  //gam_PKN5		    32-
    NV3041_SPI_Write_data(0x15);//14

    NV3041_SPI_Write_cmd(0x8e);	   //gam_PKP6		26
    NV3041_SPI_Write_data(0x14);//11
    NV3041_SPI_Write_cmd(0xAe);    //gam_PKN6		26-
    NV3041_SPI_Write_data(0x14);//11

    NV3041_SPI_Write_cmd(0x8f);	   //gam_PKP7		20
    NV3041_SPI_Write_data(0x16);//14//16
    NV3041_SPI_Write_cmd(0xAf);	   //gam_PKN7		20-
    NV3041_SPI_Write_data(0x16);//14//16

    NV3041_SPI_Write_cmd(0x90);	   //gam_PKP8		10
    NV3041_SPI_Write_data(0x06);//06
    NV3041_SPI_Write_cmd(0xB0);	   //gam_PKN8	   	10-
    NV3041_SPI_Write_data(0x06);//06

    NV3041_SPI_Write_cmd(0x91);	   //gam_PKP9		6
    NV3041_SPI_Write_data(0x0f);//0F//0f
    NV3041_SPI_Write_cmd(0xB1);	   //gam_PKN9		6-
    NV3041_SPI_Write_data(0x0e);//0F//0e
                                                    
    NV3041_SPI_Write_cmd(0x92);	   //gam_PKP10		4	
    NV3041_SPI_Write_data(0x14);//16
    NV3041_SPI_Write_cmd(0xB2);	   //gam_PKN10		4-
    NV3041_SPI_Write_data(0x14);//16

    NV3041_SPI_Write_cmd(0xff);
    NV3041_SPI_Write_data(0x00);  

    NV3041_SPI_Write_cmd(0x11);
    time_delay(200);
                                    
    NV3041_SPI_Write_cmd(0x29);
    time_delay(120);

    printf("发送完成");
}





/**
 * @brief 简单的读取ID尝试
 */
void Simple_Read_ID_Test(void) {
    // 先发送读ID命令
    NV3041_SPI_Write_cmd(0x04); // RD_SYSID
    
    // 然后尝试读取(可能需要在读之前加延时)
    // Delayms(10);

    // 尝试读取一个字节
    set_data_bus_input();

    CS_GPIO_LOW(); // 片选

    DC_GPIO_HIGH(); 

    RD_GPIO_HIGH();

    time_delay(5);

    RD_GPIO_LOW();

    time_delay(5);

    RD_GPIO_HIGH();
    
    
    time_delay(5);

    uint8_t data = read_data_bus();
    
    CS_GPIO_HIGH();
    set_data_bus_output();
    
    printf("读取到的第一个字节: 0x%02X\r\n", data);
}



void func_test(void)
{
    printf("func_test");
    
    NV3041A_lcd_driver();

    time_delay(200);

    // 填充整个屏幕为红色
    NV3041_FillScreen(RGB565_RED);

    while(1)
    {
        // os_time_dly(300);  //3秒
        NV3041_FillScreen(RGB565_RED);
        // os_time_dly(300);  
        NV3041_FillScreen(RGB565_GREEN);
        // os_time_dly(300);  
        NV3041_FillScreen(RGB565_BLUE);
    }

    // while(1)
    // {
    //     WR_GPIO_LOW();
    //     WR_GPIO_HIGH();
    // }

}

void k_test(void)
{
    NV3041_SPI_Write_cmd(0xff);
    NV3041_SPI_Write_data(0xa5);

    NV3041_SPI_Write_cmd(0xE7);//TE_output_en
    NV3041_SPI_Write_data(0x10);

    NV3041_SPI_Write_cmd(0x35);//TE_ interface_en
    NV3041_SPI_Write_data(0x01);
}

void minimal_test(void) {
    // 只做最基础的初始化
    // check_reset();
    
    NV3041_SPI_Write_cmd(0x11); // Sleep Out
    time_delay(120);
    
    NV3041_SPI_Write_cmd(0x29); // Display On
    time_delay(50);
    
    // 如果这样屏幕能亮,说明电源基本正常
}

void lcd_reset(void)
{
    RESET_GPIO_HIGH();
    time_delay(100);
    RESET_GPIO_LOW();
    time_delay(200);
    RESET_GPIO_HIGH();
    time_delay(100);
}



void lcd_init(void)
{
    printf("lcd_init");

    NV3041A_lcd_gpio_init();

    lcd_reset();

    
    // Simple_Read_ID_Test();

    // sys_timeout_add_to_task("sys_timer", NULL, func_test, 2000);


    if (thread_fork("func_test", 10, 512, 0, &kph_para.lcd_init_id, func_test, NULL) != OS_NO_ERR)
    {
        printf("thread fork fail\n");
    }


}

.h

#ifndef __K_NV3041A_LCD_DRIVER_H__
#define __K_NV3041A_LCD_DRIVER_H__

#include "app_config.h"
#include "system/includes.h"
#include "device/device.h"
#include <time.h>
#include <sys/time.h>

#include "device/gpio.h"
#include "asm/gpio.h"

#include "wifi/wifi_connect.h"

#include "server/audio_server.h"

#include "asm/port_waked_up.h"


#define WIDTH 480
#define HEIGHT 272



/**
 * @brief RGB565颜色宏定义
 */
#define RGB565_RED     0xF800  // 红色: 11111 000000 00000
#define RGB565_GREEN   0x07E0  // 绿色: 00000 111111 00000  
#define RGB565_BLUE    0x001F  // 蓝色: 00000 000000 11111
#define RGB565_WHITE   0xFFFF  // 白色: 11111 111111 11111
#define RGB565_BLACK   0x0000  // 黑色: 00000 000000 00000
#define RGB565_YELLOW  0xFFE0  // 黄色: 11111 111111 00000



#define LCD_DATA_D0  IO_PORTC_01
#define LCD_DATA_D1  IO_PORTC_02
#define LCD_DATA_D2  IO_PORTC_03
#define LCD_DATA_D3  IO_PORTC_04
#define LCD_DATA_D4  IO_PORTC_05
#define LCD_DATA_D5  IO_PORTC_06
#define LCD_DATA_D6  IO_PORTC_07
#define LCD_DATA_D7  IO_PORTC_08


#define LCD_TE       IO_PORTH_04
#define LCD_DC       IO_PORTH_03
#define LCD_RD       IO_PORTC_09
#define LCD_WR       IO_PORTC_10
#define LCD_CS       IO_PORTC_00
#define LCD_RESET    IO_PORTH_05

#define LCD_D0_HIGH() gpio_direction_output(LCD_DATA_D0,1)
#define LCD_D0_LOW() gpio_direction_output(LCD_DATA_D0,0)
#define LCD_D1_HIGH() gpio_direction_output(LCD_DATA_D1,1)
#define LCD_D1_LOW() gpio_direction_output(LCD_DATA_D1,0)
#define LCD_D2_HIGH() gpio_direction_output(LCD_DATA_D2,1)
#define LCD_D2_LOW() gpio_direction_output(LCD_DATA_D2,0)
#define LCD_D3_HIGH() gpio_direction_output(LCD_DATA_D3,1)
#define LCD_D3_LOW() gpio_direction_output(LCD_DATA_D3,0)
#define LCD_D4_HIGH() gpio_direction_output(LCD_DATA_D4,1)
#define LCD_D4_LOW() gpio_direction_output(LCD_DATA_D4,0)
#define LCD_D5_HIGH() gpio_direction_output(LCD_DATA_D5,1)
#define LCD_D5_LOW() gpio_direction_output(LCD_DATA_D5,0)
#define LCD_D6_HIGH() gpio_direction_output(LCD_DATA_D6,1)
#define LCD_D6_LOW() gpio_direction_output(LCD_DATA_D6,0)
#define LCD_D7_HIGH() gpio_direction_output(LCD_DATA_D7,1)
#define LCD_D7_LOW() gpio_direction_output(LCD_DATA_D7,0)


    
#define WR_GPIO_HIGH() gpio_direction_output(LCD_WR,1)
#define WR_GPIO_LOW() gpio_direction_output(LCD_WR,0)


//DCX = “H” is data     DCX = “L” is command
#define DC_GPIO_LOW() gpio_direction_output(LCD_DC,0)
#define DC_GPIO_HIGH() gpio_direction_output(LCD_DC,1)
#define CS_GPIO_LOW() gpio_direction_output(LCD_CS,0)
#define CS_GPIO_HIGH() gpio_direction_output(LCD_CS,1)
//低电平复位,高电平正常工作
#define RESET_GPIO_LOW() gpio_direction_output(LCD_RESET,0)
#define RESET_GPIO_HIGH() gpio_direction_output(LCD_RESET,1)


//下降沿屏幕发送数据到总线上,上升沿总线上数据被读取
#define RD_GPIO_LOW() gpio_direction_output(LCD_RD,0)
#define RD_GPIO_HIGH() gpio_direction_output(LCD_RD,1)







#endif

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐