OLED旋转任意角度显示,含C语言打印

在之前90度旋转的基础上,利用旋转矩阵,完成了任意角度旋转的程序。

程序实现效果如下

达成成就:东倒西歪

实现了6x8字符和8x16字符以及16x16中文的旋转显示(旋转数组使用的16x16),不过中文在旋转时可能会出现超过显示区域的情况,因为16x16的旋转会超过这个大小,有需要的可以自行根据程序修改。

这里我直接贴出stm32的代码

参数定义

int s_deg=0;旋转矩阵使用

u8 y_1[16][16]={0};//原始读取
float res[2][16*16]={0};//旋转矩阵后缓存数组
int trans[16][16]={0};//旋转使用

u8 map_size_x=16,map_size_y=16;//旋转区域x,y,暂未全部使用,部分使用,可自行调整旋转区域

旋转代码

void oled_cn_shift(u8 x,u8 y,int turn_deg,u8 no,u8 is_char)//16*16/8*16字符或中文显示,is_char==0显示中文,其他显示8*16字符,no为字符或者中文的序号
{      			    
	u8 t,adder=0;
	u8 dis_ok[32]={0};
	float max_offset_x=0,max_offset_y=0;
	int deg=-1*turn_deg*val;
	float t_b[2][2]={{cos(deg), -sin(deg)},{sin(deg),cos(deg)}};//旋转矩阵
	memset(res,0,sizeof(float)*512);
	memset(trans,0,sizeof(int)*256);
	memset(y_1,0,sizeof(u8)*256);//清空数组
	if(is_char==0){
	for(int i1=0;i1<map_size_y;i1++){//y数据  提取到16*16的数组 中文
		for(int i2=0;i2<map_size_x;i2++){//x
			y_1[i1][i2]=i1>7? ((Hzk[2*no+1][i2]&(1<<(i1-8)))>0 ? map_size_y+1-(i1+1):0 ) : ( (Hzk[2*no][i2]&(1<<(i1)))>0 ? map_size_y+1-(i1+1):0);
		}
		
	}	}else{
		
	for(int i1=0;i1<map_size_y;i1++){//y数据  提取到16*16的数组
		for(int i2=0;i2<map_size_x;i2++){//x
			y_1[i1][i2]=i2>7 ? 0: i1>7? ((F8X16s[(no-' ')*16+i2+8]&(1<<(i1-8)))>0 ? map_size_y+1-(i1+1):0 ) : ( (F8X16s[(no-' ')*16+i2]&(1<<(i1)))>0 ? map_size_y+1-(i1+1):0);
		}
		
	}}
	//进行旋转	
	for(int i1=0;i1<2;i1++){//旋转矩阵的行数
		for(int i2=0;i2<map_size_y*map_size_x;i2++){//被旋转的列数
			
			res[i1][i2]=t_b[i1][0]*(y_1[i2%16][i2/16]==0 ? 0 :((i2/16)+1))+t_b[i1][1]*y_1[i2%16][i2/16];//*x+*y,i1=0->x,i1=1->y
			if(res[i1][i2]<2&&y_1[i2%16][i2/16]!=0 &&i1==0){ //ok
				
				if(max_offset_x>((int)res[i1][i2]-2)) max_offset_x=((int)res[i1][i2]-2);//x<1
			}
			else 
			if(res[i1][i2]<2&&i1==1&&y_1[i2%12][i2/16]!=0){
				
				if(max_offset_y>((int)res[i1][i2]-2)) max_offset_y=((int)res[i1][i2]-2);
			}
			if(res[i1][i2]>=14 &&i1==0){
				
				if(max_offset_x<((int)res[i1][i2]-14)) max_offset_x=((int)res[i1][i2]-14);//x>15
			}
			else 
			if(res[i1][i2]>14&&i1==1){
				
				if(max_offset_y<((int)res[i1][i2]-14)) max_offset_y=((int)res[i1][i2]-14);
			}
		}
	}
        //将旋转后的数组进行调整,尽可能保证图像在16x16区域内,并取整
		for(int i2=0;i2<map_size_y*map_size_x;i2++){//被旋转的列数

			if(((int)(res[0][i2])!=0)||(int)(res[1][i2])!=0) {
				
				trans[15-((int)(res[1][i2]-max_offset_y)-1)][15-((int)(res[0][i2]-max_offset_x)-1)]=1;
			}

		}	
    //将数组转化为位数据,及8个bit代表OLED的一根显示单元,便于OLED显示
	for(int i1=0;i1<map_size_y;i1++){//y
		for(int i2=0;i2<map_size_x;i2++){//x
			if(i1<8){//第一行
				dis_ok[i2]|=(trans[i1][15-i2])!=0 ? 1<<i1:0;
			} else{//第二行
				dis_ok[i2+16]|=(trans[i1][15-i2])!=0 ? 1<<(i1-8):0;
			}
		}
	}
	OLED_Set_Pos(x,y);	//第一行,共16列
	for(int i1=0;i1<32;i1++){
		if(i1==16) OLED_Set_Pos(x,y+1);//第二行,共16列
		OLED_WR_Byte(dis_ok[i1],OLED_DATA);

	}	

}

调用方法

		oled_cn_shift(32,6,s_deg+90,'L',1);//8x16字符
		oled_cn_shift(32,8,s_deg,'D',1);
		
		oled_cn_shift(54,10,s_deg,14,0);//16x16中文
		oled_cn_shift(32,10,s_deg,15,0);

中文会出现超出区域的情况,使用需扩大旋转和显示区域

字符和中文的数组格式如下

6x8的字符我就不贴了,可以根据8x16的进行修改,只是我用的旋转数组为12x12

如果不方便在STM32上调试,也可以直接使用C语言测试

效果如下

代码如下

#include "stdio.h"
#define u8 unsigned char
#include "math.h"
#define turn_deg 30
//旋转角度
#define val 3.1415926/180
#define deg (-1*turn_deg*val)
unsigned char src7[]={0,0xff,0x11,0x11,0x11,0x11,0x01,0},dis[8]={0},src[]={0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,   0x00, 0x7F, 0x09, 0x09, 0x09, 0x01};
u8 line_8_src[]={},src1[]={0,0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,0},src3[]={0,0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,0},src4[]={0,0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,0},
  src_16_1[]={0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},//E 37
  src_16_2[]={0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},
  zw_1[2][16]={{0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00},
{0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00}}/*"中",0*/;//F 38,都是字符和中文的显示数组
u8 /*x[12][12]={0},*/y[16][16]={0};


float res[2][16*16]={0},temp1,temp2,t_b[][2]={{cos(deg), -sin(deg)},{sin(deg),cos(deg)}};

//int sf_x=0,sf_y=0;
int trans[16][16]={0};
u8 dis_ok[32]={0};
float max_offset_x=0,max_offset_y=0;

u8 map_size_x=16,map_size_y=16;//旋转和显示区域大小

#define schar//是否是字符/中文,定义显示字符,未定义显示中文

void draw_array(u8 weigt,u8 heigt,int *arr){
	
}


int main(){
	printf("hello world \n");
	#ifdef schar
	for(int i1=0;i1<16;i1++){//y原始图像,8*16
		for(int i2=0;i2<16;i2++){
//			printf("%c ",(src_16_1[i2]&(1<<i1))>0 ? '*':'.');
			printf("%c ",i1>7? (src_16_2[i2+8]&(1<<(i1-8)))>0&&i2<8 ? '*':'.':(src_16_2[i2]&(1<<i1))>0&&i2<8 ? '*':'.');
			if(i2==map_size_x-1) printf("%d ",i1);
			
		}
		printf("\n");
		if(i1==map_size_y-1) for(int i2=0;i2<16;i2++) if(i2==map_size_x-1)printf("%d \n",i2%10); else printf("%d ",i2%10);
		
	}
	#else
	for(int i1=0;i1<16;i1++){//y原始图像 中文
		for(int i2=0;i2<16;i2++){
//			printf("%c ",(src_16_1[i2]&(1<<i1))>0 ? '*':'.');
			printf("%c ",i1>7? (zw_1[1][i2]&(1<<(i1-8)))>0  ? '*':'.' /*0*/:(zw_1[0][i2]&(1<<i1))>0/*&&i2<8*/ ? '*':'.');
			if(i2==map_size_x-1) printf("%d ",i1);//纵坐标
			
		}
		printf("\n");
		if(i1==map_size_y-1) for(int i2=0;i2<16;i2++) if(i2==map_size_x-1)printf("%d \n",i2%10); else printf("%d ",i2%10);//横坐标
		
	}
	#endif
	
	//printf("0\n");
	#ifdef schar
	for(int i1=0;i1<map_size_y;i1++){//y数据提取到16*16的数组
		for(int i2=0;i2<map_size_x;i2++){//x
			y[i1][i2]=i2>7 ? 0: i1>7? ((src_16_2[i2+8]&(1<<(i1-8)))>0 ? map_size_y+1-(i1+1):0 ) : ( (src_16_2[i2]&(1<<(i1)))>0 ? map_size_y+1-(i1+1):0);
		}
		
	}
	#else
	for(int i1=0;i1<map_size_y;i1++){//y数据提取到16*16的数组 中文
		for(int i2=0;i2<map_size_x;i2++){//x
			y[i1][i2]=i1>7? ((zw_1[1][i2]&(1<<(i1-8)))>0 ? map_size_y+1-(i1+1):0 ) : ( (zw_1[0][i2]&(1<<(i1)))>0 ? map_size_y+1-(i1+1):0);
		}
		
	}
	#endif
    //旋转
	for(int i1=0;i1<2;i1++){//旋转矩阵的行数
		for(int i2=0;i2<map_size_y*map_size_x;i2++){//被旋转的列数
			
			res[i1][i2]=t_b[i1][0]*(y[i2%16][i2/16]==0 ? 0 :((i2/16)+1))+t_b[i1][1]*y[i2%16][i2/16];//*x+*y,i1=0->x,i1=1->y
			if(res[i1][i2]<2&&y[i2%16][i2/16]!=0 &&i1==0){ //ok
				
				if(max_offset_x>((int)res[i1][i2]-2)) max_offset_x=((int)res[i1][i2]-2);//x<1
			}
			else 
			if(res[i1][i2]<2&&i1==1&&y[i2%12][i2/16]!=0){
				
				if(max_offset_y>((int)res[i1][i2]-2)) max_offset_y=((int)res[i1][i2]-2);
			}
			if(res[i1][i2]>=14 &&i1==0){
				
				if(max_offset_x<((int)res[i1][i2]-14)) max_offset_x=((int)res[i1][i2]-14);//x>15
			}
			else 
			if(res[i1][i2]>14&&i1==1){
				
				if(max_offset_y<((int)res[i1][i2]-14)) max_offset_y=((int)res[i1][i2]-14);
			}

//			printf("%.d ",/*i2/12,y[i2%12][i2/12]*/i1==0? (int)(res[i1][i2]-(res[i1][i2]==0? 0:max_offset_x)): (int)(res[i1][i2]-(res[i1][i2]==0? 0:max_offset_y)));
			
		}
//		printf("\n\n");
	}
    //显示数组调整,尽可能使图像在显示区域内(大于0,小于最大宽度)
		for(int i2=0;i2<map_size_y*map_size_x;i2++){//被旋转的列数

			if(((int)(res[0][i2])!=0)||(int)(res[1][i2])!=0) {
				
				trans[15-((int)(res[1][i2]-max_offset_y)-1)][15-((int)(res[0][i2]-max_offset_x)-1)]=1;
//				printf("%d,%d ",(int)(res[0][i2]-max_offset_x),(int)(res[1][i2]-max_offset_y));
			}

		}
//转为位数据
	printf("\n\n");
	for(int i1=0;i1<map_size_y;i1++){//y
		for(int i2=0;i2<map_size_x;i2++){//x
			if(i1<8){//第一行
				dis_ok[i2]|=(trans[i1][15-i2])!=0 ? 1<<i1:0;
			} else{//第二行,只有前
				dis_ok[i2+16]|=(trans[i1][15-i2])!=0 ? 1<<(i1-8):0;
			}
		}
	}
	//打印
	for(int i1=0;i1<map_size_y;i1++){
		for(int i2=0;i2<map_size_x;i2++){
			
			if(i1<map_size_y/2){//第一行
				printf("%c ",(dis_ok[i2]&(1<<i1))>0 ? '*':'.');
//				dis_ok[i2]|=(trans[i1][11-i2])!=0 ? 1<<i1:0;
			} else{//第二行,只有前
				printf("%c ",(dis_ok[i2+map_size_x]&(1<<(i1-8)))>0 ? '*':'.');
//				dis_ok[i2+12]|=(trans[i1][11-i2])!=0 ? 1<<(i1-12):0;
			}
		}
		printf("\n");
	}
	
	return 0;
	
}

代码也上传了仓库,STM32F072:opencaneve: 开源STM32HAL ESP8266 ESP32 python Android Windows把我学习到的以及找到的可以用的代码分享出来python记录打卡信息 ESP32蓝牙鼠标 开源windows串口助手 - Gitee.com

C语言:opencaneve: 开源STM32HAL ESP8266 ESP32 python Android Windows把我学习到的以及找到的可以用的代码分享出来python记录打卡信息 ESP32蓝牙鼠标 开源windows串口助手 - Gitee.com

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山间朝暮-CanEve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值