【祖传点灯】安信可Ai-M61-32S 那就用OLED点个灯吧

[复制链接]
查看248 | 回复6 | 2024-5-15 22:58:32 | 显示全部楼层 |阅读模式

本帖最后由 CHRRR 于 2024-5-16 07:27 编辑

本帖最后由 CHRRR 于 2024-5-15 22:58 编辑

本帖最后由 CHRRR 于 2024-5-15 22:57 编辑

本帖最后由 CHRRR 于 2024-5-15 22:51 编辑

本帖最后由 CHRRR 于 2024-5-14 17:24 编辑

本帖最后由 CHRRR 于 2024-5-14 17:23 编辑

本帖最后由 CHRRR 于 2024-5-14 07:29 编辑

本帖最后由 CHRRR 于 2024-5-14 07:06 编辑

前言

五月初收到了Ai-M61-32S开发板,又白嫖朋友一个I2C OLED,就想用OLED显示点灯动画完成点灯作业

开发环境搭建

参考站内零基础搭建小安派Windows 开发环境

通过Git拉取SDK和工具链

image.png

在文件资源管理器可以看到拉取结果

image.png

接下来打开系统属性-环境变量添加Path,将M61SDK下toolchain中的gcc、make、ninja添加进环境变量,接下来保存并重启电脑,环境就配置完成了

image.png

I2C OLED

0.96寸上下的小尺寸OLED大多由SSD1306驱动。这颗驱动芯片缓存共有8页,每页128个字节,最多能够对应128*64像素(刚好是0.96寸OLED常用分辨率),支持I2C和SPI。这块屏幕是I2C协议(引脚用的少适合懒狗),作为一个常用元件网上有很多资料例程,这里贴一下中景园资料的百度云链接:中景园OLED资料 提取码8888

ada3287fb7783447ee82500f501887f0.png

通过查询Ai-M61-32S规格书,IO0和IO1可作为I2C SCL和SDA使用,这里把OLED屏幕的引脚和开发板依次接好,如图所示:

9d7bad1d2d52de6a5ca624b21bea2380.png

Aseprite像素画编辑器

做像素游戏开发和像素画的坛友应该挺熟悉这个工具。正如其名,Aseprite是一个方便使用的精灵图形编辑器。精灵图形在游戏开发中是将多个图像(更多是一个动画序列)按照坐标拼合成一个图像,使用时通过坐标变化取图,能够避免多次图像载入,是一种空间换时间的策略。

Aseprite售价20刀,但是在Github是有开源版本的,可以自己编译,将白嫖进行到底。Github链接:Aseprite Github

OK,编译完成打开应用,首先左上角 文件-新建 新建一个图形序列。这里尺寸选择和OLED屏幕分辨率相同的128x64像素,方便图形绘制和取模,颜色选择灰度(其实用到的只有黑白两色),背景选透明,点击确定就完成了设置,进入画布。

image.png

Aseprite界面类似画图,上手还是相对简单的。贴一个简单入门教程,对于OLED这种每个像素只有亮灭两种状态的屏幕来说,几分钟就能学会并制作出自己的动画序列:

关于aseprite画像素画你需要知道的一切

第一步,用工具栏里的椭圆、直线工具简单画一个灯泡的形状作为第一帧

image.png

第二步,多画两笔,得到一个动画序列

LightOn.gif

第三步,导出动画序列中的图片并依次取模,或者就像精灵图形的定义一样,将动画序列导出到一张图中,一次取模十分方便:

LightOn-Sheet.png

点灯程序

因为工作不在家,再摸到开发板已经是14号晚上了,于是在社区找到了个大佬搬运的OLED驱动程序Ai-M61-32S i2c点亮oled详细教程及踩坑记录 - 小安派S1&M61教程合集 - 物联网开发者社区-安信可论坛 - Powered by Discuz! (ai-thinker.com),在基础上照葫芦画瓢写了个播放动画帧图像的函数:

/**
  * 函    数:OLED显示GIF帧序列
  * 参    数:X 指定图像左上角的横坐标,范围:0~127
  * 参    数:Y 指定图像左上角的纵坐标,范围:0~63
  * 参    数:Width 指定图像的宽度,范围:0~128
  * 参    数:Height 指定图像的高度,范围:0~64
  * 参    数:GIF 需要显示的GIF图像名
  * 参    数:frame GIF动画帧数
  * 返 回 值:无
  * 说    明:调用此函数后,要想真正地呈现在屏幕上,还需调用更新函数
  */
void OLED_ShowGIFFrame(uint8_t X, uint8_t Y, uint8_t Width, uint8_t Height, uint8_t *GIF, const uint8_t frame)
{
    uint8_t i, j;

    /*参数检查,保证指定图像不会超出屏幕范围*/
    // if (X > 127) {return;}
    if (Y > 63) {return;}

    /*将图像所在区域清空*/
    OLED_ClearArea(X, Y, Width, Height);

    /*遍历指定图像涉及的相关页*/
    /*(Height - 1) / 8 + 1的目的是Height / 8并向上取整*/
    for (j = 0; j < (Height - 1) / 8 + 1; j ++)
    {
        /*遍历指定图像涉及的相关列*/
        for (i = 0; i < Width; i ++)
        {
            /*超出边界,则跳过显示*/
            // if (X + i > 127) {break;}
            if (Y / 8 + j > 7) {return;}

            /*显示图像在当前页的内容*/
            OLED_DisplayBuf[Y / 8 + j][X + i] |= GIF[frame* ((Height - 1) / 8 + 1) * Width + j * Width + i] << (Y % 8);

            /*超出边界,则跳过显示*/
            /*使用continue的目的是,下一页超出边界时,上一页的后续内容还需要继续显示*/
            if (Y / 8 + j + 1 > 7) {continue;}

            /*显示图像在下一页的内容*/
            OLED_DisplayBuf[Y / 8 + j + 1][X + i] |= GIF[frame* ((Height - 1) / 8 + 1) * Width + j * Width + i] >> (8 - Y % 8);
        }
    }
}

接下来make一下,按住开发板IO2不放的同时点按EN后松开进入烧录模式,烧录完成后再按一下EN复位,这时就能看到点灯结果啦:

4d4cc834748e5827dec8a3d145421f9f.png

回复

使用道具 举报

WT_0213 | 2024-5-16 08:44:42 | 显示全部楼层
这个有点厉害呀
回复 支持 反对

使用道具 举报

lazy | 2024-5-16 10:01:27 | 显示全部楼层
回复

使用道具 举报

hdydy | 2024-5-16 10:04:04 | 显示全部楼层
点赞
回复

使用道具 举报

1055173307 | 2024-5-16 15:55:57 | 显示全部楼层
强啊
回复

使用道具 举报

sansui | 昨天 17:32 | 显示全部楼层
大佬啊
回复

使用道具 举报

7788 | 昨天 17:52 | 显示全部楼层
厉害了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则