2. 点屏示例(LVDS)

本章节主要介绍点亮LVDS 2Port接口的模组,显示 SD 卡.BMP 图片、程序代码产生的画面,按键上翻 下翻 切换画面、 ON/OFF 开关显示。

主要内容: - 1 硬件初始化

  • 2 初始化IO口,设置IO口电压。

  • 3 LCD 参数设置。包括接口模式,分辨率,RGB 时序(Video mode)

  • 4 加载画面。调用 SD 卡.BMP (必须是 24 位 bmp),和代码产生规则画面。

  • 5 实现 按键“上翻”、“下翻”切换画面,ON/OFF 开关显示

Attention

while 循环里需要放置10ms的延时,来维持系统的正常运行。

2.1. 硬件初始化

初始化K2000板载各种外设,电源板,背光板,信号板。

My_Board = Set_Board_All()

2.2. 初始化IO口,设置IO口电压

设置IO口电压

SHAP_user.My_Board.IOVOL_Set(3.3)

初始化IO口

IT_ON_OFF = Pin_Device.LCD__IO_5 #外部IO口宏
IT_MTP = Pin_Device.LCD__IO_6    #外部IO口宏

My_IT_ON_OFF_Pin = Pin_Device(IT_ON_OFF,Pin_Device.IN)  #第一个参数是定义好的外部IO口宏,第二个参数是IO口输入输出模式
My_IT_MTP_Pin = Pin_Device(IT_MTP,Pin_Device.IN)        #Pin_Device.IN 和 Pin_Device.OUT 就是配置输入或者输出模式

2.3. LCD 屏幕参数设置

点屏前需要对屏幕参数设置,通过配置 lvds_panel_par 点屏参数类对象,并通过 Display_Lvds_Init 方法生效。

  • 点屏参数类 具体有以下几个参数:

    • autoPanelFre :屏幕刷新率,此值设置之后,pclk设置无效

    • pclk:屏幕pclk时钟 单位:Mhz,支持小数

    • h_active:水平同步信号的的有效像素

    • h_pulse_width:水平同步信号的脉冲宽度

    • h_front_porch: 水平同步信号的前沿

    • h_back_porch: 水平同步信号的前沿

    • v_active: 垂直同步信号的有效像素

    • v_pulse_width: 垂直同步信号的脉冲宽度

    • v_front_porch: 垂直同步信号的前沿

    • v_back_porch: 垂直同步信号的后沿

    • bit_mode: 数据位数

      • MiPi_18_BIT = 0 # 18 Bit

      • MiPi_24_BIT = 1 # 24 Bit

      • MiPi_30_BIT = 2 # 30 Bit

    • pclk_edge: pclk锁存边缘

      • MiPi_FALLING_EDGE = 0 # 下降沿锁存数据

      • MiPi_RISING_EDGE = 1 # 上升沿锁存数据

    • h_active_edge: 水平同步信号的有效电平

      • MiPi_LOW_ACTIVE = 0 # 低电平有效

      • MiPi_HIGH_ACTIVE = 1 # 高电平有效

    • v_active_edge: 垂直同步信号的有效电平

      • MiPi_LOW_ACTIVE = 0 # 低电平有效

      • MiPi_HIGH_ACTIVE = 1 # 高电平有效

    • de_active_edge: de脉冲有效电平

      • MiPi_LOW_ACTIVE = 0 # 低电平有效

      • MiPi_HIGH_ACTIVE = 1 # 高电平有效

    • display_mode: 显示模式

      • LVDS_1Port_Display = 0 # 1port

      • LVDS_2Port_Display = 1 # 2port

      • LVDS_3Port_Display = 2 # 3port

      • LVDS_4Port_Display = 3 # 4port

      • LVDS_2Port_Split_Display = 4 # 2port 左右分屏

      • LVDS_3Port_Split_Display = 5 # 3port 三分屏

      • LVDS_4Port_Split_Display = 6 # 4port 左右分屏

    • dat_format: 数据格式

      • LVDS_VESA = 0 # 标准显示

      • LVDS_JEIDA = 1 # JEIDA格式

    • rgb_dir: RGB方向

      • LVDS_DIR_RGB = 0 # RGB

      • LVDS_DIR_BGR = 1 # BGR

    • port_dir: port顺序

      • LVDS_PortDir_Normal = 0 #port顺序正向

      • LVDS_PortDir_Opposite = 1 #port顺序反向

    • port_group: port组合

      • LVDS_PortGroup_Left = 0 #靠左组合port

      • LVDS_PortGroup_Right = 1 #靠右组合port

  • 更多详情可参考 LVDS点屏模块

def parameter_settings():
    # ''' 点屏参数配置 '''
    LVDS_struct = lvds_panel_par()

    LVDS_struct.autoPanelFre = 60  # 屏幕刷新率 ,此值设置之后,pclk设置无效
    LVDS_struct.pclk = 69  # PCLK时钟

    LVDS_struct.h_active = 1920  # 水平的有效像素
    LVDS_struct.h_back_porch = 60  # 水平的后沿
    LVDS_struct.h_front_porch = 90  # 水平的前沿
    LVDS_struct.h_pulse_width = 30  # 水平的脉冲

    LVDS_struct.v_active = 1080  # 垂直的有效像素
    LVDS_struct.v_back_porch = 8  # 垂直的后沿
    LVDS_struct.v_front_porch = 8  # 垂直的前沿
    LVDS_struct.v_pulse_width = 5  # 垂直的脉冲

    LVDS_struct.display_mode = LVDS_2Port_Display  # 显示模式
    LVDS_struct.bit_mode = LVDS_24_BIT  # 数据位数
    LVDS_struct.dat_format = LVDS_VESA  # 数据格式
    LVDS_struct.rgb_dir = LVDS_DIR_RGB  # RGB方向

    LVDS_struct.pclk_edge = LVDS_RISING_EDGE  # pclk锁存边缘
    LVDS_struct.h_active_edge = LVDS_LOW_ACTIVE  # h脉冲有效电平
    LVDS_struct.v_active_edge = LVDS_LOW_ACTIVE  # v脉冲有效电平
    LVDS_struct.de_active_edge = LVDS_HIGH_ACTIVE  # de脉冲有效电平

    SHARP_Display_Lvds_Init(LVDS_struct.autoPanelFre, LVDS_struct)

2.4. 加载画面

  • 这段代码是一个名为LoadFrame的函数,主要是用于加载画面。本示例程序画面加载的是来自 SD 卡的图片。

  • Img_SDCard_BMP函数第一个参数是加载画面的文件名,第二个参数是画面保持时间,通过调用image.Img_SDCard_BMP函数来实现图像文件的加载。加载完成后,会输出调试信息”Load image OK”表示加载完成。

Attention

目前K2000还不支持预加载用户自行编写的画面,相信在不远的将来能实现这个功能。

def LoadFrame():
    print("Load image..")
    image.Img_SDCard_BMP('/sdcard/Full Red_compresed.bmp',0)
    image.Img_SDCard_BMP('/sdcard/Full Green_compresed.bmp',0)
    image.Img_SDCard_BMP('/sdcard/Full Blue_compresed.bmp',0)
    image.Img_Full(255,0,0)
    image.Img_Full(0,255,0)
    image.Img_Full(0,0,255)
    print("Load image OK")

2.5. 上下电控制

设置液晶模组所需的电源电压、背光电流,输出图像信号等。体现在 Display_ON_Trad() 和 Display_OFF()两个函数。

设置电源电压

设置某VDD通道电压使用的方法为 POWER_SetVDD( ch, v)

ch :通道号, =1 代表VDD1 v :要输出的电压值,单位V,精度 0.1V

更多电源功能函数使用可参考 电源板功能

输出图像信号

输出图像信号使用的方法为 UserLvds_ON(index = None)

  • Display_ON_Trad()Display_OFF() 代码如下:

# 传统上电模式
def Display_ON_Trad():

    print('Display ON')

    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,1,2000)
    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,2,2000)

    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,3,2000)
    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,4,2000)

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 1, 3.3)
    if ret !=0:
        print('VDD%d NG'%(1))

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 2, 12)
    if ret !=0:
        print('VDD%d NG'%(2))

    user_mode.Delay_ms(5)
    SwitchFrame(SHAP_user.frame)

    UserLvds_ON()
    user_mode.Delay_ms(100)

    for i in range(1,13):
        SHAP_user.My_Board.LED_SetI(SHAP_user.Power_Flag, i, 10)

    user_mode.Delay_ms(100)

    ret,Error_info = LED_ON(SHAP_user.Power_Flag, 0xff)
    for i in range(4):      #适用一拖四 Error_info[0] 1号机 Error_info[0] 1号机
        if Error_info[i]<0:
            print('LED_ON %d NG Error = %d'%(i,Error_info[i]))

    SHAP_user.display_on = 1


# 下电时序
def Display_OFF():
    print('Display OFF')

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 1, 0)
    if ret !=0:
        print('VDD%d NG'%(1))
    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 2, 0)
    if ret !=0:
        print('VDD%d NG'%(2))

    UserLvds_OFF()

    LED_OFF(SHAP_user.Power_Flag)

    SHAP_user.frame=0
    SHAP_user.display_on = 0

2.6. 按键控制程序

按键需要实时回读,实时处理.因此需要放在while循环里执行。

#按键读
while True:
    user_mode.Delay_ms(10)

    key_str = Key_Device.read_key_lift(500)

    if key_str.find('key_onoff_lift') != -1:

        if SHAP_user.display_on == 0 :
            print('KEY_ON')
            # 上电时序
            Display_ON_Trad()
            SHAP_user.display_on = 1
            frame_hold_cnt = user_mode.MeasureTimeStart_ms()
        else :
            print('KEY_OFF')
            # 下电时序
            Display_OFF()


    elif key_str.find('key_down_lift') != -1:

        if SHAP_user.auto_switch_mode == 0 and SHAP_user.display_on == 1 :
            if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
                frame_hold_cnt = user_mode.MeasureTimeStart_ms()
                print('KEY_DOWN')
                SHAP_user.frame += 1
                if  SHAP_user.frame >= SHAP_user.frame_num :
                    SHAP_user.frame = 0

                SwitchFrame(SHAP_user.frame)

    elif key_str.find('key_up_lift') != -1:
        print('KEY_UP')
        if SHAP_user.auto_switch_mode == 0 and SHAP_user.display_on == 1 :
            if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
                frame_hold_cnt = user_mode.MeasureTimeStart_ms()
                print('KEY_UP')
                if SHAP_user.frame == 0 :
                    SHAP_user.frame = SHAP_user.frame_num - 1
                else :
                    SHAP_user.frame -= 1
                SwitchFrame(SHAP_user.frame)

    elif key_str.find('key_enter_lift') != -1:
        print('KEY_enter')


    elif key_str.find('key_add_lift') != -1:
        print('KEY5_add')
        SHAP_user.auto_switch_mode = 1

    elif key_str.find('key_sub_lift') != -1:
        print('KEY6_sub')
        SHAP_user.auto_switch_mode = 0

    elif key_str.find('key_spare_lift') != -1:
        print('key_spare_lift')

    if SHAP_user.auto_switch_mode == 1 and SHAP_user.display_on == 1 :
        if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
            frame_hold_cnt = user_mode.MeasureTimeStart_ms()
            if SHAP_user.frame < (SHAP_user.frame_num - 1) :
                SHAP_user.frame += 1
            else :
                SHAP_user.frame = 0
            SwitchFrame(SHAP_user.frame)

2.7. 整体点屏示例

from sharp_img import image
from sharp_user import Pin_Device,user_mode,Key_Device
from sharp_display_lvds import *
from sharp_app_mod import Set_Board_All

IT_ON_OFF = Pin_Device.LCD__IO_5 #外部IO口宏
IT_MTP = Pin_Device.LCD__IO_6    #外部IO口宏

def ON_OFF_IRQHandler(index,pin):
    print('ON_OFF index = %x,pin = %x'%(index,pin))
    #===============点亮的情况下才执行中断=======================================================
    if pin == Pin_Device.LCD__IO_5 and SHAP_user.display_on == 1:
        user_mode.Delay_ms(10)
        print('IO_55 ONOFF')

def MTP_IRQHandler(index,pin):
    print('MTP index = %x,pin = %x'%(index,pin))
    #===============点亮的情况下才执行中断=======================================================
    if pin ==Pin_Device.LCD__IO_6 and SHAP_user.display_on == 1:
        user_mode.Delay_ms(10)
        print('IO_66 MTP')

class User_Fun():
    Power_Flag = 0
    Backlight_Flag = 0
    frame = 0
    frame_num = 0
    display_on = 0
    auto_switch_mode = 0  # 画面模式  =0 手动  =1 自动
    frame_hold_ms = []  # 画面保持时间 ,在LoadFrame() 函数中赋值

    My_Board = Set_Board_All()                                          # 主控板对象 里面包含电源板 背光板 GPU板

    My_IT_ON_OFF_Pin = Pin_Device(IT_ON_OFF,Pin_Device.IN)  #第一个参数是定义好的外部IO口宏,第二个参数是IO口输入输出模式
    My_IT_MTP_Pin = Pin_Device(IT_MTP,Pin_Device.IN)        #Pin_Device.IN 和 Pin_Device.OUT 就是配置输入或者输出模式

def parameter_settings():
    # ''' 点屏参数配置 '''
    LVDS_struct = lvds_panel_par()

    LVDS_struct.autoPanelFre = 60  # 屏幕刷新率 ,此值设置之后,pclk设置无效
    LVDS_struct.pclk = 69  # PCLK时钟

    LVDS_struct.h_active = 1920  # 水平的有效像素
    LVDS_struct.h_back_porch = 60  # 水平的后沿
    LVDS_struct.h_front_porch = 90  # 水平的前沿
    LVDS_struct.h_pulse_width = 30  # 水平的脉冲

    LVDS_struct.v_active = 1080  # 垂直的有效像素
    LVDS_struct.v_back_porch = 8  # 垂直的后沿
    LVDS_struct.v_front_porch = 8  # 垂直的前沿
    LVDS_struct.v_pulse_width = 5  # 垂直的脉冲

    LVDS_struct.display_mode = LVDS_2Port_Display  # 显示模式
    LVDS_struct.bit_mode = LVDS_24_BIT  # 数据位数
    LVDS_struct.dat_format = LVDS_VESA  # 数据格式
    LVDS_struct.rgb_dir = LVDS_DIR_RGB  # RGB方向

    LVDS_struct.pclk_edge = LVDS_RISING_EDGE  # pclk锁存边缘
    LVDS_struct.h_active_edge = LVDS_LOW_ACTIVE  # h脉冲有效电平
    LVDS_struct.v_active_edge = LVDS_LOW_ACTIVE  # v脉冲有效电平
    LVDS_struct.de_active_edge = LVDS_HIGH_ACTIVE  # de脉冲有效电平

    SHARP_Display_Lvds_Init(LVDS_struct.autoPanelFre, LVDS_struct)

    SHAP_user.My_IT_ON_OFF_Pin.IO_irq(Pin_Device.EDGE_UP,ON_OFF_IRQHandler)
    SHAP_user.My_IT_MTP_Pin.IO_irq(Pin_Device.EDGE_UP,MTP_IRQHandler)


# 加载图片
def LoadFrame():
    print("Load image..")
    image.Img_SDCard_BMP('/sdcard/Full Red_compresed.bmp',0)
    image.Img_SDCard_BMP('/sdcard/Full Green_compresed.bmp',0)
    image.Img_SDCard_BMP('/sdcard/Full Blue_compresed.bmp',0)
    image.Img_Full(255,0,0)
    image.Img_Full(0,255,0)
    image.Img_Full(0,0,255)
    print("Load image OK")

'''
函数名:FrameBefor
描述  :切图之前要做的事情 (可以用来切换normal,idle模式等等)

'''
def FrameBefor(frame):
    pass


'''
函数名:FrameAfter
描述  :切图之后要做的事情 (可以用来测试电压电流什么的)

'''
def FrameAfter(frame):
    pass


def SwitchFrame(frame):
    # 切图之前
    # FrameBefor(frame)

    SHAP_user.My_Board.GPU_DisplayFrame(frame)  # 切图

    # 切图之后
    # FrameAfter(frame)


def run():

    ############硬件初始化##############
    SHAP_user.My_Board.IOVOL_Set(3.3)
    user_mode.DEBUG("LVDS hardware init\n")

    # ''' 屏幕参数配置 '''
    parameter_settings()
    # ''' 加载图片 '''
    LoadFrame()

    while True:
        try:
            run_while()

        except ITException as e:    #IO口中断异常处理  不可修改
            user_mode.DEBUG("ITException ERR\r")

        except Exception as e:      #其他异常处理   不可修改

            traceback = user_mode.traceback_exception(e)    #获取异常信息
            user_mode.DEBUG(traceback)                      #显示盒打印异常信息
            ##异常里执行的功能  用户可自行更改
            user_mode.DEBUG("Exception ERR\r")

def run_while():

    SHAP_user.My_Board.MONITOR_SetBee(1)
    user_mode.Delay_ms(500)
    SHAP_user.My_Board.MONITOR_SetBee(0)

    #按键读
    while True:
        user_mode.Delay_ms(10)

        key_str = Key_Device.read_key_lift(500)

        if key_str.find('key_onoff_lift') != -1:

            if SHAP_user.display_on == 0 :
                print('KEY_ON')
                # 上电时序
                Display_ON_Trad()
                SHAP_user.display_on = 1
                frame_hold_cnt = user_mode.MeasureTimeStart_ms()
            else :
                print('KEY_OFF')
                # 下电时序
                Display_OFF()


        elif key_str.find('key_down_lift') != -1:

            if SHAP_user.auto_switch_mode == 0 and SHAP_user.display_on == 1 :
                if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
                    frame_hold_cnt = user_mode.MeasureTimeStart_ms()
                    print('KEY_DOWN')
                    SHAP_user.frame += 1
                    if  SHAP_user.frame >= SHAP_user.frame_num :
                        SHAP_user.frame = 0

                    SwitchFrame(SHAP_user.frame)

        elif key_str.find('key_up_lift') != -1:
            print('KEY_UP')
            if SHAP_user.auto_switch_mode == 0 and SHAP_user.display_on == 1 :
                if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
                    frame_hold_cnt = user_mode.MeasureTimeStart_ms()
                    print('KEY_UP')
                    if SHAP_user.frame == 0 :
                        SHAP_user.frame = SHAP_user.frame_num - 1
                    else :
                        SHAP_user.frame -= 1
                    SwitchFrame(SHAP_user.frame)

        elif key_str.find('key_enter_lift') != -1:
            print('KEY_enter')


        elif key_str.find('key_add_lift') != -1:
            print('KEY5_add')
            SHAP_user.auto_switch_mode = 1

        elif key_str.find('key_sub_lift') != -1:
            print('KEY6_sub')
            SHAP_user.auto_switch_mode = 0

        elif key_str.find('key_spare_lift') != -1:
            print('key_spare_lift')

        if SHAP_user.auto_switch_mode == 1 and SHAP_user.display_on == 1 :
            if user_mode.GetMeasureTime_ms(frame_hold_cnt) >= SHAP_user.frame_hold_ms[SHAP_user.frame] :
                frame_hold_cnt = user_mode.MeasureTimeStart_ms()
                if SHAP_user.frame < (SHAP_user.frame_num - 1) :
                    SHAP_user.frame += 1
                else :
                    SHAP_user.frame = 0
                SwitchFrame(SHAP_user.frame)

# 传统上电模式
def Display_ON_Trad():

    print('Display ON')

    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,1,2000)
    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,2,2000)

    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,3,2000)
    SHAP_user.My_Board.POWER_SetVDDLimit(SHAP_user.Power_Flag,4,2000)

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 1, 3.3)
    if ret !=0:
        print('VDD%d NG'%(1))

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 2, 12)
    if ret !=0:
        print('VDD%d NG'%(2))

    user_mode.Delay_ms(5)
    SwitchFrame(SHAP_user.frame)

    UserLvds_ON()
    user_mode.Delay_ms(100)

    for i in range(1,13):
        SHAP_user.My_Board.LED_SetI(SHAP_user.Power_Flag, i, 10)

    user_mode.Delay_ms(100)

    ret,Error_info = LED_ON(SHAP_user.Power_Flag, 0xff)
    for i in range(4):      #适用一拖四 Error_info[0] 1号机 Error_info[0] 1号机
        if Error_info[i]<0:
            print('LED_ON %d NG Error = %d'%(i,Error_info[i]))

    SHAP_user.display_on = 1


# 下电时序
def Display_OFF():
    print('Display OFF')

    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 1, 0)
    if ret !=0:
        print('VDD%d NG'%(1))
    ret=SHAP_user.My_Board.POWER_SetVDD(SHAP_user.Power_Flag, 2, 0)
    if ret !=0:
        print('VDD%d NG'%(2))

    UserLvds_OFF()

    LED_OFF(SHAP_user.Power_Flag)

    SHAP_user.frame=0
    SHAP_user.display_on = 0



# ''' 初始化配置 '''
SHAP_user=User_Fun()
if __name__ == '__main__':  #主程序入口
    user_mode.DEBUG("Enter Python OK !")
    run()