玩转RP2040之LCD绘制基本形状测试
<div class='showpostmsg'><p cid="n0" mdtype="paragraph">上篇文章:<a href="https://bbs.eeworld.com.cn/thread-1226513-1-1.html" target="_blank"> 玩转RP2040之Python开发环境搭建</a>,进行了RP2040的Python软件开发环境搭建与测试,本篇进行程序编写,测试LCD的基础显示功能。</p><p cid="n2" mdtype="paragraph">RP2040用到Python环境,准确的讲是MicroPython,它是Python 3编程语言的精简高效实现 ,包括Python标准库的一小部分,并且经过优化,可在微控制器和受限环境中运行。</p>
<h1 cid="n3" mdtype="heading">1 MicroPython画图介绍</h1>
<p cid="n4" mdtype="paragraph">MicroPython相比较Python,有一些专有的库,比如本篇要介绍的framebuf库,就是专有的库,可以看下MicroPython官方文档:<a href="https://docs.micropython.org/en/latest/library/framebuf.html">https://docs.micropython.org/en/latest/library/framebuf.html</a></p>
<p cid="n5" mdtype="paragraph"></p>
<p cid="n6" mdtype="paragraph">如果英文文档看着不习惯,国内有一些翻译文档,比如:</p>
<ul cid="n7" data-mark="-" mdtype="list">
<li cid="n8" mdtype="list_item">
<p cid="n9" mdtype="paragraph">01studio:<a href="https://docs.01studio.cc/library/framebuf.html" spellcheck="false">class FrameBuffer</a></p>
</li>
<li cid="n10" mdtype="list_item">
<p cid="n11" mdtype="paragraph">星瞳科技:<a href="https://docs.singtown.com/micropython/zh/latest/openmvcam/library/framebuf.html" spellcheck="false">framebuf — 帧缓冲区操作</a></p>
</li>
</ul>
<h1 cid="n12" mdtype="heading">2 FrameBuffer绘制原始形状</h1>
<p cid="n13" mdtype="paragraph">在介绍FrameBuffer画图之前,先来看下绘图坐标系,微雪RP2040这块板子屏幕的分辨率是240x240,但这个屏幕是圆形的,因此圆形意外的位置是无法显示的,在绘制图形时,需要将绘图位置落在圆形的区域内。</p>
<p cid="n14" mdtype="paragraph">圆形屏幕的有效显示范围如下图中的黄色亮部所示:</p>
<p cid="n15" mdtype="paragraph"></p>
<p cid="n16" mdtype="paragraph"> </p>
<h2 cid="n17" mdtype="heading">2.1 指定颜色填满整个帧缓冲区</h2>
<pre style="background:#555; padding:10px; color:#ddd !important;">
#使用指定颜色填满整个帧缓冲区
FrameBuffer.fill(c)</pre>
<h2 cid="n19" mdtype="heading">2.2 画单个像素点</h2>
<pre style="background:#555; padding:10px; color:#ddd !important;">
#若未给定c,则获取指定像素的色值。若给定c,将指定像素设置到给定颜色
FrameBuffer.pixel(x, y[, c])</pre>
<p cid="n21" mdtype="paragraph">测试程序:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
from machine import Pin,I2C,SPI,PWM,ADC
import mylcd
import time
class LCDDraw:
#LCD
LCD = mylcd.LCD_GC9A01A()
LCD.set_bl_pwm(65535)
def __init__(self):
print('%s __init__' % self.__class__.__name__)
def __del__(self):
print('%s __del__' % self.__class__.__name__)
def draw_title(self):
self.LCD.fill_rect(0,0,240,35,self.LCD.red)
self.LCD.text("RP2040-LCD-1.28",60,20,self.LCD.white)
def draw_pixel_test(self, t = 2):
self.LCD.fill(self.LCD.white)
self.draw_title()
for i in range(1, 10):
for x in range(20, 220, i):
self.LCD.pixel(x, 80 + (i-1)*10, self.LCD.green)
self.LCD.show()
self.LCD.show()
time.sleep(t)
#主函数
if __name__=='__main__':
DrawTest = LCDDraw()
while(True):
DrawTest.draw_pixel_test()
time.sleep(1000)</pre>
<p cid="n23" mdtype="paragraph">实测结果:</p>
<p cid="n24" mdtype="paragraph"></p>
<h2 cid="n25" mdtype="heading">2.3 画直线</h2>
<pre style="background:#555; padding:10px; color:#ddd !important;">
#画水平直线
FrameBuffer.hline(x, y, w, c)
#画竖直直线
FrameBuffer.vline(x, y, h, c)
#画两点间的直线
FrameBuffer.line(x1, y1, x2, y2, c)</pre>
<p cid="n27" mdtype="paragraph">测试程序1:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
def draw_line_test(self, t = 2):
self.LCD.fill(self.LCD.white)
self.draw_title()
self.LCD.hline(50, 80, 100, self.LCD.red)
self.LCD.vline(50, 80, 100, self.LCD.blue)
self.LCD.line(50, 80, 80, 100, self.LCD.green)
self.LCD.show()
time.sleep(t)</pre>
<p cid="n29" mdtype="paragraph">实测结果:</p>
<p cid="n30" mdtype="paragraph"></p>
<p cid="n31" mdtype="paragraph">测试程序2:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
def draw_line_test2(self, t = 2):
self.LCD.fill(self.LCD.white)
self.draw_title()
for y in range(35, 205+1, 10):
self.LCD.hline(35, y, 170, self.LCD.red)
self.LCD.show()
time.sleep(0.1)
for x in range(35, 205+1, 10):
self.LCD.vline(x, 35, 170, self.LCD.blue)
self.LCD.show()
time.sleep(0.1)
self.LCD.show()
time.sleep(t)</pre>
<p cid="n33" mdtype="paragraph">实测结果:</p>
<p cid="n33" mdtype="paragraph">动图:</p>
<p cid="n33" mdtype="paragraph"></p>
<h2 cid="n35" mdtype="heading">2.4 画矩形</h2>
<pre style="background:#555; padding:10px; color:#ddd !important;">
#画矩形
FrameBuffer.rect(x, y, w, h, c)
#填充矩形
FrameBuffer.fill_rect(x, y, w, h, c)</pre>
<p cid="n37" mdtype="paragraph">测试程序1:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
def draw_rect_test(self, t = 2):
self.LCD.fill(self.LCD.white)
self.draw_title()
self.LCD.rect(100, 100, 30, 10, self.LCD.blue)
self.LCD.fill_rect(100, 150, 30, 10, self.LCD.green)
self.LCD.show()
time.sleep(t)</pre>
<p cid="n39" mdtype="paragraph">实测结果:</p>
<p cid="n40" mdtype="paragraph"></p>
<p cid="n41" mdtype="paragraph">测试程序2:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
def draw_rect_test2(self, t = 2):
self.LCD.fill(self.LCD.white)
self.draw_title()
for i in range(1, 85, 3):
x = 120 - i
y = 120 - i
self.LCD.fill_rect(x, y, i*2, i*2, self.LCD.yellow)
time.sleep(0.1)
self.LCD.show()
self.LCD.fill(self.LCD.white)
self.draw_title()
for i in range(85, 1, -3):
x = 120 - i
y = 120 - i
self.LCD.rect(x, y, i*2, i*2, self.LCD.yellow)
time.sleep(0.1)
self.LCD.show()
self.LCD.show()
time.sleep(t)
</pre>
<p cid="n43" mdtype="paragraph">实测结果:</p>
<p cid="n43" mdtype="paragraph"></p>
<h1 cid="n44" mdtype="heading">3 FrameBuffer绘制文本与其它函数</h1>
<h2 cid="n45" mdtype="heading">3.1 绘制文本</h2>
<p cid="n46" mdtype="paragraph">使用坐标作为文本的左上角,将文本写入帧缓冲区。文本颜色可由任意参数定义,否则将保持其默认值1。所有字符都有8x8像素的尺寸,目前尚无办法改变字体。</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
FrameBuffer.text(s, x, y[, c])</pre>
<p cid="n48" mdtype="paragraph">测试程序:</p>
<pre style="background:#555; padding:10px; color:#ddd !important;">
def draw_time_test(self):
self.LCD.fill(self.LCD.white)
self.draw_title()
cnt = 0
minute = 0
second = 0
for i in range(1, 100):
cnt = cnt + 1
if cnt == 60:
minute = minute + 1
cnt = 0
second = cnt
timestr = "%02d:%02d" % (minute, second)
self.LCD.fill_rect(100, 125, 40, 8, self.LCD.white)
self.LCD.text(timestr,100,125,self.LCD.blue)
self.LCD.show()
time.sleep(1)</pre>
<p cid="n50" mdtype="paragraph">实测结果:</p>
<p cid="n51" mdtype="paragraph"></p>
<h2 cid="n52" mdtype="heading">3.2 其他类函数</h2>
<pre style="background:#555; padding:10px; color:#ddd !important;">
#使用给定向量转换帧缓冲区的内容。这可能会在帧缓冲区中留下之前颜色的覆盖区。
FrameBuffer.scroll(xstep, ystep)
#在当前帧缓冲区的顶部的给定坐标下绘制另外一个帧缓冲区。若指定key,则其应为一个颜色整数,且相应颜色被认为是透明的:所有具有该色值的像素都不会被绘制。
FrameBuffer.blit(fbuf, x, y[, key])</pre>
<p cid="n54" mdtype="paragraph">这些函数在绘制图片的时候会用到,绘制图片的功能还没研究透,下次介绍图片绘制时再详细介绍。</p>
<h2 cid="n55" mdtype="heading">3.3 一些常量</h2>
<ul cid="n56" data-mark="-" mdtype="list">
<li cid="n57" mdtype="list_item">
<p cid="n58" mdtype="paragraph"><strong>framebuf.MONO_VLSB</strong>:单色(1位)颜色模式</p>
<p cid="n59" mdtype="paragraph">此模式定义了一个映射,其中一个字节的位为垂直映射,而0位位于屏幕的最顶部。因此,每个字节占据8个垂直像素。 后续字节在连续的水平位置出现,直至到达最右侧的边缘。更多字节从最左边开始低8个像素显示。</p>
</li>
<li cid="n60" mdtype="list_item">
<p cid="n61" mdtype="paragraph"><strong>framebuf.MONO_HLSB</strong>:单色(1位)颜色模式</p>
<p cid="n62" mdtype="paragraph">此模式定义了一个映射,其中一个字节的位为水平映射。每个字节占据8个水平像素,0位位于最左边。 后续字节在连续的水平位置出现,直至到达最右侧的边缘。更多字节在下一行低1个像素显示。</p>
</li>
<li cid="n63" mdtype="list_item">
<p cid="n64" mdtype="paragraph"><strong>framebuf.MONO_HMSB</strong>:单色(1位)颜色模式</p>
<p cid="n65" mdtype="paragraph">此模式定义了一个映射,其中一个字节的位为水平映射。每个字节占据8个水平像素,而7位位于屏幕的最左边。 后续字节在连续的水平位置出现,直至到达最右侧的边缘。更多字节在下一行低1个像素显示。</p>
</li>
<li cid="n66" mdtype="list_item">
<p cid="n67" mdtype="paragraph"><strong>framebuf.RGB565</strong>:RGB565彩色(16位,5+6+5)颜色模式</p>
</li>
<li cid="n68" mdtype="list_item">
<p cid="n69" mdtype="paragraph"><strong>framebuf.GS2_HMSB</strong>:灰度(2位)颜色模式</p>
</li>
<li cid="n70" mdtype="list_item">
<p cid="n71" mdtype="paragraph"><strong>framebuf.GS4_HMSB</strong>:灰度(4位)颜色模式</p>
</li>
<li cid="n72" mdtype="list_item">
<p cid="n73" mdtype="paragraph"><strong>framebuf.GS8</strong>:灰度(8位)颜色模式</p>
</li>
</ul>
<h1 cid="n74" mdtype="heading">4 总结</h1>
<p cid="n75" mdtype="paragraph">本篇介绍了 MicroPython中使用FrameBuffer库进行基本功能的画图,包括画像素点、直线、矩形等,并在RP2040上进行了实测和演示。</p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]