前期准备
这快2.8寸TFT彩屏是从淘宝买的,分辨率320*240 驱动是ILI9341 接口是SPI,网上找到了32上跑的驱动代码,但是并没有找到ESP的驱动代码,准备自己写一个ESP32使用的ILI9341驱动和一些简单的画图接口
屏幕初始化
这个比较容易实现,现在已经有基于stm32的屏幕驱动,可以直接将C代码用python语法重写一遍即可
#——————————–初始化即底层代码(部分)——————————————–#
def init(self, spi, cs, dc, rst, w, h, r):
self.spi = spi
self.cs = cs
self.dc = dc
self.rst = rst
self.init_width = w
self.init_height = h
self.width = w
self.height = h
self.rotation = r
self.cs.init(self.cs.OUT, value=1)
self.dc.init(self.dc.OUT, value=0)
self.rst.init(self.rst.OUT, value=0)
self.reset()
self.init()
……………………………………….
def reset(self):
self.rst(0)
time.sleep_ms(50)
self.rst(1)
time.sleep_ms(50)
#写数据
def data(self, data):
self.dc(1)
self.cs(0)
self.spi.write(data)
self.cs(1)
#写命令
def command(self, command):
self.dc(0)
self.cs(0)
self.spi.write(bytearray([command]))
self.cs(1)
#写入块
def writeblock(self, x0, y0, x1, y1):
self.command(CASET)# 列地址设置
self.data(struct.pack(“>HH”, x0, x1))
self.command(PASET)# 页地址设置
self.data(struct.pack(“>HH”, y0, y1))
self.command(RAMWR)# 内存写入
#读取块,返回
def readblock(self, x0, y0, x1, y1):
self.command(CASET)# 列地址设置
self.data(struct.pack(“>HH”, x0, x1))
self.command(PASET)# 页地址设置
self.data(struct.pack(“>HH”, y0, y1))
self.command(RAMRD)# 内存读出
data = self.spi.read((x1 - x0 + 1) * (y1 - y0 + 1) * 3)
return data
#———————————————————————————————#
添加基本绘图接口
利用micro python固件提供的FrameBuffer类,重写该类方法,可以大大节省时间,在ESP内存中创建一个缓冲区,将要写入显存的数据先写入FrameBuffer,最终在show方法中将缓冲区数据通过SPI写入显存
注意!这块2.8寸屏的分辨率为320240,而且数据格式为RGB565,即一个像素点需要16个bit,共需要320240*16bit空间,对于ESP32肯定不能一次性写入显存(内存不足),应该多创建几次FrameBuffer分批写入比较合理
1.画点
def pixel(self,x,y,c = 0xffff):
self.getbuffer(x,y,1,1)
self.fb.pixel(0,0,c)
2.画线
def line(self,x1,y1,x2,y2,c = 0xffff):
w = x2-x1
h = y2-y1
self.getbuffer(x1,y1,w,h)
self.fb.line(0,0,w,h,c)
self.show()
3.画矩形
def rect(self,x,y,w,h,c = 0xffff):
self.getbuffer(x,y,w,h)
self.fb.rect(0,0,w,h,c)
self.show()
4.填充、擦除、斜线等绘图接口
详见个人github
添加高级绘图接口
1.显示图片
#---------------------------------实现图片(数组)显示由SD卡或网络传输--------------------------------#
#x,y图片起始显示位置
#pic_w,pic_h图片宽高
#图片文件的路径
def bitmap(self,x,y,pic_w,pic_h,file_name):
lines = 6
block = pic_w * lines * 2
nums = (pic_w * pic_h * 2) // block
with open(file_name,'rb') as fio:
for v in range(nums):
self.getbuffer(x ,y+v*lines, pic_w ,lines)
self.buf = fio.read(block)
self.show()
#实现网络传输图片
def bitmap_net(self,sock):
lines = 6
x = int(sock.recv(10))
sock.send(b's')
y = int(sock.recv(10))
sock.send(b's')
pic_w = int(sock.recv(10))
sock.send(b's')
pic_h = int(sock.recv(10))
sock.send(b's')
block = pic_w * lines * 2
nums = (pic_w * pic_h * 2) // block
for v in range(nums):
self.getbuffer(x ,y+v*lines, pic_w ,lines)
self.buf = sock.recv(block)
self.show()
time.sleep_ms(100)#延时等待刷新
#---------------------------------------------------------------------------------------------#
2.显示字符
#--------------------------------字符输入自动换行支持所有字符的输入--------------------------------#
#功能:传入黑白字库文件,支持自定义字体颜色,速度较慢
def print(self,str,xstart,ystart,fg = 0xffff,bg = 0x0000,font_path="/sd/utf16.zk",size=16):
def hex2bin(g):#将传入的颜色转为字节串
s = hex(g).replace("0x","")
while len(s)<4:s = '0' + s#补全为四位
return bytearray([int(s[0:2],16),int(s[2:4],16)])
_fg = hex2bin(fg) #前景色
_bg = hex2bin(bg) #背景色
pos_y = ystart
charbytes = int((size**2)/8)#一个字符的所占的字节数,是跳转字库指针的最小单位
n = -1#字符计数器,表示当前显示的字符
max = int(240/size)-1
with open(font_path,'rb') as f:#打开字库
for c in str:#分割字符串为字符
n = n + 1
v = 0#写入buf的计数器,每显示一个字符清零
f.seek(ord(c)*charbytes)#跳转到字符c的位置
chr_num = f.read(charbytes)#读取字符c,返回此字符对应的点阵数据
pos_x = xstart + size * n #y的位置为起始值加上n个字符size
if pos_x >= 240 - 1.1 * size:#如果当前超出行
pos_y = pos_y + size#y位置向下偏移一个size<换行>
pos_x = xstart
n = -1
self.getbuffer(pos_x,pos_y,size,size)#每次显示一个字符
for byte in chr_num:#分割一个字符点阵数据为字节,并将整个字符入self.buf等待显示
x = bin(byte).replace('0b','')
while len(x)<8:#补全为8位
x = '0' + x
for r in x:#将黑白字符转为彩色字符放在self.buf中
if r == '0':
self.buf[0+2*v:2+2*v] = _bg
else:
self.buf[0+2*v:2+2*v] = _fg
v = v + 1
self.show()#显示一个字符
#功能:直接传入转化好的RGB565字库,不可改颜色,但速度更快
def printf(self,str,xstart,ystart,font_path="/sd/utf16.fzk",size=16):
charbytes = int((size**2)*2)#一个字符的所占的字节数,是跳转字库指针的最小单位
n = -1
pos_y = ystart
max = int(240/size)-1
with open(font_path,'rb') as f:#打开字库
for c in str:#分割字符串为字符
n = n + 1
pos_x = xstart + size * n #y的位置为起始值加上n个字符size
if pos_x >= 240 - 1.1 * size:#如果当前y位置超出屏幕
pos_y = pos_y + size#x位置向下偏移一个size<换行>
pos_x = xstart
n = -1
self.getbuffer(pos_x,pos_y,size,size)#每次显示一个字符
f.seek(ord(c)*charbytes)#跳转到字符c的位置
self.buf = f.read(charbytes)#读取字符c,返回此字符对应的点阵数据
self.show()#显示一个字符
#---------------------------------------------------------------------------------------------#
字库文件通过取模软件生成,并将其格式处理为RGB65 存于内存卡中
实现代码如下:
1 | old = r'C:\Users\liu\Desktop\22.DZK' |