找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3120|回复: 3
打印 上一主题 下一主题
收起左侧

STM32F1驱动OLED显示画图及动画特效

[复制链接]
跳转到指定楼层
楼主
ID:394949 发表于 2021-12-6 21:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 田裕中 于 2021-12-9 15:41 编辑

OLED的界面UI显示





      本文主要总结OLED显示绘图及动画特效的相关功能函数,记录自己的开发过程或作为自己的开发笔记,以便不时之需!
      本次OLED采用的SSD1306驱动,分辨率为128*32像素。项目编译环境使用KEIL5开发,由于调试发现,采用软件模拟IIC不能满足刷新帧率,故采用硬件IIC驱动。而显示功能部分不依赖于软件或者硬件IIC驱动,只需提供对应的读写IIC接口即可!

创建显示Buf,更新显存
      创建128 * 32的像素点阵大小,任何显示功能特效都只需对该点阵进行填充操作,1Byte = 8bit,4 * 8 = 32,点阵填充完毕后调用该函数即可完成刷新显示。
unsigned char OLED_GRAM[4][128];
void OLED_Refresh_Gram(void)
{
    unsigned char i,n;
    for(i=0;i<4;i++)  
    {  
        WriteCmd(0xb0+i);    //设置页地址(0~4)
        WriteCmd(0x00);      //设置显示位置—列低地址
        WriteCmd(0x10);      //设置显示位置—列高地址   
        WriteDat(OLED_GRAM[ i]);
    }

清除屏幕显示
      调用该函数后整个屏幕是黑色的,和没点亮一样!
void OLED_Clear(void)  
{  
    memset(OLED_GRAM,0,sizeof(OLED_GRAM));
    OLED_Refresh_Gram();//更新显示
}

画点填充
      在对应的坐标位置填充像素点颜色,该函数包含4个方向的显示,拓展了函数的可移植性,通过宏设置显示的方向。
#define TFT_ROT_NONE        1
#define TFT_ROT_RIGHT       0
#define TFT_ROT_LEFT        0
#define TFT_ROT_FLIP        0/*
@parameter:
           x:横坐标
           y:纵坐标
           t:0 or 1
*/
void OLED_DrawPoint(unsigned char x,unsigned char y,unsigned char t)
{
    unsigned char pos,bx,temp=0;
#if TFT_ROT_RIGHT
    if(x>31||y>127)return;//超出范围了.
    pos=x/8;
    bx=x%8;
    temp=1<<bx;
?
    if(t)
    {
        OLED_GRAM[pos][127-y]|=temp;
    }
    else
    {
        OLED_GRAM[pos][127-y]&=~temp;     
    }   
#elif TFT_ROT_LEFT
    if(x>31||y>127)return;
    pos=3-x/8;
    bx=x%8;
    temp=1<<(7-bx);
    if(t)
    {
        OLED_GRAM[pos][y]|=temp;
    }
    else
    {
        OLED_GRAM[pos][y]&=~temp;     
    }   
#elif TFT_ROT_FLIP
    if(x>127||y>31)return;
    pos=3-y/8;
    bx=y%8;
    temp=1<<(7-bx);
    if(t)
    {
        OLED_GRAM[pos][127-x]|=temp;
    }
    else
    {
        OLED_GRAM[pos][127-x]&=~temp;     
    }
#else
    if(x>127||y>31)return;//超出范围了.
    pos=y/8;
    bx=y%8;
    temp=1<<bx;
?
    if(t)
    {
        OLED_GRAM[pos][x]|=temp;
    }
    else
    {
        OLED_GRAM[pos][x]&=~temp;     
    }   
#endif
}

画任意直线
      由一点到另一点的直线!
/*
@parameter:
           x1:初始点横坐标
           y1:初始点纵坐标
           x2:终点横坐标
           y2:终点纵坐标
           color:0 or 1
*/
void OLED_DrawLine(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char color)
{
    int dx,dy,e;
    dx = x2 - x1;
    dy = y2 - y1;
   
    if(dx >= 0)
    {
        if(dy >= 0)
        {
            if(dx >= dy)
            {
                e = dy - dx/2;
                while(x1<=x2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        y1+=1;
                        e-=dx;
                    }
                    x1+=1;
                    e+=dy;
                }
            }
            else
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        x1+=1;
                        e-=dy;
                    }
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else
        {
            dy=-dy;
            if(dx>=dy)
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        y1-=1;
                        e-=dx;
                    }
                    x1+=1;
                    e+=dy;
                }
            }
            else
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        x1+=1;
                        e-=dy;
                    }
                    y1-=1;
                    e+=dx;
                }
            }
        }
    }
    else
    {
        dx=-dx;
        if(dy>=0)
        {
            if(dx>=dy)
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        y1+=1;
                        e-=dx;
                    }
                    x1-=1;
                    e+=dy;
                }
            }
            else
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        x1-=1;
                        e-=dy;
                    }
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else
        {
            dy = -dy;
            if(dx>=dy)
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        y1-=1;
                        e-=dx;
                    }
                    x1-=1;
                    e+=dy;
                }
            }
            else
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    OLED_DrawPoint(x1,y1,color);
                    if(e>0)
                    {
                        x1-=1;
                        e-=dy;
                    }
                    y1-=1;
                    e+=dx;
                }
            }
        }
    }
}

画圆
      画指定半径的圆,分为静止态和动态。
//-------------画圆函数。参数:圆心,半径,颜色----------
//        画1/8圆 然后其他7/8对称画
//          ---------------->X
//          |(0,0)   0
//          |     7     1
//          |    6       2
//          |     5     3
//       (Y)V        4
//
//      L = x^2 + y^2 - r^2
void OLED_DrawCircle(unsigned char x,unsigned char y,unsigned char r,unsigned char color,unsigned char n)
{
#if 0 //画静止的圆
    int a,b,num,i;
    a=0;
    b=r;
   
    while(2*b>a)
    {
      OLED_DrawPoint(x+a,y-b,color);//0~1
        OLED_DrawPoint(x-a,y-b,color);//0~7
        OLED_DrawPoint(x-a,y+b,color);//4~5
        OLED_DrawPoint(x+a,y+b,color);//4~3
        OLED_DrawPoint(x+b,y+a,color);//2~3
        OLED_DrawPoint(x+b,y-a,color);//2~1
        OLED_DrawPoint(x-b,y-a,color);//6~7
        OLED_DrawPoint(x-b,y+a,color);//6~5
        
        a++;
        num=(a*a+b*b)-r*r;//计算画的点离圆心的距离
        if(num>0)
        {
            b--;
            a--;
        }
        OLED_Refresh_Gram();
    }
#elif 1
    int di=0;
    int con_r=r*r;
   
    int a=0;
    int b=r;
    int bar=0;
    int lvel=0;
   
    lvel = n / 25;
    bar = (n % 25) * (r*10/25) /10;
   
    if(lvel==0)//第一象限
    {
        while(b)
        {   
            if(b<(r-bar))
            {
                OLED_Clear();
                return;
            }
            OLED_DrawPoint(x+a,y+b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
            OLED_Refresh_Gram();
        }
    }   
    else if(lvel==1)//第二象限
    {
        while(b)
        {   
            OLED_DrawPoint(x+a,y+b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            if(b<(r-bar))
            {
                OLED_Clear();
                return;
            }
            OLED_DrawPoint(x+b,y-a,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
            OLED_Refresh_Gram();
        }
    }
    else if(lvel==2)//第三象限
    {
        while(b)
        {   
            OLED_DrawPoint(x+a,y+b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            OLED_DrawPoint(x+b,y-a,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            if(b<(r-bar))
            {
                OLED_Clear();
                return;
            }
            OLED_DrawPoint(x-a,y-b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
            OLED_Refresh_Gram();
        }
    }
    else if(lvel==3)//第四象限
    {
        while(b)
        {   
            OLED_DrawPoint(x+a,y+b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            OLED_DrawPoint(x+b,y-a,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            OLED_DrawPoint(x-a,y-b,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
        }
        a=0;
        b=r;
        while(b)
        {   
            if(b<(r-bar))
            {
                OLED_Clear();
                return;
            }
            OLED_DrawPoint(x-b,y+a,color);
            a++;
            di=a*a+b*b-con_r;
            if(di>0)
            {
                b--;
                a--;
            }
            OLED_Refresh_Gram();
        }
    }
#endif
}

开机动画
      综上所述,制作开机动画。
void Boot_Animation(void)
{
    unsigned char i,num=0;
    for(i=64;i<64+20;i++)
    {
        OLED_DrawPoint(64-num,9+num,1);
        OLED_DrawPoint(64-num,32-9-num,1);  
        num++;
        OLED_Refresh_Gram();
        delay_ms(1);
    }
    OLED_DrawLine(46,4,83,4,1);
    OLED_DrawLine(83,28,46,28,1);
    OLED_Refresh_Gram();//更新显示到OLED
}

总结
      个人笔记总结,若有问题,欢迎留言、批评指正!!!
若有兴趣,欢迎关注公众号“瀚林创客”,内有资料提取链接。



qrcode_for_gh_d8d03909d746_258.jpg (27.02 KB, 下载次数: 78)

qrcode_for_gh_d8d03909d746_258.jpg

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:85865 发表于 2021-12-7 14:44 | 只看该作者
来个视频,看 看
回复

使用道具 举报

板凳
ID:394949 发表于 2021-12-9 15:35 | 只看该作者

想看哪个内容?
回复

使用道具 举报

地板
ID:983499 发表于 2021-12-13 10:30 来自手机 | 只看该作者
我主页有源码可以直接用
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表