- /*
- Copyright (c) [2019] [一只程序缘 jiezhuo]
- [https://gitee.com/jiezhuonew/oledlib] is licensed under the Mulan PSL v1.
- You can use this software according to the terms and conditions of the Mulan PSL v1.
- You may obtain a copy of Mulan PSL v1 at:
- http://license.coscl.org.cn/MulanPSL
- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
- PURPOSE.
- See the Mulan PSL v1 for more details.
- ==========此函数是oledlib图形库的综合测试函数 基本上使用到了里面的所有内容==================
- 目前接线说明:
- 仅仅使用到0.96寸7引脚oled 使用SPI通信方式(具体见oled_drive.c)
- D0 = SCK -> PA4 (屏幕批次不同丝印可能不同)
- D1 = SDA -> PA5
- RES = RES -> PA6
- DC = DC -> PA7
- CS = SCS -> PA8
- 软件模块:
- oled spi驱动
- beep 蜂鸣器 提示或作为led表示运行状态
- timer3 中断1ms 可为图形库提供时间基准
- uart 可作为串口连接电脑打印调试xinxi
- delay 系统自带的时间设置与提供延时函数
- 视频演示信息:
- 单片机 --- STM32F103
- oled --- 采用4线SPI的7引脚0.96寸黑白双色oled
- 图形库功能:
- 在oledlib文件夹下作出多个c文件的分类 每个c文件的开头都有对该文件的简要说明
- 包括打点 画线 矩形 三角形 圆 椭圆 圆角矩形 的边缘与填充
- 还包括 字符显示 汉字显示 位图显示
- 最后还有 oled模拟串口printf的debug
- 字符显示:
- 针对于字符有4种大小0-1-2-3 具体参见SetFontSize()
- 基于大家的使用习惯
- 0是一般大家习惯用的 此时y只能为0-7对应显示的7大行 注意:此时x为地基大行 y为第几列
- 2 3都是基于1的等比例放大 此时y能为0-6x对应显示的每一小行 此时为正常坐标系 x为第几小行 y为第几列
- 中文汉字显示:
- 中文汉字的大小为16x16 此时y也只能为0-7对应显示的7大行 注意:此时x为地基大行 y为第几列
- 取模说明:
- 取模软件采用PCtoLCD2002
- 字符 汉字 和 位图的取模方式和设置都在font.c和bmp.c中有注释
- 用户调用函数:
- 在draw_api.h中提供了所有函数的接口 可在其中查看所有函数的简要功能
- 移植说明:
- 1.移植图形库仅需要准备好底层驱动 在oled_driver.c中作出修改即可 在该c文件开头有说明
- 2.若需要对test.c中的动画效果进行测试 还需要为函数OledTimeMsFunc()提供时间基准
- 3.库函数使用的延时函数是DelayMs() 移植后由单片机型号补充调整DelayMs()
- 图形库本质:
- 该图形库本质为对一数组进行操作 然后刷新整个数组到屏幕中实现效果
- 因此相似点阵屏(oled/TFT/大小尺寸/点阵/液晶)也可以使用 根据像素可参见oled_config.h
- 详细的注释:
- 如果是使用为用途 了解test.c和draw_api.c即可 做出花里胡哨的UI界面
- 在本人阅读代码和注释的过程中 发现很多结构和函数都值得学习 仔细理解理解
- GUI和本图形库的关系:
- gui是一个以图形界面来进行人机交互的系统 gui是拥有窗口、菜单、控件、对话框等交互的图形接口
- 这个只是一个图形库 类似于c++上的easyx图形库 是没有图形接口的 只提供绘图和显示的功能
- 图形库可以算是gui的一部分,也可以自己以图形库继续封装为gui库
- 代码容量:
- 除去位图 Code=26254 RO-data=3754 RW-data=100 ZI-data=4108
- 原作的话:
- 为了做这个绘制图形库,我参考了很多其他的算法,花了大量时间去做移植
- 优化,其中参考最多的是github中的arduboy游戏机,大部分图形是移植它的,
- 现在是最初的初稿版本,还有很多地方需要优化改进。我想要将这个图形库做大,
- 后续会加入更多有趣的东西,和模块,代码都是用最简单的方式编写的,都是开源的。
- 后续也会加上注释说明,让更多人以单片机和oled屏来入门硬件编程,如果你
- 使用了该库,请标明出处。b站关注oximeterg,可获取该库的最新版本和消息。
- 注意:绘制填充或实心的图形,影响刷新效率(待优化中)
- */
- // #include "test.h"
- #include "draw_api.h"
- #include "../Delay/Delay.h"
- #include "stdlib.h"
- #include "stdio.h"
- #include "math.h"
- void ShowStars(void);
- void ShowWatch(void);
- void ShowPolygon(void);
- void ShowSnow(void);
- void demo(void)
- {
- int i,j;
- //demo演示
- ClearScreen();
- DrawBitmap(0,0,Panda,128,64);
- UpdateScreen();
- DelayMs(1000);
- //字符
- ClearScreen();
- SetFontSize(1);
- DrawString(0,0,"test");
- UpdateScreen();
- DelayMs(1000);
- SetFontSize(2);
- DrawString(0,8,"test");
- UpdateScreen();
- DelayMs(1000);
- SetFontSize(3);
- DrawString(0,24,"test");
- UpdateScreen();
- DelayMs(1000);
- //汉字测试
- ClearScreen();
- OLED_ShowCHinese(0,0,"一只程序缘");
- UpdateScreen();
- DelayMs(1000);
- OLED_ShowCHinese(2,0,"一只程序缘一只程序缘一只程序缘一只程序缘");
- UpdateScreen();
- DelayMs(1000);
- //数字测试
- ClearScreen();
- for(i=0; i<300; i++)
- {
- SetFontSize(0);
- DrawNum(0,96,i,4);
- SetFontSize(1);
- DrawNum(0,16,i,4);
- SetFontSize(2);
- DrawNum(0,24,i,4);
- SetFontSize(3);
- DrawNum(0,40,i,4);
- UpdateScreen();
- }
- //串口debug
- DelayMs(100);
- ClearScreen();
- for(i=0; i<256; i++)
- {
- OledPrintf("num:%d cha:%c hex:%x\r\n",i,i,i);
- }
- DelayMs(100);
- //划线
- ClearScreen();
- for(i=0; i<20; i++)
- {
- DrawLine(0,0,i*10,63);
- UpdateScreen();
- }
- for(i=0; i<20; i++)
- {
- DrawLine(128,0,128-i*10,63);
- UpdateScreen();
- }
- DelayMs(100);
- //矩形
- for(j=0; j<2; j++)
- {
- if(j==0)
- ClearScreen();
- for(i=0; i<31; i+=2)
- {
- DrawRect2(i*2,i,128-i*4,64-2*i);//画矩形外框
- UpdateScreen();
- }
- if(j==0)
- ClearScreen();
- DelayMs(100);
- for(i=31; i>0; i-=2)
- {
- DrawFillRect2(i*2,i,128-i*4,64-2*i);//画实心矩形
- UpdateScreen();
- }
- SetDrawColor(pix_black);//划线颜色
- SetFillcolor(pix_black);//填充颜色
- }
- SetDrawColor(pix_white);
- SetFillcolor(pix_white);
- //圆角矩形
- for(j=0; j<2; j++)
- {
- if(j==0)
- ClearScreen();
- for(i=0; i<25; i+=2)
- {
- DrawRoundRect(i*2,i,128-i*4,64-2*i,8);
- UpdateScreen();
- }
- if(j==0)
- ClearScreen();
- DelayMs(100);
- for(i=25; i>2; i-=2)
- {
- DrawfillRoundRect(i*2,i,128-i*4,64-2*i,8);
- UpdateScreen();
- }
- SetDrawColor(pix_black);
- SetFillcolor(pix_black);
- }
- SetDrawColor(pix_white);
- SetFillcolor(pix_white);
- DelayMs(100);
- //椭圆
- ClearScreen();
- DrawEllipse(63,31,63,31);
- UpdateScreen();
- DelayMs(500);
- ClearScreen();
- DrawEllipse(63,31,16,31);
- UpdateScreen();
- DelayMs(500);
- ClearScreen();
- DrawFillEllipse(63,31,63,31);
- UpdateScreen();
- DelayMs(500);
- ClearScreen();
- DrawFillEllipse(63,31,16,31);
- UpdateScreen();
- DelayMs(500);
- //圆
- ClearScreen();
- DrawCircle(63,31,30);
- UpdateScreen();
- DelayMs(500);
- ClearScreen();
- DrawFillCircle(63,31,30);
- UpdateScreen();
- DelayMs(500);
- //三角形
- ClearScreen();
- DrawTriangle(5,10,100,30,60,50);
- UpdateScreen();
- DelayMs(500);
- ClearScreen();
- DrawFillTriangle(5,10,100,30,60,50);
- UpdateScreen();
- DelayMs(500);
- //绘制图形图片 位图
- ClearScreen();
- DrawBitmap(0,0,BmpTest1,16,16);
- UpdateScreen();
- DelayMs(500);
- DrawBitmap(16,0,BmpTest2,32,32);
- UpdateScreen();
- DelayMs(500);
- DrawBitmap(48,0,BmpTest3,64,64);
- UpdateScreen();
- DelayMs(500);
- //圆弧
- ClearScreen();
- for(i=0; i<360; i++)
- {
- DrawArc(63,31,30,0,i); //画圆弧
- UpdateScreen();
- DelayMs(25);
- ClearScreen();
- }
- DrawCircle(63,31,30); //画圆
- UpdateScreen();
- DelayMs(100);
- for(i=0; i<10; i++)
- {
- DrawFillCircle(63,31,i); //在中心填充圆
- DrawCircle(63,31,30);
- UpdateScreen();
- DelayMs(25);
- ClearScreen();
- }
- //绕点
- for(i=0; i<720; i++) //转720度2圈
- {
- TypeXY temp;
- SetAngle(i); //设置角度
- SetRotateCenter(63,31); //设置圆心
- temp=GetRotateXY(63,31+30); //讲已知坐标旋转角度
- DrawFillCircle(temp.x,temp.y,5);//画出算出的位置
- DrawCircle(63,31,30); //画出轨迹
- DrawFillCircle(63,31,10); //填充中心
- UpdateScreen(); //更新屏幕
- ClearScreen();
- }
- //向右边平移
- for(i=0; i<95; i++)
- {
- TypeXY temp; //其实就是上面继续旋转
- SetAngle(720+i); //画图的时候x+偏移量
- SetRotateCenter(63+i,31);
- temp=GetRotateXY(63+i,31+30);
- DrawFillCircle(temp.x,temp.y,5);
- DrawCircle(63+i,31,30);
- DrawFillCircle(63+i,31,10);
- UpdateScreen();
- ClearScreen();
- }
- //动画
- ShowStars(); //星空动画
- ShowWatch(); //时钟动画
- ShowPolygon(); //多边形动画
- // ShowSnow(); //下雪动画
- DelayMs(100);
- //结束
- ClearScreen();
- SetFontSize(2);
- DrawString(8,16," Show End "); //显示字符串
- UpdateScreen();
- DelayMs(1000);
- ClearScreen();
- DrawBitmap(0,10,Like,128,40); //三连图片
- UpdateScreen();
- DelayMs(1000);
- }
- /
- //星空动画
- void ShowStars(void)
- {
- int i;
- int count=0;
- int fps=60;
- typedef struct START
- {
- short x;
- short y;
- short speed;
- unsigned char speedcount;
- unsigned char isexist;
- } Star;
- Star star[128]= {0};
- srand(2);
- for(i=0; i<128; i++)
- {
- if(star[i].isexist==0)
- {
- //设置128个()星星的初始信息
- star[i].x=rand()%127; //随机生成初始x坐标
- star[i].y=rand()%64; //随机生成y的坐标
- star[i].speedcount=0;
- star[i].speed=rand()%8+1; //1-8的数
- star[i].isexist=1;
- }
- }
- while(1)
- {
- if(FrameRateUpdateScreen(fps)==1) //在此函数中定时刷新屏
- {
- count++;
- if(count>=fps*10) //10秒钟时间到达之后跳出循环结束动画
- return;
- }
- //此段函数一直在运行
- //依次画出128个星星
- for(i=0; i<128; i++)
- {
- //如果这一个星星已经移动到退出屏幕界面
- //则在最左侧重新生成一颗新星星
- if(star[i].isexist==0)
- {
- star[i].x=0;
- star[i].y=rand()%64;
- star[i].speed=rand()%6+1;
- star[i].speedcount=0;
- star[i].isexist=1;
- }
- else
- {
- star[i].speedcount++;
- if(star[i].x>=124) //标记已经退出屏幕
- star[i].isexist=0;
- //清除上一个时刻画的星星(的尾巴) 不管有没有操作 都进行清除操作
- SetDrawColor(pix_black);
- DrawLine(star[i].x,star[i].y,star[i].x,star[i].y);
- SetDrawColor(pix_white);
- if(star[i].speedcount==star[i].speed) //运行时间到了一定的长度
- {
- star[i].speedcount=0; //复位运行时间并向右移一格
- star[i].x+=1; //总之星星的结束需要在这经历124次
- } //只不过有的更快 就能移动更快
- //从头到尾画出整条星星 不管星星是否已经变化
- DrawLine(star[i].x, star[i].y, star[i].x+(6/star[i].speed)-1, star[i].y);
- }
- }
- }
- }
- //时钟动画
- //钟 小时 分钟 秒,
- void RoundClock(int hours,int minute,int sec)
- {
- unsigned char i=0;
- TypeXY hourspoint,minutepoint,secpoint,tmp1,tmp2;
- //时针
- SetRotateValue(63,31,hours*30+(minute*30)/60,1);
- hourspoint=GetRotateXY(63-14,31);
- DrawLine(63,31,hourspoint.x,hourspoint.y);
- //分针
- SetRotateValue(63,31,minute*6+(sec*6)/60,1);
- minutepoint=GetRotateXY(63-21,31);
- DrawLine(63,31,minutepoint.x,minutepoint.y);
- //秒针
- SetRotateValue(63,31,sec*6,1);
- secpoint=GetRotateXY(63-28,31);
- DrawLine(63,31,secpoint.x,secpoint.y);
- //表盘
- for(i=0; i<12; i++)
- {
- SetRotateValue(63,31,i*30,1);
- tmp1=GetRotateXY(63-29,31);
- tmp2=GetRotateXY(63-24,31);
- DrawLine(tmp1.x,tmp1.y,tmp2.x,tmp2.y);
- }
- DrawFillCircle(63,31,2);
- DrawCircle(63,31,30);
- UpdateScreen();
- DelayMs(25);
- ClearScreen();
- }
- void ShowWatch(void)
- {
- int i,j,z;
- int count=0;
- for(i=0; i<12; i++)
- for(j=0; j<60; j++)
- for(z=0; z<60; z++)
- {
- RoundClock(i,j,z);
- count++;
- if(count>=800)
- return;
- }
- }
- /
- //多边形动画
- void ShowPolygon(void)
- {
- int x0=63,y0=31; //正多边形的外接圆的圆心
- unsigned char i =0,j;
- int n=1,r=31; //画正n边形 大小半径31
- int v=1,count=0; //每个相邻的多边形隔1 画count次后退出
- int x[30],y[30];
- while(1)
- {
- ClearScreen();
- for(i=0; i<n; i++)
- {
- x[i]=r*cos(2*3.1415926*i/n)+x0;
- y[i]=r*sin(2*3.1415926*i/n)+y0;
- }
- for(i=0; i<=n-2; i++)
- {
- for(j=i+1; j<=n-1; j++)
- DrawLine(x[i],y[i],x[j],y[j]);
- }
- n+=v;
- if(n==20||n==0)
- v=-v;
- UpdateScreen();
- DelayMs(25); //延时停顿100ms
- if(++count==90)
- {
- count=0;
- return ;
- }
- }
- }
- //下雪的函数 和星空类似
- void ShowSnow(void)
- {
- int a[66],i,num=0;
- int count=0;
- int fps=60;
- struct Snow
- {
- short x;
- short y;
- short speed;
- } snow[100];
- srand(1);
- for(i=0; i<66; i++)
- a[i]=(i-2)*10;
- ClearScreen();
- while(1)
- {
- if(FrameRateUpdateScreen(fps)==1) //在此函数中定时刷新屏
- {
- count++;
- if(count>=fps*10) //10秒钟时间到达之后跳出循环结束动画
- return;
- }
- if(num!=100)
- {
- snow[num].speed=1+rand()%4;
- i=rand()%66;
- snow[num].x=a[i];
- snow[num].y=0;
- num++;
- }
- for(i=0; i<num; i++)
- {
- snow[i].y+=snow[i].speed;
- DrawPixel(snow[i].x,snow[i].y+1);
- DrawPixel(snow[i].x+1,snow[i].y);
- DrawPixel(snow[i].x,snow[i].y);
- DrawPixel(snow[i].x-1,snow[i].y);
- DrawPixel(snow[i].x,snow[i].y-1);
- if(snow[i].y>63)
- {
- snow[i].y=0;
- }
- }
- UpdateScreen();
- DelayMs(25);
- ClearScreen();
- }
- }