DDZZ669 发表于 2022-11-27 15:50

玩转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 &mdash; 帧缓冲区操作</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">&nbsp;</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:
&nbsp; &nbsp;#LCD
&nbsp; &nbsp;LCD = mylcd.LCD_GC9A01A()
&nbsp; &nbsp;LCD.set_bl_pwm(65535)
&nbsp; &nbsp;
&nbsp; &nbsp;def __init__(self):
&nbsp; &nbsp; &nbsp; &nbsp;print(&#39;%s __init__&#39; % self.__class__.__name__)
&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;def __del__(self):
&nbsp; &nbsp; &nbsp; &nbsp;print(&#39;%s __del__&#39; % self.__class__.__name__)
&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;def draw_title(self):
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.fill_rect(0,0,240,35,self.LCD.red)
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.text(&quot;RP2040-LCD-1.28&quot;,60,20,self.LCD.white)
&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;def draw_pixel_test(self, t = 2):
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.fill(self.LCD.white)
&nbsp; &nbsp; &nbsp; &nbsp;self.draw_title()
&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;for i in range(1, 10):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for x in range(20, 220, i):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.LCD.pixel(x, 80 + (i-1)*10, self.LCD.green)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;time.sleep(t)
&nbsp; &nbsp; &nbsp; &nbsp;
#主函数
if __name__==&#39;__main__&#39;:
&nbsp; &nbsp;DrawTest = LCDDraw()
&nbsp; &nbsp;while(True):
&nbsp; &nbsp; &nbsp; &nbsp;DrawTest.draw_pixel_test()
&nbsp; &nbsp; &nbsp; &nbsp;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):
&nbsp; &nbsp;self.LCD.fill(self.LCD.white)
&nbsp; &nbsp;self.draw_title()
&nbsp; &nbsp;
&nbsp; &nbsp;self.LCD.hline(50, 80, 100, self.LCD.red)
&nbsp; &nbsp;self.LCD.vline(50, 80, 100, self.LCD.blue)
&nbsp; &nbsp;self.LCD.line(50, 80, 80, 100, self.LCD.green)
&nbsp; &nbsp;
&nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp;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):
&nbsp; &nbsp;self.LCD.fill(self.LCD.white)
&nbsp; &nbsp;self.draw_title()
&nbsp; &nbsp;
&nbsp; &nbsp;for y in range(35, 205+1, 10):
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.hline(35, y, 170, self.LCD.red)
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp; &nbsp; &nbsp;time.sleep(0.1)
&nbsp; &nbsp;for x in range(35, 205+1, 10):
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.vline(x, 35, 170, self.LCD.blue)
&nbsp; &nbsp; &nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp; &nbsp; &nbsp;time.sleep(0.1)
&nbsp; &nbsp;
&nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp;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):
&nbsp; &nbsp;self.LCD.fill(self.LCD.white)
&nbsp; &nbsp;self.draw_title()
&nbsp; &nbsp;
&nbsp; &nbsp;self.LCD.rect(100, 100, 30, 10, self.LCD.blue)
&nbsp; &nbsp;self.LCD.fill_rect(100, 150, 30, 10, self.LCD.green)
&nbsp; &nbsp;
&nbsp; &nbsp;self.LCD.show()
&nbsp; &nbsp;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 = &quot;%02d:%02d&quot; % (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]
查看完整版本: 玩转RP2040之LCD绘制基本形状测试