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 开关显示
注意
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”表示加载完成。
注意
目前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 代表VDD1v:要输出的电压值,单位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()