在之前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