代码拉取完成,页面将自动刷新
from time import sleep_ms
from struct import pack
from machine import Pin,PWM
from micropython import const
import framebuf
#定义RGB565颜色常量
RED,GREEN,BLUE,WHITE = const(248),const(57351),const(7936),const(65535)
CYAN,YELLOW,PURPLE,GREY = const(65287),const(57599),const(8184),const(4228)
#定义像素格式
RGB565=framebuf.RGB565
GS8=framebuf.GS8
#定义显示模式常量
PART,NORMAL,SCROLL,IDLE=0x12,0x13,0X33,0x39
def clamp( aVal:int, aMin:int, aMax:int)->int:
'''把aVal限定在区间[aMin,aMax]之内'''
return max(aMin, min(aMax, aVal))
def rgb565(R:int, G:int, B:int)->int:
'''将给定的R、G、B三基色转换成小端模式的RGB565颜色值'''
c=(((R&0xF8)<<8) | ((G&0xFC)<<3) | (B>>3)).to_bytes(2,'little')
return (c[0]<<8) + c[1]
class ST7735S(framebuf.FrameBuffer):
#构造函数-----------------------------------------------------------------------
def __init__(self,spi,*,dc,rst,cs,bl=None, width=128, height=160):
'''参数说明:
spi: SPI或SoftSPI对象
rst: LCD重置
dc: LCD数据/命令选择,低电平0-命令,高电平1-数据
cs: 片选,0有效
bl: 背光,0关闭,1开启,此处用pwm控制亮度
width/height: LCD屏宽/高-像素数。若宽>高,则为横屏;反之为竖屏
'''
self.spi = spi
self.dc=Pin(dc,Pin.OUT,value=0)
self.rst=Pin(rst,Pin.OUT,value=1)
self.cs=Pin(cs,Pin.OUT,value=1)
self.bl=None if bl is None else PWM(Pin(bl), freq=1000, duty_u16=32768)
self.width = width
self.height = height
self.buffer = bytearray(width*height*2)
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
#硬件重置,rst引脚低电平重置,高电平正常工作,间隔5ms
self.rst(1)
sleep_ms(5)
self.rst(0)
sleep_ms(5)
self.rst(1)
sleep_ms(5)
self._write(0x11) #0x11命令:sleep out,默认sleep in
sleep_ms(120) #等待电源电压和时钟电路的时序稳定
if width>height:
self._write(0x36, b'\x60') #0x36命令:当宽>高时设为横屏(60或A0),默认0x00
self._write(0x3A, b'\x55') #0x3A命令:设置16位颜色模式RGB565,默认RGB666
self._write(0xb4,b'\x00') #0xB4命令:设置液晶面板极性反转模式为点反转,默认0x07。
self._write(0x29, None) #0x29命令:开启显示,默认关闭显示
sleep_ms(50)
self.clear() #用黑色填充缓存
self.backlight(128) #开启背光50%
def deinit(self):
if self.bl is not None: self.bl.deinit() #关闭PWM输出
#功能函数定义-----------------------------------------------------------------------
def _write(self, command:int, data:bytes=None):
'''向IC发送命令或数据'''
self.cs.off() # 开启片选信号
self.dc.off() # 低电平写命令
self.spi.write(bytearray([command]))
self.cs.on() # 释放片选信号
if data is not None:
self.cs.off() # 开启片选信号
self.dc.on() # 高电平写参数
self.spi.write(data)
self.cs.on() # 释放片选信号
def clear(self,c:int=0):
'''用c颜色填充缓存和显存,默认黑色'''
self.fill(c) #调用FrameBuffer.fill()
self.show()
def backlight(self, duty:int):
'''背光亮度调节,范围:0-255'''
if self.bl is not None:
self.bl.duty_u16(duty%256*257)
def sleep(self):
'''显示屏进入睡眠'''
if self.bl is not None: self.backlight(0)
self._write(0x28) #28命令:关闭显示
self._write(0x10) #10命令:sleep in
def wakeup(self):
'''唤醒显示屏'''
self._write(0x11) #11命令:sleep out
sleep_ms(120) #等待120ms
self._write(0x29) #29命令:开启显示
if self.bl is not None: self.backlight(1)
def rotate(self,angle:int):
'''顺时针旋转屏幕0、90、180、270'''
a=b'\x00\x60\xC0\xA0'
angle=angle//90%4
if (angle%2==0 and self.height<self.width) or (angle%2==1 and self.height>self.width):
self.width,self.height=self.height,self.width
#重新初始化FrameBuffer,保持缓存形状与屏幕显示模式一致
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
self._write(0x36, pack('>B',a[angle]))
def setWindow(self,xs:int,ys:int,xe:int,ye:int)->None:
'''设置数据发送或图像绘制的目标窗口,0≤xs,xe≤width-1, 0≤ys,ye≤height-1,'''
xs%=self.width
xe%=self.width
ys%=self.height
ye%=self.height
if ye<ys or xe<xs:return
self._write(0x2A,pack(">HH", xs, xe)) #0x2a命令:设置列起止地址
self._write(0x2B,pack(">HH", ys, ye)) #0x2b命令:设置行起止地址
def setDisMode(self,mode:int,*p):
'''设置部分\正常\滚动\空闲显示模式
mode: PART,NORMAL,SCROLL,IDLE
p[0]: 部分区域开始地址或滚动顶部固定区
p[1]: 部分区域结束地址或中间滚动区
p[2]: 滚动底部固定区'''
if mode==SCROLL:
self._write(mode,pack('>HHH',p[0],p[1],p[2])) #设置滚动区域
else:
self._write(mode)
if mode==PART:
amax=max(self.width,self.height)
p0,p1=clamp(p[0],0,amax-1),clamp(p[1],0,amax-1)
self._write(0x30,pack(">HH", p0,p1))#设置部分显示区域
def setScrollStart(self,ys:int):
'''设置滚动的开始线'''
self._write(0x37,pack('>H',ys))
def show(self):
'''全屏显示,把FrameBuffer的全部发送到屏幕'''
self.setWindow(0,0,self.width-1,self.height-1)
self._write(0x2c,self.buffer) #0x2c命令:显存写入命令
def showVPart(self,ys:int,ye:int):
'''刷新显示 垂直部分区域,实现对垂直矩形区域的局部刷新,矩形左上角坐标为[0,ys],右下角为[width-1,ye]'''
self.setWindow(0,ys,self.width-1,ye)
self._write(0x2c,memoryview(self.buffer)[(ys*self.width)*2:(ye*self.width+1)*2])
def showImage(self,xs:int,ys:int,xe:int,ye:int,img_rgb565:bytes):
'''把bytes或bytearray类型img直接发送到屏幕指定窗口显示
适合显示相机拍摄的图片,分辨率上图片需小于等于屏幕,且为RGB565格式'''
self.setWindow(xs,ys,xe,ye)
self._write(0x2c,img_rgb565)
def bufToBmp(self,bmpfile:str):
'''把framebuf缓存上的图像保存为RGB565格式的bmp文件'''
#the size of bmp
size=70+self.width*self.height*2
with open(bmpfile, 'wb') as f:
#写入文件头
f.write(pack('<HIII',0x4D42,size,0,70))
#写入信息头
f.write(pack('<IIiHHIIQQ',40,self.width,-self.height,1,16,3,size-70,0,0))
#写入调试板,RGB565掩码
f.write(pack('<IIII',0xF800,0x7E0,0x1F,0))
#写入数据,每行为4的倍数
for row in range(self.height):
for col in range(self.width):
p=(row*self.width+col)*2
f.write(pack('<BB',self.buffer[p+1],self.buffer[p]))
print('has saved to bmp!')
#绘图函数定义(在FrameBuffer上绘图)----------------------------------------------------------
def drawText(self,text:str,x:int,y:int,fontDB,c:int=WHITE,bc:int=0,alpha:bool=True):
'''在framebuf上,从左上角(x,y)处不换行绘制汉字或因为字符,需要调用show()显示。
fontDB:模块gbk中定义的获取字模数据的对象,gbk.font16x16()
c:字体颜色
bc: 背景色
alpha:背景是否透明'''
#定义汉字RGB565格式的背景、前景色调色板
palette = framebuf.FrameBuffer(bytearray([bc&0xFF,(bc>>8)&0xFF,c&0xFF,(c>>8)&0xFF]),2,1,framebuf.RGB565)
for ch in text:
w,h,fbm=fontDB.get(ch) #取得字模的宽、高、位图信息bytearray
if w==0 or x+w>self.width or y+h>self.height: break #超出屏幕不绘制
fbuf=framebuf.FrameBuffer(fbm,w,h,framebuf.MONO_HLSB)#定义字体的framebuffer
self.blit(fbuf,x,y,bc if alpha else -1,palette) #在framebuf上绘制汉字
x+=w
def drawImage(self,imgw:int,imgh:int,img:bytes,format:int=RGB565,x:int=0,y:int=0):
'''在framebuf上,从(x,y)处绘制字节数据组成的图像,每个像素为1字节的灰度值或2个字节rgb565,
超出屏幕范围的图像被忽略'''
fbuf=framebuf.FrameBuffer(bytearray(img),imgw,imgh,format) #定义img对应的framebuf
if format==GS8:
pbuf=bytearray(256*2)
for i in range(256):
t=i>>3 #灰度值除8,变成5位数
pbuf[i*2],pbuf[i*2+1]=((t<<3)|(t>>3)),((t<<5)|t) #灰度转为rgb565格式
palette = framebuf.FrameBuffer(pbuf,256,1,framebuf.RGB565) #定义灰度值的调色板
self.blit(fbuf,x,y,-1,palette) #在framebuf上绘制img
elif format==RGB565:
self.blit(fbuf,x,y)
else:
print('Only GRAYSCALE/GS8 and RGB565 are supported!')
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。