【STM32】STM32 OLED打点划线画圆 OLED电子罗盘 程序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_39492932/article/details/87097988


注: 本文仅用于学习分享

用到的工具

  • STM32 MCU
  • Keil 5

用到的库函数为 正点原子 STM32F4 库OLED


 自定义OLED 坐标系如下: 【构建OLED 直角坐标系, x,y轴反置 方便函数运算】

			↑y
		    |
	      127--------
			|	     |
			|		 |
			|		 |
			|		 |
			|		 |
			|		 |
		(0,0)----------→x  
							63

一、画点函数

//画点 
//x:0~127
//y:0~63
//t:1 填充 0,清空				   
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
	u8 pos,bx,temp=0;
	if(x>127||y>63)return;//超出范围了.
	pos=7-y/8;
	bx=y%8;
	temp=1<<(7-bx);
	if(t)OLED_GRAM[x][pos]|=temp;
	else OLED_GRAM[x][pos]&=~temp;	    
}

二、动态划线

此函数有限制条件:
- 1.划线的线段在 规定的圆内.
- 2.斜率为东北天坐标系下 解算航向斜率slope

构建的是后面 OLED页面指南针 的 “ 针 ”

/* 使用不同坐标系 为了解决函数上 x映射y时只能多对一的关系 该方法较为繁杂 */
void draw_line(u8 x0,u8 y0,float k,u8 dot) //过固定点(x0,y0),斜率k   dot:0,清空;1,填充	  
{
		u8 x,y;
		//y = (k*(x-x0)+y0); 直线函数
/* 以下函数使用该坐标系: 
	                            127 ↑y
			-------------------------
			|						|
			|						|
			|						|
			|						|
	   ←-----------------------------(0,0)x  
			63
*/
	for(x = 0;x <= 63;x++){
		y = sqrt(pow(20,2)-pow(x-31,2))+31+1; //圆方程  x,y反置
		
		if( (JY901.Angle[2] >-135 && JY901.Angle[2] <-90 ) ||(JY901.Angle[2] >90 && JY901.Angle[2] < 145 ) || dot == 0 ){ //上半圆
			if( ((x-x0)/k+y0) >= 31 && ((x-x0)/k+y0) < y ) {  //点限制在 圆方程内
				OLED_DrawPoint(x,((x-x0)/k+y0),dot);
			}
		}
			
		if( (JY901.Angle[2] < -45 && JY901.Angle[2] > -90) || (JY901.Angle[2] < 90 && JY901.Angle[2] > 45) || dot == 0 ){ //上半圆
			if(  ((x-x0)/k+y0) <= 31 && ((x-x0)/k+y0)> 63-y ) {  //点限制在 圆方程内
				OLED_DrawPoint(x,((x-x0)/k+y0),dot);}
		}
	}
/* 以下函数使用该坐标系: 
	    127 ↑y
			------------
			|	      |
			|		  |
			|		  |
			|		  |
			|		  |
			|		  |
		(0,0)----------→x  
					63
*/
	for(x = 0;x <= 63;x++){
		y = sqrt(pow(20,2)-pow(x-31,2))+31+1; //圆方程  x,y反置
	
		if( (JY901.Angle[2] >=-45 && JY901.Angle[2] <= 0) || (JY901.Angle[2] >=-180 && JY901.Angle[2] <= -135)  || dot == 0 ){  // JY901.Angle[2] < 0
			if( (k*(x-x0)+y0) >= 31 && (k*(x-x0)+y0) < y ) {  //点限制在 圆方程内   上半圆
				OLED_DrawPoint((k*(x-x0)+y0),x,dot);
			}
		}
			
		if( (JY901.Angle[2] > 0 && JY901.Angle[2] <= 45) || (JY901.Angle[2] >=135 && JY901.Angle[2] <= 180)  || dot == 0 ){  // JY901.Angle[2] < 0
			if(((k*(x-x0)+y0)< 31 && (k*(x-x0)+y0) > 63-y)) {  //点限制在 圆方程内  下半圆
				OLED_DrawPoint((k*(x-x0)+y0),x,dot);
			} 
		}
	}

}

此间延时方法为 RT-Thread 操作系统中 释放内存 挂起函数 rt_thread_delay()

/* 开机动画 */
void Boot_Animation(void)
{
		static u8 x=0,y=0;
		for(x = 63;x>=18;x--){
				OLED_DrawPoint(108-0.7*x,x,1);//画斜线 斜率≈√3/3
				OLED_DrawPoint(17 +0.7*x,x,1);
				y = 64-x;
				OLED_DrawPoint(64-0.7*y,y,1);
				OLED_DrawPoint(64+0.7*y,y,1);
				rt_thread_delay(2);
			  	OLED_Refresh_Gram();//更新显示到OLED
		}
		
		for(x = 30;x <= 94;x++){
				OLED_DrawPoint(125-x,47,1);
				OLED_DrawPoint(x,18,1);
				rt_thread_delay(2);
				OLED_Refresh_Gram();//更新显示到OLED
		}

		OLED_ShowString(60,20,(u8 *)"E",16);
	  	OLED_Refresh_Gram();//更新显示到OLED
		rt_thread_delay(100);
		
}

效果演示:

上下同时画两个互相倒置的三角形,形成简易六芒星.
在这里插入图片描述

三、画圆函数

构建的是后面 OLED页面指南针 的 “ 圆 ”

void draw_circle(u8 x0,u8 y0,u8 r) //圆心(x0,y0),半径r
{
	u8 x,y;
	for(x = 0;x <= 63;x++){
		y = sqrt(pow(r,2)-pow(x-x0,2))+y0; //圆方程  x,y反置
		OLED_DrawPoint(y,x,1);      //上半圆
		OLED_DrawPoint(63-y,x,1);   //下半圆
	}
}

在这里插入图片描述

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

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

	
		OLED_Refresh_Gram();//更新显示到OLED						
}

效果演示

在这里插入图片描述

四、实心圆函数

void draw_fill_circle(u8 x0,u8 y0,u8 r,u8 dot)//写画实心圆心(x0,y0),半径r
{	
		u8 x = 0,y = 0,R = 0;
		for(x = x0-r;x <= x0+r;x++){
			for(y = y0-r; y <= y0+r ;y++ ){
				R = sqrt(pow(r,2)-pow(x-x0,2))+y0; //圆方程  x,y反置		
				if( (y >= y0 && y <= R) || (y < y0 && y >= 2*y0-R )|| dot == 0 ) {  //点限制在 圆方程内	
					OLED_DrawPoint(y,x,dot);
				}	
			}
		}
}

Dwfish 淹死的鱼 2019.2.12

猜你喜欢

转载自blog.csdn.net/qq_39492932/article/details/87097988