发 帖  
原厂入驻New

[经验] 【小项目程序分享】STM32 OLED打点划线画圆 OLED电子罗盘

2019-12-6 10:05:33  1502 STM32 电子罗盘 OLED
分享
2
用到的工具
用到的库函数为 正点原子 STM32F4 库OLED
  1. <blockquote> 自定义OLED 坐标系如下: 【构建OLED 直角坐标系, x,y轴反置 方便函数运算】
复制代码

一、画点函数
  1. //画点
  2. //x:0~127
  3. //y:0~63
  4. //t:1 填充 0,清空                                  
  5. void OLED_DrawPoint(u8 x,u8 y,u8 t)
  6. {
  7.         u8 pos,bx,temp=0;
  8.         IF(x>127||y>63)return;//超出范围了.
  9.         pos=7-y/8;
  10.         bx=y%8;
  11.         temp=1<<(7-bx);
  12.         if(t)OLED_GRAM[x][pos]|=temp;
  13.         else OLED_GRAM[x][pos]&=~temp;            
  14. }
复制代码
二、动态划线
  1. 此函数有限制条件:
  2. - 1.划线的线段在 规定的圆内.
  3. - 2.斜率为东北天坐标系下 解算航向斜率slope
复制代码
构建的是后面 OLED页面指南针 的 “ 针 ”
  1. /* 使用不同坐标系 为了解决函数上 x映射y时只能多对一的关系 该方法较为繁杂 */
  2. void draw_line(u8 x0,u8 y0,float k,u8 dot) //过固定点(x0,y0),斜率k   dot:0,清空;1,填充          
  3. {
  4.                 u8 x,y;
  5.                 //y = (k*(x-x0)+y0); 直线函数
  6. /* 以下函数使用该坐标系:
  7.                                     127 ↑y
  8.                         -------------------------
  9.                         |                                                |
  10.                         |                                                |
  11.                         |                                                |
  12.                         |                                                |
  13.            ←-----------------------------(0,0)x  
  14.                         63
  15. */
  16.         for(x = 0;x <= 63;x++){
  17.                 y = sqrt(pow(20,2)-pow(x-31,2))+31+1; //圆方程  x,y反置
  18.                
  19.                 if( (JY901.Angle[2] >-135 && JY901.Angle[2] <-90 ) ||(JY901.Angle[2] >90 && JY901.Angle[2] < 145 ) || dot == 0 ){ //上半圆
  20.                         if( ((x-x0)/k+y0) >= 31 && ((x-x0)/k+y0) < y ) {  //点限制在 圆方程内
  21.                                 OLED_DrawPoint(x,((x-x0)/k+y0),dot);
  22.                         }
  23.                 }
  24.                        
  25.                 if( (JY901.Angle[2] < -45 && JY901.Angle[2] > -90) || (JY901.Angle[2] < 90 && JY901.Angle[2] > 45) || dot == 0 ){ //上半圆
  26.                         if(  ((x-x0)/k+y0) <= 31 && ((x-x0)/k+y0)> 63-y ) {  //点限制在 圆方程内
  27.                                 OLED_DrawPoint(x,((x-x0)/k+y0),dot);}
  28.                 }
  29.         }
  30. /* 以下函数使用该坐标系:
  31.             127 ↑y
  32.                         ------------
  33.                         |              |
  34.                         |                  |
  35.                         |                  |
  36.                         |                  |
  37.                         |                  |
  38.                         |                  |
  39.                 (0,0)----------→x  
  40.                                         63
  41. */
  42.         for(x = 0;x <= 63;x++){
  43.                 y = sqrt(pow(20,2)-pow(x-31,2))+31+1; //圆方程  x,y反置
  44.        
  45.                 if( (JY901.Angle[2] >=-45 && JY901.Angle[2] <= 0) || (JY901.Angle[2] >=-180 && JY901.Angle[2] <= -135)  || dot == 0 ){  // JY901.Angle[2] < 0
  46.                         if( (k*(x-x0)+y0) >= 31 && (k*(x-x0)+y0) < y ) {  //点限制在 圆方程内   上半圆
  47.                                 OLED_DrawPoint((k*(x-x0)+y0),x,dot);
  48.                         }
  49.                 }
  50.                        
  51.                 if( (JY901.Angle[2] > 0 && JY901.Angle[2] <= 45) || (JY901.Angle[2] >=135 && JY901.Angle[2] <= 180)  || dot == 0 ){  // JY901.Angle[2] < 0
  52.                         if(((k*(x-x0)+y0)< 31 && (k*(x-x0)+y0) > 63-y)) {  //点限制在 圆方程内  下半圆
  53.                                 OLED_DrawPoint((k*(x-x0)+y0),x,dot);
  54.                         }
  55.                 }
  56.         }

  57. }
复制代码
此间延时方法为 RT-Thread 操作系统中 释放内存 挂起函数 rt_thread_delay()
  1. /* 开机动画 */
  2. void Boot_Animation(void)
  3. {
  4.                 static u8 x=0,y=0;
  5.                 for(x = 63;x>=18;x--){
  6.                                 OLED_DrawPoint(108-0.7*x,x,1);//画斜线 斜率≈√3/3
  7.                                 OLED_DrawPoint(17 +0.7*x,x,1);
  8.                                 y = 64-x;
  9.                                 OLED_DrawPoint(64-0.7*y,y,1);
  10.                                 OLED_DrawPoint(64+0.7*y,y,1);
  11.                                 rt_thread_delay(2);
  12.                                   OLED_Refresh_Gram();//更新显示到OLED
  13.                 }
  14.                
  15.                 for(x = 30;x <= 94;x++){
  16.                                 OLED_DrawPoint(125-x,47,1);
  17.                                 OLED_DrawPoint(x,18,1);
  18.                                 rt_thread_delay(2);
  19.                                 OLED_Refresh_Gram();//更新显示到OLED
  20.                 }

  21.                 OLED_ShowString(60,20,(u8 *)"E",16);
  22.                   OLED_Refresh_Gram();//更新显示到OLED
  23.                 rt_thread_delay(100);
  24.                
  25. }
复制代码
效果演示:上下同时画两个互相倒置的三角形,形成简易六芒星.
20190212165405446.gif
三、画圆函数构建的是后面 OLED页面指南针 的 “ 圆 ”
  1. void draw_circle(u8 x0,u8 y0,u8 r) //圆心(x0,y0),半径r
  2. {
  3.         u8 x,y;
  4.         for(x = 0;x <= 63;x++){
  5.                 y = sqrt(pow(r,2)-pow(x-x0,2))+y0; //圆方程  x,y反置
  6.                 OLED_DrawPoint(y,x,1);      //上半圆
  7.                 OLED_DrawPoint(63-y,x,1);   //下半圆
  8.         }
  9. }

复制代码
20190217163549224.jpg
  1. OLED_PicturePage()
  2. - 1.右半边显示OLED电子罗盘
  3. - 2.左半边显示欧拉角:①Roll 横滚角 ②Pitch 俯仰角 ③ Yaw 偏航角 与 偏航角的正切值
复制代码
  1. /* OLED第四页 【图像页】*/
  2. void OLED_PicturePage(void)
  3. {
  4.                 static u8 y=0;
  5.                 char str[100];
  6.        
  7.                 draw_line(31,31,slope,0); //清除上一次画的线 进行刷新
  8.                 OLED_Refresh_Gram();//更新显示到OLED
  9.        
  10.                 slope = tan((float)(JY901.Angle[2]*Pi/180));  //转化弧度制 解算东北天坐标系下 航向斜率slope
  11.        
  12.                 for(y = 28;y <= 36;y++){ //补圆顶底部的缺失点
  13.                                 OLED_DrawPoint(y,0,1);
  14.                                 OLED_DrawPoint(y,63,1);
  15.                 }
  16.        
  17.                 draw_line(31,31,slope,1);
  18.                
  19.                 sprintf(str,"Rol:%3.1f  ",JY901.Angle[0]); //横滚脚Roll
  20.                 OLED_ShowString(65,0, (u8 *)str,12);
  21.                
  22.                 sprintf(str,"Pit:%3.1f  ",JY901.Angle[1]); //俯仰角Pitch
  23.                 OLED_ShowString(65,16, (u8 *)str,12);
  24.                
  25.                 sprintf(str,"Yaw:%3.1f  ",JY901.Angle[2]); //俯仰角Yaw
  26.                 OLED_ShowString(65,32, (u8 *)str,12);
  27.                
  28.                 sprintf(str,"k:%.1f   ",slope);
  29.                 OLED_ShowString(65,48,(u8 *)str,12);
  30.                

  31.                 OLED_ShowString(29,2 ,(u8 *)"N",12);
  32.                 OLED_ShowString(29,51,(u8 *)"S",12);
  33.                 OLED_ShowString(3        ,28,(u8 *)"W",12);
  34.                 OLED_ShowString(55,28,(u8 *)"E",12);
  35.                 draw_circle(31,31,32);

  36.        
  37.                 OLED_Refresh_Gram();//更新显示到OLED                                               
  38. }
复制代码

效果演示 20190217162539754.gif
四、实心圆函数
  1. void draw_fill_circle(u8 x0,u8 y0,u8 r,u8 dot)//写画实心圆心(x0,y0),半径r
  2. {       
  3.                 u8 x = 0,y = 0,R = 0;
  4.                 for(x = x0-r;x <= x0+r;x++){
  5.                         for(y = y0-r; y <= y0+r ;y++ ){
  6.                                 R = sqrt(pow(r,2)-pow(x-x0,2))+y0; //圆方程  x,y反置               
  7.                                 if( (y >= y0 && y <= R) || (y < y0 && y >= 2*y0-R )|| dot == 0 ) {  //点限制在 圆方程内       
  8.                                         OLED_DrawPoint(y,x,dot);
  9.                                 }       
  10.                         }
  11.                 }
  12. }
复制代码
本文转自CSDN 博主:淹死的大白鲨




相关经验

langzitianya 2019-12-6 13:05:43
不错的实验,学习了,希望继续
回复

举报

simplea 2019-12-8 16:16:24

不错的实验,学习了,希望继续
回复

举报

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发经验
关闭

站长推荐 上一条 /7 下一条

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